From 6e512b9304a38e0a37bc63434afb2b8a397c0a21 Mon Sep 17 00:00:00 2001 From: Alvaro Sanchez-Leon Date: Mon, 31 May 2010 19:22:58 +0000 Subject: [PATCH] --- org.eclipse.linuxtools.lttng.ui/.classpath | 7 + org.eclipse.linuxtools.lttng.ui/.project | 28 + .../META-INF/MANIFEST.MF | 18 + .../build.properties | 7 + .../icons/LTTng.png | Bin 0 -> 1566 bytes .../icons/control_flow_view.gif | Bin 0 -> 215 bytes .../icons/control_view.gif | Bin 0 -> 152 bytes .../icons/events_view.gif | Bin 0 -> 97 bytes .../icons/garland16.png | Bin 0 -> 631 bytes .../icons/garland32.png | Bin 0 -> 1566 bytes .../icons/histogram.gif | Bin 0 -> 174 bytes .../icons/project_view.gif | Bin 0 -> 144 bytes .../icons/resources_view.gif | Bin 0 -> 101 bytes .../icons/statistics_view.gif | Bin 0 -> 343 bytes .../icons/time_frame_view.gif | Bin 0 -> 368 bytes .../plugin.properties | 28 + org.eclipse.linuxtools.lttng.ui/plugin.xml | 416 +++++++ .../linuxtools/lttng/ui/LTTngUiPlugin.java | 65 + .../linuxtools/lttng/ui/TraceDebug.java | 132 ++ .../ui/model/trange/ITimeRangeComponent.java | 43 + .../lttng/ui/model/trange/ItemContainer.java | 53 + .../ui/model/trange/TimeRangeComponent.java | 93 ++ .../ui/model/trange/TimeRangeComposite.java | 205 +++ .../lttng/ui/model/trange/TimeRangeEvent.java | 156 +++ .../model/trange/TimeRangeEventProcess.java | 222 ++++ .../model/trange/TimeRangeEventResource.java | 176 +++ .../trange/TimeRangeResourceFactory.java | 248 ++++ .../model/trange/TimeRangeViewerProvider.java | 229 ++++ .../lttng/ui/views/PerspectiveFactory.java | 113 ++ .../ui/views/common/AbsTRangeUpdate.java | 63 + .../ui/views/common/AbsTimeUpdateView.java | 669 ++++++++++ .../lttng/ui/views/common/ParamsUpdater.java | 262 ++++ .../lttng/ui/views/control/ControlView.java | 52 + .../ui/views/controlflow/ControlFlowView.java | 1094 +++++++++++++++++ .../lttng/ui/views/controlflow/Messages.java | 33 + .../evProcessor/AbsFlowTRangeUpdate.java | 214 ++++ .../evProcessor/FlowAfterUpdateHandlers.java | 380 ++++++ .../evProcessor/FlowBeforeUpdateHandlers.java | 390 ++++++ .../FlowEventToHandlerFactory.java | 177 +++ .../evProcessor/FlowFinishUpdateHandler.java | 109 ++ .../ui/views/controlflow/messages.properties | 26 + .../controlflow/model/FlowModelFactory.java | 51 + .../model/FlowProcessContainer.java | 251 ++++ .../lttng/ui/views/events/EventsView.java | 133 ++ .../histogram/ChildrenHistogramCanvas.java | 48 + .../ui/views/histogram/HistogramCanvas.java | 369 ++++++ .../HistogramCanvasControlListener.java | 63 + .../HistogramCanvasFocusListener.java | 58 + .../histogram/HistogramCanvasKeyListener.java | 95 ++ .../HistogramCanvasMouseListener.java | 233 ++++ .../HistogramCanvasPaintListener.java | 167 +++ .../ui/views/histogram/HistogramConstant.java | 172 +++ .../ui/views/histogram/HistogramContent.java | 785 ++++++++++++ .../ui/views/histogram/HistogramElement.java | 27 + .../ui/views/histogram/HistogramRequest.java | 237 ++++ .../histogram/HistogramSelectedWindow.java | 212 ++++ .../ui/views/histogram/HistogramView.java | 936 ++++++++++++++ .../histogram/ParentHistogramCanvas.java | 173 +++ .../ParentHistogramCanvasPaintListener.java | 144 +++ .../ui/views/histogram/TimeTextGroup.java | 476 +++++++ .../ui/views/project/LTTngProjectNature.java | 60 + .../lttng/ui/views/project/ProjectView.java | 211 ++++ .../views/project/dialogs/AddTraceWizard.java | 94 ++ .../project/dialogs/AddTraceWizardPage.java | 83 ++ .../dialogs/DialogTraceContentProvider.java | 51 + .../dialogs/DialogTraceLabelProvider.java | 50 + .../project/dialogs/ImportTraceWizard.java | 117 ++ .../dialogs/ImportTraceWizardPage.java | 342 ++++++ .../project/dialogs/NewExperimentDialog.java | 335 +++++ .../dialogs/NewProjectMainWizardPage.java | 32 + .../project/dialogs/NewProjectWizard.java | 147 +++ .../project/dialogs/TraceErrorDialog.java | 135 ++ .../project/handlers/CloseProjectHandler.java | 95 ++ .../handlers/DeleteExperimentHandler.java | 105 ++ .../handlers/DeleteProjectHandler.java | 104 ++ .../project/handlers/DeleteTraceHandler.java | 105 ++ .../project/handlers/ImportTraceHandler.java | 123 ++ .../handlers/NewExperimentHandler.java | 117 ++ .../project/handlers/NewProjectHandler.java | 105 ++ .../handlers/OpenExperimentHandler.java | 100 ++ .../project/handlers/OpenProjectHandler.java | 95 ++ .../project/handlers/OpenTraceHandler.java | 75 ++ .../project/handlers/RefreshHandler.java | 98 ++ .../handlers/RenameExperimentHandler.java | 75 ++ .../handlers/RenameProjectHandler.java | 93 ++ .../project/handlers/RenameTraceHandler.java | 75 ++ .../project/handlers/SelectTracesHandler.java | 105 ++ .../project/handlers/TraceErrorHandler.java | 61 + .../project/model/ILTTngProjectTreeNode.java | 41 + .../model/LTTngExperimentFolderNode.java | 130 ++ .../project/model/LTTngExperimentNode.java | 125 ++ .../model/LTTngProjectContentProvider.java | 52 + .../model/LTTngProjectLabelProvider.java | 140 +++ .../views/project/model/LTTngProjectNode.java | 200 +++ .../views/project/model/LTTngProjectRoot.java | 99 ++ .../project/model/LTTngProjectTreeNode.java | 82 ++ .../project/model/LTTngTraceFolderNode.java | 127 ++ .../views/project/model/LTTngTraceNode.java | 69 ++ .../lttng/ui/views/resources/Messages.java | 33 + .../ui/views/resources/ResourcesView.java | 560 +++++++++ .../evProcessor/AbsResourcesTRangeUpdate.java | 305 +++++ .../ResourcesAfterUpdateHandlers.java | 68 + .../ResourcesBeforeUpdateHandlers.java | 374 ++++++ .../ResourcesEventToHandlerFactory.java | 164 +++ .../ResourcesFinishUpdateHandler.java | 64 + .../ui/views/resources/messages.properties | 26 + .../resources/model/ResourceContainer.java | 230 ++++ .../resources/model/ResourceModelFactory.java | 52 + .../ui/views/statistics/StatisticsView.java | 655 ++++++++++ .../AbstractStatsEventHandler.java | 243 ++++ .../evProcessor/StatsModeChangeHandler.java | 44 + .../evProcessor/StatsModeEndHandler.java | 46 + .../StatsTimeCountHandlerFactory.java | 137 +++ .../evProcessor/StatsTimeCountHandlers.java | 178 +++ .../ui/views/statistics/model/Statistics.java | 22 + .../statistics/model/StatisticsTreeNode.java | 215 ++++ .../model/StatisticsTreeRootFactory.java | 73 ++ .../ui/views/timeframe/SpinnerGroup.java | 321 +++++ .../ui/views/timeframe/TimeFrameView.java | 380 ++++++ 119 files changed, 18781 insertions(+) create mode 100644 org.eclipse.linuxtools.lttng.ui/.classpath create mode 100644 org.eclipse.linuxtools.lttng.ui/.project create mode 100644 org.eclipse.linuxtools.lttng.ui/META-INF/MANIFEST.MF create mode 100644 org.eclipse.linuxtools.lttng.ui/build.properties create mode 100644 org.eclipse.linuxtools.lttng.ui/icons/LTTng.png create mode 100644 org.eclipse.linuxtools.lttng.ui/icons/control_flow_view.gif create mode 100644 org.eclipse.linuxtools.lttng.ui/icons/control_view.gif create mode 100644 org.eclipse.linuxtools.lttng.ui/icons/events_view.gif create mode 100644 org.eclipse.linuxtools.lttng.ui/icons/garland16.png create mode 100644 org.eclipse.linuxtools.lttng.ui/icons/garland32.png create mode 100644 org.eclipse.linuxtools.lttng.ui/icons/histogram.gif create mode 100644 org.eclipse.linuxtools.lttng.ui/icons/project_view.gif create mode 100644 org.eclipse.linuxtools.lttng.ui/icons/resources_view.gif create mode 100644 org.eclipse.linuxtools.lttng.ui/icons/statistics_view.gif create mode 100644 org.eclipse.linuxtools.lttng.ui/icons/time_frame_view.gif create mode 100644 org.eclipse.linuxtools.lttng.ui/plugin.properties create mode 100644 org.eclipse.linuxtools.lttng.ui/plugin.xml create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/LTTngUiPlugin.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/TraceDebug.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/ITimeRangeComponent.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/ItemContainer.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/TimeRangeComponent.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/TimeRangeComposite.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/TimeRangeEvent.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/TimeRangeEventProcess.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/TimeRangeEventResource.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/TimeRangeResourceFactory.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/TimeRangeViewerProvider.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/PerspectiveFactory.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/common/AbsTRangeUpdate.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/common/AbsTimeUpdateView.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/common/ParamsUpdater.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/control/ControlView.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/ControlFlowView.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/Messages.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/evProcessor/AbsFlowTRangeUpdate.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/evProcessor/FlowAfterUpdateHandlers.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/evProcessor/FlowBeforeUpdateHandlers.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/evProcessor/FlowEventToHandlerFactory.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/evProcessor/FlowFinishUpdateHandler.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/messages.properties create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/model/FlowModelFactory.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/model/FlowProcessContainer.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/events/EventsView.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/ChildrenHistogramCanvas.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramCanvas.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramCanvasControlListener.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramCanvasFocusListener.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramCanvasKeyListener.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramCanvasMouseListener.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramCanvasPaintListener.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramConstant.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramContent.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramElement.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramRequest.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramSelectedWindow.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramView.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/ParentHistogramCanvas.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/ParentHistogramCanvasPaintListener.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/TimeTextGroup.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/LTTngProjectNature.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/ProjectView.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/AddTraceWizard.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/AddTraceWizardPage.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/DialogTraceContentProvider.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/DialogTraceLabelProvider.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/ImportTraceWizard.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/ImportTraceWizardPage.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/NewExperimentDialog.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/NewProjectMainWizardPage.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/NewProjectWizard.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/TraceErrorDialog.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/CloseProjectHandler.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/DeleteExperimentHandler.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/DeleteProjectHandler.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/DeleteTraceHandler.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/ImportTraceHandler.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/NewExperimentHandler.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/NewProjectHandler.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/OpenExperimentHandler.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/OpenProjectHandler.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/OpenTraceHandler.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/RefreshHandler.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/RenameExperimentHandler.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/RenameProjectHandler.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/RenameTraceHandler.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/SelectTracesHandler.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/TraceErrorHandler.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/ILTTngProjectTreeNode.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngExperimentFolderNode.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngExperimentNode.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngProjectContentProvider.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngProjectLabelProvider.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngProjectNode.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngProjectRoot.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngProjectTreeNode.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngTraceFolderNode.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngTraceNode.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/Messages.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/ResourcesView.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/evProcessor/AbsResourcesTRangeUpdate.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/evProcessor/ResourcesAfterUpdateHandlers.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/evProcessor/ResourcesBeforeUpdateHandlers.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/evProcessor/ResourcesEventToHandlerFactory.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/evProcessor/ResourcesFinishUpdateHandler.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/messages.properties create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/model/ResourceContainer.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/model/ResourceModelFactory.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/StatisticsView.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/evProcessor/AbstractStatsEventHandler.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/evProcessor/StatsModeChangeHandler.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/evProcessor/StatsModeEndHandler.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/evProcessor/StatsTimeCountHandlerFactory.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/evProcessor/StatsTimeCountHandlers.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/model/Statistics.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/model/StatisticsTreeNode.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/model/StatisticsTreeRootFactory.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/timeframe/SpinnerGroup.java create mode 100644 org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/timeframe/TimeFrameView.java diff --git a/org.eclipse.linuxtools.lttng.ui/.classpath b/org.eclipse.linuxtools.lttng.ui/.classpath new file mode 100644 index 0000000000..64c5e31b7a --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/org.eclipse.linuxtools.lttng.ui/.project b/org.eclipse.linuxtools.lttng.ui/.project new file mode 100644 index 0000000000..b6f70c26a2 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/.project @@ -0,0 +1,28 @@ + + + org.eclipse.linuxtools.lttng.ui + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/org.eclipse.linuxtools.lttng.ui/META-INF/MANIFEST.MF b/org.eclipse.linuxtools.lttng.ui/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..dfce508378 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/META-INF/MANIFEST.MF @@ -0,0 +1,18 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %Bundle-Name +Bundle-SymbolicName: org.eclipse.linuxtools.lttng.ui;singleton:=true +Bundle-Version: 0.2.0.qualifier +Bundle-Activator: org.eclipse.linuxtools.lttng.ui.LTTngUiPlugin +Bundle-Vendor: %Bundle-Vendor +Require-Bundle: org.eclipse.ui, + org.eclipse.ui.ide, + org.eclipse.core.resources, + org.eclipse.core.filesystem, + org.eclipse.core.runtime, + org.eclipse.linuxtools.tmf;bundle-version="0.2.0", + org.eclipse.linuxtools.tmf.ui;bundle-version="0.2.0", + org.eclipse.linuxtools.lttng;bundle-version="0.2.0" +Bundle-RequiredExecutionEnvironment: J2SE-1.5 +Bundle-ActivationPolicy: lazy +Bundle-Localization: plugin diff --git a/org.eclipse.linuxtools.lttng.ui/build.properties b/org.eclipse.linuxtools.lttng.ui/build.properties new file mode 100644 index 0000000000..6b4afb7a5a --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/build.properties @@ -0,0 +1,7 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.xml,\ + icons/,\ + plugin.properties diff --git a/org.eclipse.linuxtools.lttng.ui/icons/LTTng.png b/org.eclipse.linuxtools.lttng.ui/icons/LTTng.png new file mode 100644 index 0000000000000000000000000000000000000000..3083054466a5d4602960be392b440a729a9760d9 GIT binary patch literal 1566 zcmV+(2I2XMP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L00F}Q00F}RI(wh600007bV*G`2iXW7 z5hpp}cYgo?00o{&L_t(o!@ZY#Y*Td<$3M62wziaw4KVUFURSRMN3 z$n+_50PuEraJm}t`+Wq0ezY3xRms9{bLLFw6=3_G_wo4^wv@aRyW#P+V$d5=RW;5b z91dL;z>pX6j`i7uLI~#0S{%EPlB}n>#X&F>0N`BfS)8s$bh@O=0vK!_k5XGJlC|0f z;D-bNRaN6M5D5B7PD-KO-4)PYdrfuE$85mp8x_? zRq^>dsc&impsK#UtLz%h6LEv+i*JhA_1Op1J5FD4^N1Ru!>5pvtjF8o!5{D?1TWrN zO8Jlbah`2pJ;G z{pXvrIqubB>}Nu&)l%Q|CjbV0KSmC_5ue}3q|7noOrOr+%uL>xG6nay-{xxoPApi6 zx26U~mQiGxpdp2xU~1&wns;_~HDa6R9QqU^PFG`0SRMR+FOf)ukwZrV@R&6_Hjtjq zU(Cb@AH-%hADXvl5jQMa^sY{k<=Do4hXd~~zp!!batgAivHrUX)_m~x1+!6T-_G%$ zeoHtN_fLG3V^!s(nlgB7=KU8`S}$5GlUqLj{LsxCHr$6I%i`>T145DI*gCy*sZeBD zY%Z{i84o`t05S8S83GV5K9eWTAECIlW6NGKX7o5ANg6RHd!7Kq{MjqT3Y%T5u-W7O ztJKyCMV3X)ym>E4iYyCPX(`uDoeDs(rG@0dgJZOg&6^qi+;cd#ZbhrpF(f-1Pi3Wl zSZ=Q2{EKGVk;<~qHm%!%T=NGhdOcx381%-320gac&TZC7y!!gO@C!o?#Uc`Ek|s=e z!tl|ZgI>E~!Ge76i4$l|CXAVx0EF7wNJ>wq>En+XHoHq_HkXvNT|aA9dQ(x6du&0$ zAh+9{I&k1XPtP<*r)qyw8YW{ZtL!$qmwWZHH)_}HFTPb%QL)E&YhmG%hV|>4jbp~p ze)K3omka04og}5F)4Y2(VVCQnsAJIW{sv%JZtg&UP$*(>dN^w%*mffxU`{ z*7lZ!KA1Fa?9GW2tg1@-N17TZPXq6u%!jBq~cw#amD2_!AUS$n8d>(**#+?d`Wmf3MET8QNgCF9t{& zFaUr%ii&>d2{3BZsCG$`!jdFux@peXk{cV!cfGfe Q&j0`b07*qoM6N<$f(HBa2><{9 literal 0 HcmV?d00001 diff --git a/org.eclipse.linuxtools.lttng.ui/icons/control_flow_view.gif b/org.eclipse.linuxtools.lttng.ui/icons/control_flow_view.gif new file mode 100644 index 0000000000000000000000000000000000000000..3971b507656454e819cdc8b4b6b8ce86abc51149 GIT binary patch literal 215 zcmZ?wbhEHb6krfwIKse?U)B;+wMsZ{o^ae;k+`|yiSuPr7s;e9lucbEo4QcHaHW3H zN`u0c21P5)%h%Xet+%ZPqIG_4+x*(M`L}Nk?%EODwLPq7XMFR5bN62PM#cUI0|ppS z{K>+|z#zk*0}=q)$-o+-px&3F8JE#DYthub1)?m=OgyhF@s~NfX|Or=%R%gCK9}A$2CO+Pp1hh6&gqgWgD(ks1;3HcCcZ=b?yrdjmnA) F)&Og%Q2GD> literal 0 HcmV?d00001 diff --git a/org.eclipse.linuxtools.lttng.ui/icons/control_view.gif b/org.eclipse.linuxtools.lttng.ui/icons/control_view.gif new file mode 100644 index 0000000000000000000000000000000000000000..0dc862cbd7d883765b71f5d377a3aed0d13f3645 GIT binary patch literal 152 zcmZ?wbhEHb6krfw*v!BnlDS$Sv}@D-znky>op$N_rU!pFKlpp@&HrhazaM<@|J>XE z=imN+`0YOgFfcGE{$ycfVBllW0kVN62rw|PxL&YySiPrW(^-de2MTq%rq6l7%F`5B z;i$8k#Yy1a@~|oIyrPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L00F}Q00F}RI(wh600007bV*G`2iXW7 z5hD*up)Z{P00H+&L_t(I%cYV}NYh~)ho9g0xxYziI2Rd-GIAZV;beHBR$7QWw`->crrrx{ZjwJ^M?U8KnTIrtxwYq*{RcE^e00AUZ zF&bp`rY(j}4~x1Hip8%0$g&JT;zyf}P|~^eH)Vj2xeoxCjBRz{Om>y#T`d5-3caMM zMUPb0^Dgq1MZX_wM@Orw7EGlT@?So!hZCtN#Zmzw1Rxk58A8{n;?Dh>EXTv#otwj8 zHlw=GuEBS8geUi=aQ2#6tCY#+G63lHT9T_Vs?{nB&mN%D8qjGCT=ZTi@c1dOJ)Q$n zJ`@rFxnPi;HXHHTSw35P>FV6i4vR%PYC93^G9T`#Rw^_%8PRF=-{qprnZ1>)1h6tc zFGRJ9#$=)pjndfNO~mJ$GP&KOy9Wj&MN!V3a=C9GI%t;w_89kZ`TWWH%`Q()W|qdr z!ue20C^IvKTC*ClSgfsfwp;s4f$3>+Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L00F}Q00F}RI(wh600007bV*G`2iXW7 z5hpp}cYgo?00o{&L_t(o!@ZY#Y*Td<$3M62wziaw4KVUFURSRMN3 z$n+_50PuEraJm}t`+Wq0ezY3xRms9{bLLFw6=3_G_wo4^wv@aRyW#P+V$d5=RW;5b z91dL;z>pX6j`i7uLI~#0S{%EPlB}n>#X&F>0N`BfS)8s$bh@O=0vK!_k5XGJlC|0f z;D-bNRaN6M5D5B7PD-KO-4)PYdrfuE$85mp8x_? zRq^>dsc&impsK#UtLz%h6LEv+i*JhA_1Op1J5FD4^N1Ru!>5pvtjF8o!5{D?1TWrN zO8Jlbah`2pJ;G z{pXvrIqubB>}Nu&)l%Q|CjbV0KSmC_5ue}3q|7noOrOr+%uL>xG6nay-{xxoPApi6 zx26U~mQiGxpdp2xU~1&wns;_~HDa6R9QqU^PFG`0SRMR+FOf)ukwZrV@R&6_Hjtjq zU(Cb@AH-%hADXvl5jQMa^sY{k<=Do4hXd~~zp!!batgAivHrUX)_m~x1+!6T-_G%$ zeoHtN_fLG3V^!s(nlgB7=KU8`S}$5GlUqLj{LsxCHr$6I%i`>T145DI*gCy*sZeBD zY%Z{i84o`t05S8S83GV5K9eWTAECIlW6NGKX7o5ANg6RHd!7Kq{MjqT3Y%T5u-W7O ztJKyCMV3X)ym>E4iYyCPX(`uDoeDs(rG@0dgJZOg&6^qi+;cd#ZbhrpF(f-1Pi3Wl zSZ=Q2{EKGVk;<~qHm%!%T=NGhdOcx381%-320gac&TZC7y!!gO@C!o?#Uc`Ek|s=e z!tl|ZgI>E~!Ge76i4$l|CXAVx0EF7wNJ>wq>En+XHoHq_HkXvNT|aA9dQ(x6du&0$ zAh+9{I&k1XPtP<*r)qyw8YW{ZtL!$qmwWZHH)_}HFTPb%QL)E&YhmG%hV|>4jbp~p ze)K3omka04og}5F)4Y2(VVCQnsAJIW{sv%JZtg&UP$*(>dN^w%*mffxU`{ z*7lZ!KA1Fa?9GW2tg1@-N17TZPXq6u%!jBq~cw#amD2_!AUS$n8d>(**#+?d`Wmf3MET8QNgCF9t{& zFaUr%ii&>d2{3BZsCG$`!jdFux@peXk{cV!cfGfe Q&j0`b07*qoM6N<$f(HBa2><{9 literal 0 HcmV?d00001 diff --git a/org.eclipse.linuxtools.lttng.ui/icons/histogram.gif b/org.eclipse.linuxtools.lttng.ui/icons/histogram.gif new file mode 100644 index 0000000000000000000000000000000000000000..dd2dda5caae9e3f7143589d640be5c7b878bc305 GIT binary patch literal 174 zcmZ?wbhEHb6krfwXpv^fFKdaZS|uDePdIL_NZefU#Q8F*i)2z4%BC)oOz&! zj0_C&3_1)z0J4*TRr`T@UrJ`z;ml<#y*9o3y;ZsQoJH>QKe~r^2?>;Q^L6i8Xmm2h NYW9WYCQ?ic)&OORO?dzS literal 0 HcmV?d00001 diff --git a/org.eclipse.linuxtools.lttng.ui/icons/project_view.gif b/org.eclipse.linuxtools.lttng.ui/icons/project_view.gif new file mode 100644 index 0000000000000000000000000000000000000000..4b98a62c6eed7401e6fc5d44a2b319fdf56097de GIT binary patch literal 144 zcmZ?wbhEHb6krfw*v!BnlDS$SwCmuD|Ns9V|Nn8t|I3v-n!S$n`mZQ;UQyyaC(8~f z!GHu5f3h$#FmN;IfW$y%FtFGbob+71_gjX~`5)5h0xF3*POJPp9*Uh5I`d`89Sd{T mDpsFa%+I%fXlM~*P%zM%8#eWtcG&6%MSItj?e1V;um%8#wKpgL literal 0 HcmV?d00001 diff --git a/org.eclipse.linuxtools.lttng.ui/icons/resources_view.gif b/org.eclipse.linuxtools.lttng.ui/icons/resources_view.gif new file mode 100644 index 0000000000000000000000000000000000000000..234486172ca3778924ccb8815871b43a86908777 GIT binary patch literal 101 zcmZ?wbhEHb6krfwSj4~(Q?)9gZf#og#)(Uh=X7l^ny{;E%D(^q|117vVPs%nXV75) z0+3n;X03`{cm5ezIXq=zmO0EV=;)j|&1o9DrI+%u+JzZm7b91hTuEb(dA>qHg^|G; E05nA-vj6}9 literal 0 HcmV?d00001 diff --git a/org.eclipse.linuxtools.lttng.ui/icons/statistics_view.gif b/org.eclipse.linuxtools.lttng.ui/icons/statistics_view.gif new file mode 100644 index 0000000000000000000000000000000000000000..d11c996e570dfe06518631ba3f0f1893a21f88d1 GIT binary patch literal 343 zcmZ?wbhEHb6krfwxXQrL*t=xKh671O{Rss<85L8yrmfy{NYquZUcHsQZLl+L5ymsX5t;1(-R&*|??pfS0VOjI!mCch^v`<^zJ!{>P z4F{HOI<#fqnG+Z97BS&av~iHtadMe)ow93pN}%f9pROFrWg( zpDc_F3|0&}AYqW77}!c2<`#J9NcFq9Bq=Nq5EJEITyl^ne{-M)L)J|j!E0QmE(|jL zZi<^P7AVZU958kD?pHr{W$9TxC{U_5syC^2(yS1!tT1p^V-uRdHhBu0nzKrUPLqV50y literal 0 HcmV?d00001 diff --git a/org.eclipse.linuxtools.lttng.ui/icons/time_frame_view.gif b/org.eclipse.linuxtools.lttng.ui/icons/time_frame_view.gif new file mode 100644 index 0000000000000000000000000000000000000000..c984fba7039a0465a1858a1161e7d5e1bb4c8c31 GIT binary patch literal 368 zcmZ?wbhEHb6krfwxXQp_Zy)cQP%Z1(^6=HS7w^8U+j;Eqn{Q9wetZ7zn|=NM2d}?9 zdh_kc+ix%4fBW?1TSV!^=kLG0{`l?5yKiqleS81;n_vIlk6*sU&)@&~>$my)_aD7; z`{si?`|t0+boKPZSG!)m*}s4P{7-L={d#x$|GRVl|Nm#8Hc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %wizard.description.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/LTTngUiPlugin.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/LTTngUiPlugin.java new file mode 100644 index 0000000000..460ed6a8f6 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/LTTngUiPlugin.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui; + +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class LTTngUiPlugin extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "org.eclipse.linuxtools.lttng.ui"; + + // The shared instance + private static LTTngUiPlugin plugin; + + /** + * The constructor + */ + public LTTngUiPlugin() { + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + TraceDebug.init(); + plugin = this; + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + @Override + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static LTTngUiPlugin getDefault() { + return plugin; + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/TraceDebug.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/TraceDebug.java new file mode 100644 index 0000000000..c0b24d242d --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/TraceDebug.java @@ -0,0 +1,132 @@ +package org.eclipse.linuxtools.lttng.ui; + +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.eclipse.core.runtime.ILog; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Plugin; +import org.eclipse.core.runtime.Status; + +public class TraceDebug { + static boolean DEBUG = false; + static boolean INFO = false; + static boolean WARN = false; + + private static Plugin plugin = LTTngUiPlugin.getDefault(); + private static String pluginID = LTTngUiPlugin.PLUGIN_ID; + private static SimpleDateFormat stimeformat = new SimpleDateFormat( + "HH:mm:ss:SSS"); + + public static void init() { + // Update Trace configuration options + String debugTrace = Platform.getDebugOption(pluginID + "/debug"); + String infoTrace = Platform.getDebugOption(pluginID + "/info"); + String warnTrace = Platform.getDebugOption(pluginID + "/warn"); + + if (debugTrace != null) { + DEBUG = (new Boolean(debugTrace)).booleanValue(); + } + + if (infoTrace != null) { + INFO = (new Boolean(infoTrace)).booleanValue(); + } + + if (warnTrace != null) { + WARN = (new Boolean(warnTrace)).booleanValue(); + } + } + + public static void info(String message) { + if (INFO) { + ILog logger = plugin.getLog(); + logger.log(new Status(IStatus.INFO, LTTngUiPlugin.PLUGIN_ID, + IStatus.OK, message, null)); + } + } + + public static void warn(String message) { + if (WARN) { + ILog logger = plugin.getLog(); + logger.log(new Status(IStatus.WARNING, LTTngUiPlugin.PLUGIN_ID, + IStatus.WARNING, message, null)); + } + } + + public static void debug(String message) { + if (DEBUG) { + String location = getCallingLocation(); + System.out.println(location + "\n\t-> " + message); + + } + } + + public static void debug(String message, int additionalStackLines) { + if (DEBUG) { + String location = getCallingLocation(additionalStackLines); + System.out.println(location + "\n\t-> " + message); + } + } + + public static void throwException(String message) { + if (DEBUG) { + try { + triggerException(message); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + private static void triggerException(String message) throws Exception { + throw new Exception(message); + } + + private static String getCallingLocation() { + StringBuilder sb = new StringBuilder(); + sb.append(trace(Thread.currentThread().getStackTrace(), 4)); + sb.append("\n" + trace(Thread.currentThread().getStackTrace(), 3)); + return sb.toString(); + } + + private static String getCallingLocation(int numOfStackLines) { + int stackCalledFromIdx = 3; + int earliestRequested = numOfStackLines > 0 ? stackCalledFromIdx + + numOfStackLines : stackCalledFromIdx; + StringBuilder sb = new StringBuilder(); + for (int i = earliestRequested; i >= stackCalledFromIdx; i--) { + sb.append(trace(Thread.currentThread().getStackTrace(), i) + "\n"); + } + return sb.toString(); + } + + private static String trace(StackTraceElement e[], int level) { + if (e != null) { + level = level >= e.length ? e.length - 1 : level; + StackTraceElement s = e[level]; + if (s != null) { + String simpleClassName = s.getClassName(); + String[] clsNameSegs = simpleClassName.split("\\."); + if (clsNameSegs.length > 0) + simpleClassName = clsNameSegs[clsNameSegs.length - 1]; + return stimeformat.format(new Date()) + " " + simpleClassName + + "." + s.getLineNumber() + "." + s.getMethodName(); + } + } + + return null; + } + + public static boolean isDEBUG() { + return DEBUG; + } + + public static boolean isINFO() { + return INFO; + } + + public static boolean isWARN() { + return WARN; + } +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/ITimeRangeComponent.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/ITimeRangeComponent.java new file mode 100644 index 0000000000..9cb42a5978 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/ITimeRangeComponent.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.model.trange; + +/** + * The common component of the Composite related to time-range events its + * components or containers + * + * @author alvaro + * + */ +public interface ITimeRangeComponent { + + public long getStartTime(); + + public void setStartTime(long startTime); + + public long getStopTime(); + + public void setStopTime(long endTime); + + public ITimeRangeComponent getEventParent(); + + public String getName(); + + /** + * Flag to indicate if this Time Range is visible within the GUI, May not be + * visible if the duration can not be represented in one pixel + * + * @return true if visible i.e. represented at least in one pixel + */ + public boolean isVisible(); + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/ItemContainer.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/ItemContainer.java new file mode 100644 index 0000000000..89298be4f4 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/ItemContainer.java @@ -0,0 +1,53 @@ +package org.eclipse.linuxtools.lttng.ui.model.trange; + +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITmfTimeAnalysisEntry; + +public interface ItemContainer { + + /** + * Interface to add resources. + * + * @param process + */ + public abstract void addItem(T newItem); + + // ======================================================================== + // Methods + // ======================================================================== + /** + * Request a unique ID + * + * @return Integer + */ + public abstract Integer getUniqueId(); + + /** + * This method is intended for read only purposes in order to keep the + * internal data structure in Synch + * + * @return + */ + public abstract T[] readItems(); + + /** + * Clear the children information for resources related to a specific trace + * e.g. just before refreshing data with a new time range + * + * @param traceId + */ + public abstract void clearChildren(); + + /** + * Clear all resources items e.g. when a new experiment is selected + */ + public abstract void clearItems(); + + /** + * Remove the resources related to a specific trace e.g. during trace + * removal + * + * @param traceId + */ + public abstract void removeItems(String traceId); + +} \ No newline at end of file diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/TimeRangeComponent.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/TimeRangeComponent.java new file mode 100644 index 0000000000..d7a4fc2d1f --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/TimeRangeComponent.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.model.trange; + + +/** + * @author alvaro + * + */ +public abstract class TimeRangeComponent implements ITimeRangeComponent { + + // ======================================================================== + // Data + // ======================================================================= + protected Long startTime = 0L; + protected Long stopTime = Long.MAX_VALUE; + protected TimeRangeComposite eventParent = null; + private boolean visible = true; + + + + // ======================================================================== + // Constructor + // ======================================================================= + public TimeRangeComponent(Long stime, Long etime, + TimeRangeComposite eventParent) { + this.startTime = stime; + this.stopTime = etime; + this.eventParent = eventParent; + } + + // ======================================================================== + // Methods + // ======================================================================= + /** + * This method shall not be used to estimate the starting drawing point of + * the time range-event. see interface method getTime(). However this method + * can be used to retrieve the tool tip information where we need to reflect + * that the actual start of this event is unknown + * + * @param time + */ + public long getStartTime() { + return startTime.longValue(); + } + + public void setStartTime(long time) { + if (time > -1) { + startTime = time; + } + } + + public long getStopTime() { + return stopTime.longValue(); + } + + public void setStopTime(long stopTime) { + if (stopTime > -1) { + this.stopTime = stopTime; + } + } + + public ITimeRangeComponent getEventParent() { + return eventParent; + } + + public void setEventParent(TimeRangeComposite eventParent) { + this.eventParent = eventParent; + } + + public abstract String getName(); + + + public void setVisible(boolean visible) { + this.visible = visible; + } + + /* (non-Javadoc) + * @see org.eclipse.linuxtools.lttng.ui.model.trange.ITimeRangeComponent#isVisible() + */ + public boolean isVisible() { + return visible; + } +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/TimeRangeComposite.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/TimeRangeComposite.java new file mode 100644 index 0000000000..7cf42f2cd7 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/TimeRangeComposite.java @@ -0,0 +1,205 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.model.trange; + +import java.util.Vector; + +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITmfTimeAnalysisEntry; + +public class TimeRangeComposite extends TimeRangeComponent implements +ITmfTimeAnalysisEntry { + + // ======================================================================== + // Data + // ======================================================================= + /** + * Type of Composites or Containers + *

+ * PROPERTY: Refers to a sub-composite of a RESOURCE or a PROCESS e.g the + * cpu which can vary over time and can have time range events associated to + * it, and at the same time PROPERTY is associated to a Composite parent + * like a PROCESS + *

+ *

+ * PROCESS: A composite of time range events representing a Process + *

+ *

+ * RESOURCE: A composite of time range events representing a resource i.g. + * irq, softIrq, trap, bdev, cpu + *

+ * + * @author alvaro + * + */ + public static enum CompositeType { + UNKNOWN, PROPERTY, PROCESS, RESOURCE + } + + protected final Vector ChildEventLeafs = new Vector(); + protected final Vector ChildEventComposites = new Vector(); + protected Integer id = 0; + protected String name; + protected String groupName = ""; + protected String className = ""; + protected CompositeType contType = CompositeType.UNKNOWN; + protected Long next_good_time = -1L; + /*Time of first event which trigger the creation of this local resource */ + protected Long insertionTime = -1L; + + // ======================================================================== + // Constructors + // ======================================================================= + public TimeRangeComposite(Integer id, Long stime, Long etime, String name, + CompositeType type, long insertionTime) { + super(stime, etime, null); + this.id = id; + this.name = name; + contType = type; + this.insertionTime = insertionTime; + // Adjust the first good drawing position to the event time creating this resource + next_good_time = insertionTime; + } + + public TimeRangeComposite(Integer id, Long stime, Long etime, String name, + String groupName, String className, CompositeType type, + long insertionTime) { + this(id, stime, etime, name, type, insertionTime); + this.groupName = groupName; + this.className = className; + } + + // ======================================================================== + // Methods + // ======================================================================= + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeComponent#getName() + */ + @Override + public String getName() { + return name; + } + + /** + * @param name + */ + public void setName(String name) { + this.name = name; + } + + /* + * (non-Javadoc) + * + * @seeorg.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model. + * ITmfTimeAnalysisEntry#getGroupName() + */ + public String getGroupName() { + return groupName; + } + + /** + * @param groupName + */ + public void setGroupName(String groupName) { + this.groupName = groupName; + } + + /* + * (non-Javadoc) + * + * @seeorg.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model. + * ITmfTimeAnalysisEntry#getId() + */ + public int getId() { + return id; + } + + /** + * @param id + */ + public void setId(int id) { + this.id = id; + } + + /** + * @return + */ + public String getClassName() { + return className; + } + + /** + * @param className + */ + public void setClassName(String className) { + this.className = className; + } + + /* + * (non-Javadoc) + * + * @seeorg.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model. + * ITmfTimeAnalysisEntry#getTraceEvents() + */ + @SuppressWarnings("unchecked") + public Vector getTraceEvents() { + return ChildEventLeafs; + } + + /** + * @return + */ + public Vector getChildEventComposites() { + return ChildEventComposites; + } + + /** + * Represents the time where the next time range can start the drawing i.e. + * right after previous time range. + * + * @return + */ + public long getNext_good_time() { + return next_good_time; + } + + /** + * Represents the time where the next time range can start the drawing i.e. + * right after previous time range. + * + * @param nextGoodTime + */ + public void setNext_good_time(long nextGoodTime) { + next_good_time = nextGoodTime; + } + + /** + * Reset this resource to the construction state + */ + public void reset() { + getChildEventComposites().clear(); + getTraceEvents().clear(); + next_good_time = insertionTime; + } + + /** + * Event Time reflecting the creation of this local resource e.g. at Reception of Fork, etc. + * + * @return + */ + public long getInsertionTime() { + return insertionTime; + } +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/TimeRangeEvent.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/TimeRangeEvent.java new file mode 100644 index 0000000000..acf57fbcbc --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/TimeRangeEvent.java @@ -0,0 +1,156 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.model.trange; + +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITimeEvent; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITmfTimeAnalysisEntry; + +/** + * @author alvaro + * + */ +public class TimeRangeEvent extends TimeRangeComponent implements ITimeEvent { + // ======================================================================= + // Data + // ======================================================================= + TimeRangeComposite parent = null; + + public static enum Type { + UNKNOWN, PROPERTY, PROCESS_MODE, BDEV_MODE, TRAP_MODE, SOFT_IRQ_MODE, IRQ_MODE, CPU_MODE + } + + protected Type eventType = Type.UNKNOWN; + protected String stateMode = ""; + + // ======================================================================= + // Constructors + // ======================================================================= + /** + * @param stime + * Event Start Time (may be unknown) + * @param etime + * Event EndTime (may be unknown) + * @param eventParent + * @param type + * @param duration + */ + public TimeRangeEvent(Long stime, Long etime, + TimeRangeComposite eventParent, Type type, String stateMode) { + super(stime, etime, eventParent); + + this.eventType = type; + this.stateMode = stateMode; + } + + // ======================================================================= + // Methods + // ======================================================================= + + // @Override + /* + * (non-Javadoc) + * + * @see + * org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITimeEvent#getTime + * () + */ + public long getTime() { + // The value provided by this method is used to start drawing the + // time-range, + // so a null value shall not be provided. + // If the actual start time is unknown then use the start of the Trace + // as the + // starting reference point. + if (startTime == null) { + return eventParent.getStartTime(); + } + return startTime; + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITimeEvent#getEntry + * () + */ + public ITmfTimeAnalysisEntry getEntry() { + return parent; + } + + /** + * return the duration between end and start time , if the start time or end + * time are unknown, use the Trace start and End times to estimate it, this + * value will be used to draw the time range and need to provide a valid + * time width. + * + * @return the duration + */ + /* + * (non-Javadoc) + * + * @seeorg.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITimeEvent# + * getDuration() + */ + public long getDuration() { + long duration = -1; + long endT = (stopTime == null) ? parent.getStopTime() : stopTime; + long startT = (startTime == null) ? parent.getStartTime() : startTime; + + if (endT > startT) { + return stopTime - startTime; + } + return duration; + } + + /** + * @return + */ + public String getStateMode() { + return stateMode; + } + + /** + * @param stateMode + */ + public void setStateMode(String stateMode) { + if (stateMode != null) { + this.stateMode = stateMode; + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.linuxtools.lttng.ui.model.ITimeRangeComponent#getName() + */ + @Override + public String getName() { + return stateMode; + } + + /** + * @return + */ + public Type getEventType() { + return eventType; + } + + /** + * @param eventType + */ + public void setEventType(Type eventType) { + this.eventType = eventType; + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/TimeRangeEventProcess.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/TimeRangeEventProcess.java new file mode 100644 index 0000000000..bceef5f6cd --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/TimeRangeEventProcess.java @@ -0,0 +1,222 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.model.trange; + +public class TimeRangeEventProcess extends TimeRangeComposite implements + Comparable { + // ======================================================================== + // Data + // ======================================================================= + // GUI information + private Long pid = 0L; + private Long tgid = 0L; + private Long ppid = 0L; + private Long creationTime = 0L; + private String traceID = ""; + private String processType = "User"; // Kernel or user thread + private Long cpu = 0L; + private String brand = ""; + + // ======================================================================== + // Constructor + // ======================================================================= + /** + * @param id + * @param name + * @param sTime + * normally set to the Trace start time + * @param stopTime + * normally set to the Trace end time + * @param groupName + * @param className + */ + public TimeRangeEventProcess(int id, String name, long startTime, + long stopTime, String groupName, String className, Long cpu, + long insertionTime) { + + super(id, startTime, stopTime, name, CompositeType.PROCESS, + insertionTime); + this.cpu = cpu; + } + + // ======================================================================== + // Methods + // ======================================================================= + + + /** + * Interface to add children to this process + * + * @param newEvent + */ + public void addChildren(TimeRangeEvent newEvent) { + if ((newEvent != null)) { + this.ChildEventLeafs.add(newEvent); + } + } + + /** + * @return + */ + public Long getPid() { + return pid; + } + + /** + * @param pid + */ + public void setPid(Long pid) { + this.pid = pid; + } + + /** + * @return + */ + public Long getTgid() { + return tgid; + } + + /** + * @param tgid + */ + public void setTgid(Long tgid) { + this.tgid = tgid; + } + + /** + * @return + */ + public Long getPpid() { + return ppid; + } + + /** + * @param ppid + */ + public void setPpid(Long ppid) { + this.ppid = ppid; + } + + /** + * @return + */ + public Long getCreationTime() { + return creationTime; + } + + /** + * @param creationTime + */ + public void setCreationTime(Long creationTime) { + this.creationTime = creationTime; + } + + /** + * @return + */ + public String getTraceID() { + return traceID; + } + + /** + * @param traceID + */ + public void setTraceID(String traceID) { + if (traceID != null) { + this.traceID = traceID; + } else { + this.traceID = ""; + } + } + + /** + * @return + */ + public String getProcessType() { + return processType; + } + + /** + * @param processType + */ + public void setProcessType(String processType) { + if (processType != null) { + this.processType = processType; + } + } + + /** + * @return + */ + public Long getCpu() { + return cpu; + } + + /** + * @param cpu + */ + public void setCpu(Long cpu) { + if (cpu != null) { + this.cpu = cpu; + } else { + cpu = 0L; + } + } + + /** + * @return + */ + public String getBrand() { + return brand; + } + + /** + * @param brand + */ + public void setBrand(String brand) { + if (brand != null) { + this.brand = brand; + } else { + brand = ""; + } + } + + /* + * (non-Javadoc) + * + * @see java.lang.Comparable#compareTo(java.lang.Object) + */ + public int compareTo(TimeRangeEventProcess process) { + if (process != null) { + int result = 0; + // Compare by trace first + String anotherTraceId = process.getTraceID(); + result = traceID.compareTo(anotherTraceId); + if (result != 0) { + return result; + } + + // Then by CPU + Long anotherCpu = process.getCpu(); + result = cpu.compareTo(anotherCpu); + if (result != 0) { + return result; + } + + // finally Compare by pid + Long anotherPid = process.getPid(); + return pid.compareTo(anotherPid); + } + + return 0; + } +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/TimeRangeEventResource.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/TimeRangeEventResource.java new file mode 100644 index 0000000000..b7a417ae9a --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/TimeRangeEventResource.java @@ -0,0 +1,176 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.model.trange; + +import org.eclipse.linuxtools.lttng.state.model.LttngTraceState; + +/** + * @author alvaro + * + */ +public abstract class TimeRangeEventResource extends TimeRangeComposite + implements + Comparable { + + // ======================================================================== + // Data + // ======================================================================= + public static enum ResourceTypes { + UNKNOWN, IRQ, TRAP, SOFT_IRQ, BDEV, CPU + } + + private ResourceTypes type = ResourceTypes.UNKNOWN; + private Long resourceId = null; + + // ======================================================================== + // Constructor + // ======================================================================= + /** + * Constructor
+ * + * @param newId Id used by the UI + * @param newStartTime normally set to the Trace start time + * @param newStopTime normally set to the Trace end time + * @param newName the name of this resource + * @param newGroupName the group name of this resource. Should be same as the traceId + * @param newClassName the classname of this resource. + * @param newType the type of the resource, as defined in the ResourceTypes enum + * @param newResourceId the resourceId, unique id identifying this resource + * + */ + public TimeRangeEventResource(int newId, long newStartTime, + long newStopTime, String newName, String newGroupName, + String newClassName, ResourceTypes newType, Long newResourceId, + long insertionTime) { + + super(newId, newStartTime, newStopTime, newName, newGroupName, + newClassName, CompositeType.RESOURCE, insertionTime); + + type = newType; + resourceId = newResourceId; + } + + // ======================================================================== + // Methods + // ======================================================================= + + /** + * Interface to add children to this resource + * + * @param newEvent + */ + public void addChildren(TimeRangeEvent newEvent) { + if ((newEvent != null)) { + this.ChildEventLeafs.add(newEvent); + } + } + + /** + * @return + */ + public Long getResourceId() { + return resourceId; + } + + /** + * @param newResId + */ + public void setResourceId(Long newResId) { + this.resourceId = newResId; + } + + /** + * @return + */ + public ResourceTypes getType() { + return type; + } + + /** + * @param type + */ + public void setType(ResourceTypes type) { + this.type = type; + } + + /** + * Getter for traceId.
+ * Note : traceId and groupName are the same for EventResource + * + * @return String + */ + public String getTraceId() { + return groupName; + } + + /** + * Getter for traceId.
+ * Note : traceId and groupName are the same for EventResource + * + * @return String + */ + public void setTraceId(String traceId) { + this.groupName = traceId; + } + + // @Override + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return getResourceId().toString() + ":" + getTraceId().toString() + ":" + + getType().toString(); + } + + /** + * Compare function to implement Comparable
+ *
+ * Compare by traceId THEN IF EQUAL by resourceType THEN IF EQUAL by + * resourceId + * + * @param comparedResource + * The resource to compare to + * + * @return int 0 if equals, negative number if "smaller", positive if + * "bigger". + */ + // @Override + public int compareTo(TimeRangeEventResource comparedResource) { + int returnedValue = 0; + + if (comparedResource != null) { + // Compare by trace id first + returnedValue = this.getTraceId().compareTo( + comparedResource.getTraceId()); + + // If same, compare by resourceName + if (returnedValue == 0) { + returnedValue = this.getName().compareTo( + comparedResource.getName()); + + // Finally, if same, compare by ResourceId + if (returnedValue == 0) { + returnedValue = this.getResourceId().compareTo( + comparedResource.getResourceId()); + } + } + + } + + return returnedValue; + } + + public abstract String getStateMode(LttngTraceState traceState); +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/TimeRangeResourceFactory.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/TimeRangeResourceFactory.java new file mode 100644 index 0000000000..94f2340f44 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/TimeRangeResourceFactory.java @@ -0,0 +1,248 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.model.trange; + + +import org.eclipse.linuxtools.lttng.state.StateStrings; +import org.eclipse.linuxtools.lttng.state.model.LttngIRQState; +import org.eclipse.linuxtools.lttng.state.model.LttngTraceState; +import org.eclipse.linuxtools.lttng.state.model.LttngTrapState; +import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEventResource.ResourceTypes; + +/** + * Creates Resources with custom implementation to obtain its corresponding + * state mode + *

+ * The state mode resolution is needed at the end of a data request, as well as + * in the before and after handlers + *

+ * + * @author alvaro + * + */ +public class TimeRangeResourceFactory { + // ======================================================================== + // Data + // ======================================================================= + private static TimeRangeResourceFactory instance = null; + + // ======================================================================== + // Create instance + // ======================================================================= + /** + * Factory singleton + * + * @return + */ + public static TimeRangeResourceFactory getInstance() { + if (instance == null) { + instance = new TimeRangeResourceFactory(); + } + return instance; + } + + // ======================================================================== + // Public methods + // ======================================================================= + public TimeRangeEventResource createResource(int newId, long newStartTime, + long newStopTime, String newName, String newGroupName, + String newClassName, ResourceTypes type, Long newResourceId, + long insertionTime) { + + TimeRangeEventResource resource = null; + switch (type) { + case CPU: + resource = createCpuResource(newId, newStartTime, newStopTime, + newName, newGroupName, newClassName, type, newResourceId, + insertionTime); + break; + case IRQ: + resource = createIrqResource(newId, newStartTime, newStopTime, + newName, newGroupName, newClassName, type, newResourceId, + insertionTime); + break; + case SOFT_IRQ: + resource = createSoftIrqResource(newId, newStartTime, newStopTime, + newName, newGroupName, newClassName, type, newResourceId, + insertionTime); + break; + case TRAP: + resource = createTrapResource(newId, newStartTime, newStopTime, + newName, newGroupName, newClassName, type, newResourceId, + insertionTime); + break; + case BDEV: + resource = createBdevResource(newId, newStartTime, newStopTime, + newName, newGroupName, newClassName, type, newResourceId, + insertionTime); + break; + default: + break; + } + + return resource; + } + + // ======================================================================== + // Private methods + // ======================================================================= + private TimeRangeEventResource createIrqResource(int newId, + long newStartTime, long newStopTime, String newName, + String newGroupName, String newClassName, ResourceTypes newType, + Long newResourceId, long insertionTime) { + + TimeRangeEventResource resource = new TimeRangeEventResource(newId, + newStartTime, newStopTime, newName, newGroupName, newClassName, + newType, newResourceId, insertionTime) { + + @Override + public String getStateMode(LttngTraceState traceSt) { + LttngIRQState irqState = traceSt.getIrq_states().get( + getResourceId()); + String statemode = ""; + if (irqState != null) { + statemode = irqState.peekFromIrqStack().getInName(); + } + + return statemode; + } + }; + + return resource; + } + + private TimeRangeEventResource createTrapResource(int newId, + long newStartTime, long newStopTime, String newName, + String newGroupName, String newClassName, ResourceTypes newType, + Long newResourceId, long insertionTime) { + + TimeRangeEventResource resource = new TimeRangeEventResource(newId, + newStartTime, newStopTime, newName, newGroupName, newClassName, + newType, newResourceId, insertionTime) { + + @Override + public String getStateMode(LttngTraceState traceSt) { + // Determine the trap state. + String trapStateMode = ""; + LttngTrapState ts = traceSt.getTrap_states().get(getResourceId()); + + // *** Note : + // Ts might not have been created yet. + // This is because the state system will be updated next to this before hook + // It should be correct to create it here as Busy + // (traps are created with running++ so it wont be idle) + if ( ts != null ) { + Long trapState = ts.getRunning(); + + if (trapState == 0) { + trapStateMode = StateStrings.TrapMode.LTTV_TRAP_IDLE.getInName(); + } else { + trapStateMode = StateStrings.TrapMode.LTTV_TRAP_BUSY.getInName(); + } + } + else { + trapStateMode = StateStrings.TrapMode.LTTV_TRAP_BUSY.getInName(); + } + + return trapStateMode; + } + }; + + return resource; + } + + private TimeRangeEventResource createSoftIrqResource(int newId, + long newStartTime, long newStopTime, String newName, + String newGroupName, String newClassName, ResourceTypes newType, + Long newResourceId, long insertionTime) { + + TimeRangeEventResource resource = new TimeRangeEventResource(newId, + newStartTime, newStopTime, newName, newGroupName, newClassName, + newType, newResourceId, insertionTime) { + + @Override + public String getStateMode(LttngTraceState traceSt) { + // Get the resource id. + Long softIrqId = getResourceId(); + // Get the resource state mode + long running = traceSt.getSoft_irq_states().get(softIrqId) + .getRunning().longValue(); + long pending = traceSt.getSoft_irq_states().get(softIrqId) + .getPending().longValue(); + + String softIrqStateMode; + if (running > 0) { + softIrqStateMode = StateStrings.SoftIRQMode.LTTV_SOFT_IRQ_BUSY + .getInName(); + } else if (pending > 0) { + softIrqStateMode = StateStrings.SoftIRQMode.LTTV_SOFT_IRQ_PENDING + .getInName(); + } else { + softIrqStateMode = StateStrings.SoftIRQMode.LTTV_SOFT_IRQ_IDLE + .getInName(); + } + + return softIrqStateMode; + } + + }; + + return resource; + } + + private TimeRangeEventResource createBdevResource(int newId, + long newStartTime, long newStopTime, String newName, + String newGroupName, String newClassName, ResourceTypes newType, + Long newResourceId, long insertionTime) { + + TimeRangeEventResource resource = new TimeRangeEventResource(newId, + newStartTime, newStopTime, newName, newGroupName, newClassName, + newType, newResourceId, insertionTime) { + + @Override + public String getStateMode(LttngTraceState traceSt) { + // Get the resource state mode + String bdevStateMode = traceSt.getBdev_states().get( + getResourceId()).peekFromBdevStack().getInName(); + + return bdevStateMode; + } + + }; + + return resource; + } + + private TimeRangeEventResource createCpuResource(int newId, + long newStartTime, long newStopTime, String newName, + String newGroupName, String newClassName, ResourceTypes newType, + Long newResourceId, long insertionTime) { + + TimeRangeEventResource resource = new TimeRangeEventResource(newId, + newStartTime, newStopTime, newName, newGroupName, newClassName, + newType, newResourceId, insertionTime) { + + @Override + public String getStateMode(LttngTraceState traceSt) { + // Get the resource state mode + String cpuStateMode = traceSt.getCpu_states().get( + getResourceId()) + .peekFromCpuStack().getInName(); + + return cpuStateMode; + } + + }; + + return resource; + } +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/TimeRangeViewerProvider.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/TimeRangeViewerProvider.java new file mode 100644 index 0000000000..c0716278d7 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/model/trange/TimeRangeViewerProvider.java @@ -0,0 +1,229 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.model.trange; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.linuxtools.lttng.state.StateStrings.BdevMode; +import org.eclipse.linuxtools.lttng.state.StateStrings.CpuMode; +import org.eclipse.linuxtools.lttng.state.StateStrings.ExecutionMode; +import org.eclipse.linuxtools.lttng.state.StateStrings.IRQMode; +import org.eclipse.linuxtools.lttng.state.StateStrings.ProcessStatus; +import org.eclipse.linuxtools.lttng.state.StateStrings.SoftIRQMode; +import org.eclipse.linuxtools.lttng.state.StateStrings.TrapMode; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeAnalysisProvider; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITimeEvent; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITmfTimeAnalysisEntry; + +public class TimeRangeViewerProvider extends TmfTimeAnalysisProvider { + // ======================================================================== + // Data + // ======================================================================= + Map procStateToColor = new HashMap( + 16); + Map bdevStateToColor = new HashMap( + 4); + Map softIrqStateToColor = new HashMap( + 4); + Map trapStateToColor = new HashMap( + 4); + Map irqStateToColor = new HashMap(4); + Map cpuStateToColor = new HashMap(8); + + // ======================================================================== + // Constructors + // ======================================================================= + public TimeRangeViewerProvider() { + // Fill the statemode to color maps + fillProcessStateToColor(); + fillBdevStateToColor(); + fillSoftIRQStateToColor(); + fillTrapStateToColor(); + fillIrqStateToColor(); + fillCpuStateToColor(); + } + + // ======================================================================== + // Methods + // ======================================================================= + @Override + public StateColor getEventColor(ITimeEvent event) { + StateColor retColor = null; + + if (event instanceof TimeRangeEvent) { + TimeRangeEvent devent = (TimeRangeEvent) event; + String stateMode = devent.getStateMode(); + switch (devent.getEventType()) { + case PROCESS_MODE: + retColor = procStateToColor.get(stateMode); + break; + case BDEV_MODE: + retColor = bdevStateToColor.get(stateMode); + break; + case IRQ_MODE: + retColor = irqStateToColor.get(stateMode); + break; + case SOFT_IRQ_MODE: + retColor = softIrqStateToColor.get(stateMode); + break; + case CPU_MODE: + retColor = cpuStateToColor.get(stateMode); + break; + case TRAP_MODE: + retColor = trapStateToColor.get(stateMode); + break; + } + } + + if (retColor == null) { + return StateColor.MAGENTA3; + } + return retColor; + } + + /* (non-Javadoc) + * @see org.eclipse.linuxtools.tmf.ui.widgets.timeAnalysis.api.TsfTmAbstractImplProvider#getStateName(org.eclipse.linuxtools.tmf.ui.widgets.timeAnalysis.api.TsfTmAbstractImplProvider.StateColor) + */ + @Override + public String getStateName(StateColor color) { + //Override to multiple instances of the widget, the same color can have multiple meanings + return "Not mapped"; + } + + @Override + public Map getEventHoverToolTipInfo(ITimeEvent revent) { + Map toolTipEventMsgs = new HashMap(); + //if the selected resource is a Process, add the Process type to the tool tip + if (revent instanceof TimeRangeComponent) { + ITimeRangeComponent parent = ((TimeRangeComponent) revent) + .getEventParent(); + if (parent != null && parent instanceof TimeRangeEventProcess) { + TimeRangeEventProcess localProcess = (TimeRangeEventProcess) parent; + toolTipEventMsgs.put("Process Type", localProcess + .getProcessType()); + } + } + + return toolTipEventMsgs; + } + + @Override + public String getEventName(ITimeEvent event, boolean upper, boolean extInfo) { + String name = null; + //The relevant event name for the time range is the actual state mode + if (event instanceof TimeRangeEvent) { + TimeRangeEvent devent = (TimeRangeEvent) event; + StringBuilder sb = new StringBuilder(devent.getStateMode()); + name = sb.toString(); + } + + if (name == null) { + return "Unknown"; + } + return name; + } + + @Override + public String getTraceClassName(ITmfTimeAnalysisEntry trace) { + String name = ""; + if (trace instanceof TimeRangeComposite) { + TimeRangeComposite dTrace = (TimeRangeComposite) trace; + name = dTrace.getClassName(); + } + return name; + } + + private void fillCpuStateToColor() { + cpuStateToColor.put(CpuMode.LTTV_CPU_UNKNOWN.getInName(), + StateColor.BLACK); + cpuStateToColor.put(CpuMode.LTTV_CPU_IDLE.getInName(), StateColor.GRAY); + cpuStateToColor.put(CpuMode.LTTV_CPU_BUSY.getInName(), + StateColor.LIGHT_BLUE); + cpuStateToColor + .put(CpuMode.LTTV_CPU_IRQ.getInName(), StateColor.ORANGE); + cpuStateToColor.put(CpuMode.LTTV_CPU_SOFT_IRQ.getInName(), + StateColor.PURPLE1); + cpuStateToColor.put(CpuMode.LTTV_CPU_TRAP.getInName(), StateColor.GOLD); + } + + private void fillIrqStateToColor() { + irqStateToColor.put(IRQMode.LTTV_IRQ_UNKNOWN.getInName(), + StateColor.BLACK); + irqStateToColor.put(IRQMode.LTTV_IRQ_IDLE.getInName(), StateColor.GRAY); + irqStateToColor.put(IRQMode.LTTV_IRQ_BUSY.getInName(), + StateColor.ORANGE); + } + + private void fillTrapStateToColor() { + trapStateToColor.put(TrapMode.LTTV_TRAP_UNKNOWN.getInName(), + StateColor.BLACK); + trapStateToColor.put(TrapMode.LTTV_TRAP_IDLE.getInName(), + StateColor.BLACK); + trapStateToColor.put(TrapMode.LTTV_TRAP_BUSY.getInName(), + StateColor.GOLD); + } + + private void fillSoftIRQStateToColor() { + softIrqStateToColor.put(SoftIRQMode.LTTV_SOFT_IRQ_UNKNOWN.getInName(), + StateColor.BLACK); + softIrqStateToColor.put(SoftIRQMode.LTTV_SOFT_IRQ_IDLE.getInName(), + StateColor.BLACK); + softIrqStateToColor.put(SoftIRQMode.LTTV_SOFT_IRQ_PENDING.getInName(), + StateColor.PINK1); + softIrqStateToColor.put(SoftIRQMode.LTTV_SOFT_IRQ_BUSY.getInName(), + StateColor.PURPLE1); + } + + private void fillBdevStateToColor() { + softIrqStateToColor.put(BdevMode.LTTV_BDEV_UNKNOWN.getInName(), + StateColor.BLACK); + softIrqStateToColor.put(BdevMode.LTTV_BDEV_IDLE.getInName(), + StateColor.BLACK); + softIrqStateToColor.put(BdevMode.LTTV_BDEV_BUSY_READING.getInName(), + StateColor.DARK_BLUE); + softIrqStateToColor.put(BdevMode.LTTV_BDEV_BUSY_WRITING.getInName(), + StateColor.RED); + } + + private void fillProcessStateToColor() { + // Process Status + procStateToColor.put(ProcessStatus.LTTV_STATE_UNNAMED.getInName(), + StateColor.GRAY); + procStateToColor.put(ProcessStatus.LTTV_STATE_DEAD.getInName(), + StateColor.BLACK); + procStateToColor.put(ProcessStatus.LTTV_STATE_WAIT_FORK.getInName(), + StateColor.DARK_GREEN); + procStateToColor.put(ProcessStatus.LTTV_STATE_WAIT_CPU.getInName(), + StateColor.DARK_YELLOW); + procStateToColor.put(ProcessStatus.LTTV_STATE_EXIT.getInName(), + StateColor.MAGENTA3); + procStateToColor.put(ProcessStatus.LTTV_STATE_ZOMBIE.getInName(), + StateColor.PURPLE1); + procStateToColor.put(ProcessStatus.LTTV_STATE_WAIT.getInName(), + StateColor.RED); + + // Execution Mode + procStateToColor.put(ExecutionMode.LTTV_STATE_MODE_UNKNOWN.getInName(), + StateColor.BLACK); + procStateToColor.put(ExecutionMode.LTTV_STATE_USER_MODE.getInName(), + StateColor.GREEN); + procStateToColor.put(ExecutionMode.LTTV_STATE_SYSCALL.getInName(), + StateColor.DARK_BLUE); + procStateToColor.put(ExecutionMode.LTTV_STATE_TRAP.getInName(), + StateColor.GOLD); + procStateToColor.put(ExecutionMode.LTTV_STATE_IRQ.getInName(), + StateColor.ORANGE); + procStateToColor.put(ExecutionMode.LTTV_STATE_SOFT_IRQ.getInName(), + StateColor.PINK1); + } +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/PerspectiveFactory.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/PerspectiveFactory.java new file mode 100644 index 0000000000..bd28bc3c82 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/PerspectiveFactory.java @@ -0,0 +1,113 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views; + +import org.eclipse.linuxtools.lttng.ui.views.control.ControlView; +import org.eclipse.linuxtools.lttng.ui.views.controlflow.ControlFlowView; +import org.eclipse.linuxtools.lttng.ui.views.events.EventsView; +import org.eclipse.linuxtools.lttng.ui.views.histogram.HistogramView; +import org.eclipse.linuxtools.lttng.ui.views.project.ProjectView; +import org.eclipse.linuxtools.lttng.ui.views.resources.ResourcesView; +import org.eclipse.linuxtools.lttng.ui.views.statistics.StatisticsView; +import org.eclipse.linuxtools.lttng.ui.views.timeframe.TimeFrameView; +import org.eclipse.ui.IFolderLayout; +import org.eclipse.ui.IPageLayout; +import org.eclipse.ui.IPerspectiveFactory; + +/** + * PerspectiveFactory + *

+ * TODO: Implement me. Please. + */ +public class PerspectiveFactory implements IPerspectiveFactory { + + // LTTng views + private static final String PROJECT_VIEW_ID = ProjectView.ID; + private static final String CONTROL_VIEW_ID = ControlView.ID; + private static final String EVENTS_VIEW_ID = EventsView.ID; + private static final String TIME_FRAME_VIEW_ID = TimeFrameView.ID; + private static final String CONTROL_FLOW_VIEW_ID = ControlFlowView.ID; + private static final String RESOURCES_VIEW_ID = ResourcesView.ID; + private static final String STATISTICS_VIEW_ID = StatisticsView.ID; + private static final String HISTOGRAM_VIEW_ID = HistogramView.ID; + + // Standard Eclipse views + private static final String PROPERTIES_VIEW_ID = IPageLayout.ID_PROP_SHEET; + private static final String PROBLEM_VIEW_ID = IPageLayout.ID_PROBLEM_VIEW; + + /* (non-Javadoc) + * @see org.eclipse.ui.IPerspectiveFactory#createInitialLayout(org.eclipse.ui.IPageLayout) + */ + public void createInitialLayout(IPageLayout layout) { + + layout.setEditorAreaVisible(false); + + addFastViews(layout); + addViewShortcuts(layout); + addPerspectiveShortcuts(layout); + + // Create the top left folder + IFolderLayout topLeftFolder = layout.createFolder("topLeftFolder", IPageLayout.LEFT, 0.15f, IPageLayout.ID_EDITOR_AREA); + topLeftFolder.addView(PROJECT_VIEW_ID); + topLeftFolder.addView(CONTROL_VIEW_ID); + + // Create the bottom left folder + IFolderLayout bottomLeftFolder = layout.createFolder("bottomLeftFolder", IPageLayout.BOTTOM, 0.50f, "topLeftFolder"); + bottomLeftFolder.addView(PROPERTIES_VIEW_ID); + + // Create the middle right folder + IFolderLayout topRightFolder = layout.createFolder("topRightFolder", IPageLayout.TOP, 0.50f, IPageLayout.ID_EDITOR_AREA); + topRightFolder.addView(CONTROL_FLOW_VIEW_ID); + topRightFolder.addView(RESOURCES_VIEW_ID); + topRightFolder.addView(STATISTICS_VIEW_ID); + + // Create the middle right folder + IFolderLayout middleRightFolder = layout.createFolder("middleRightFolder", IPageLayout.BOTTOM, 0.50f, "topRightFolder"); + middleRightFolder.addView(EVENTS_VIEW_ID); + + // Create the bottom right folder + IFolderLayout bottomRightFolder = layout.createFolder("bottomRightFolder", IPageLayout.BOTTOM, 0.65f, "middleRightFolder"); + bottomRightFolder.addView(TIME_FRAME_VIEW_ID); + bottomRightFolder.addView(HISTOGRAM_VIEW_ID); + bottomRightFolder.addView(PROBLEM_VIEW_ID); + + } + + /** + * Add fast views to the perspective + * + * @param layout + */ + private void addFastViews(IPageLayout layout) { + // TODO Auto-generated method stub + } + + /** + * Add view shortcuts to the perspective + * + * @param layout + */ + private void addViewShortcuts(IPageLayout layout) { + // TODO Auto-generated method stub + } + + /** + * Add perspective shortcuts to the perspective + * + * @param layout + */ + private void addPerspectiveShortcuts(IPageLayout layout) { + // TODO Auto-generated method stub + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/common/AbsTRangeUpdate.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/common/AbsTRangeUpdate.java new file mode 100644 index 0000000000..9664c525f2 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/common/AbsTRangeUpdate.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are made + * available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Alvaro Sanchez-Leon - Initial implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.common; + +import org.eclipse.linuxtools.lttng.state.evProcessor.ILttngEventProcessor; +import org.eclipse.linuxtools.lttng.state.evProcessor.state.AbsStateProcessing; +import org.eclipse.linuxtools.lttng.state.model.LttngTraceState; +import org.eclipse.linuxtools.tmf.event.TmfTimeRange; + +public abstract class AbsTRangeUpdate extends AbsStateProcessing implements + ILttngEventProcessor { + + private static final long MINORBITS = 20; + + // ======================================================================== + // General methods + // ======================================================================= + + /** + * Get the mkdev node id
+ *
+ * This is an implementation of a KERNEL macro used in Lttv + * + */ + public long getMkdevId(long major, long minor) { + return (((major) << MINORBITS) | (minor)); + } + + /** + * Get the pixels per Nano second, either from active widgets or initialise + * with the experiment time range values + * + * @param traceSt + * @param params + * + * @return double + */ + protected double getPixelsPerNs(LttngTraceState traceSt, ParamsUpdater params) { + double pixPerNs = params.getPixelsPerNs(); + if (pixPerNs == 0) { + TmfTimeRange tsetRange = traceSt.getContext().getExperimentTimeWindow(); + + long startTime = tsetRange.getStartTime().getValue(); + long endTime = tsetRange.getEndTime().getValue(); + long delta = endTime - startTime; + + if (delta > 0) { + pixPerNs = (double) params.getWidth() / (double) delta; + params.setPixelsPerNs(pixPerNs); + } + } + return pixPerNs; + } + +} \ No newline at end of file diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/common/AbsTimeUpdateView.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/common/AbsTimeUpdateView.java new file mode 100644 index 0000000000..58b8e65258 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/common/AbsTimeUpdateView.java @@ -0,0 +1,669 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.common; + +import java.util.Arrays; + +import org.eclipse.linuxtools.lttng.control.LttngCoreProviderFactory; +import org.eclipse.linuxtools.lttng.control.LttngSyntheticEventProvider; +import org.eclipse.linuxtools.lttng.event.LttngSyntheticEvent; +import org.eclipse.linuxtools.lttng.event.LttngSyntheticEvent.SequenceInd; +import org.eclipse.linuxtools.lttng.event.LttngTimestamp; +import org.eclipse.linuxtools.lttng.request.ILttngSyntEventRequest; +import org.eclipse.linuxtools.lttng.request.IRequestStatusListener; +import org.eclipse.linuxtools.lttng.request.LttngSyntEventRequest; +import org.eclipse.linuxtools.lttng.request.RequestCompletedSignal; +import org.eclipse.linuxtools.lttng.request.RequestStartedSignal; +import org.eclipse.linuxtools.lttng.state.evProcessor.ITransEventProcessor; +import org.eclipse.linuxtools.lttng.ui.TraceDebug; +import org.eclipse.linuxtools.lttng.ui.model.trange.ItemContainer; +import org.eclipse.linuxtools.lttng.ui.views.resources.model.ResourceModelFactory; +import org.eclipse.linuxtools.tmf.event.TmfEvent; +import org.eclipse.linuxtools.tmf.event.TmfTimeRange; +import org.eclipse.linuxtools.tmf.event.TmfTimestamp; +import org.eclipse.linuxtools.tmf.experiment.TmfExperiment; +import org.eclipse.linuxtools.tmf.request.TmfDataRequest; +import org.eclipse.linuxtools.tmf.signal.TmfRangeSynchSignal; +import org.eclipse.linuxtools.tmf.signal.TmfSignalHandler; +import org.eclipse.linuxtools.tmf.signal.TmfSignalManager; +import org.eclipse.linuxtools.tmf.signal.TmfTimeSynchSignal; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.ITimeAnalysisViewer; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeScaleSelectionEvent; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeSelectionEvent; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITmfTimeAnalysisEntry; +import org.eclipse.linuxtools.tmf.ui.views.TmfView; +import org.eclipse.swt.widgets.Display; + +/** + *

+ * Abstract class used as a base for views handling specific time range data + * requests + *

+ *

+ * The class handles a single element queue of data requests, i.e. request can + * be triggered from different sources e.g. opening a file as well as a new + * selected time window + *

+ * + * @author alvaro + * + */ +public abstract class AbsTimeUpdateView extends TmfView implements + IRequestStatusListener { + + // ======================================================================== + // Data + // ======================================================================== + /** + * One second in nanoseconds + */ + private static final long INITIAL_WINDOW_OFFSET = 1000000000L; /* + * 1 sec // + * in ns // + */ + // private static final long INITIAL_WINDOW_OFFSET = 100000000L; /* 100 ms + // in ns */ + /** + * Number of events before a GUI refresh + */ + private static final Long INPUT_CHANGED_REFRESH = 3000L; + private static final long DEFAULT_OFFSET = 0L; + private static final int DEFAULT_CHUNK = 1; + + protected boolean synch = true; // time synchronisation, used to be an + // option + protected ITimeAnalysisViewer tsfviewer = null; + + // ======================================================================== + // Constructor + // ======================================================================== + public AbsTimeUpdateView(String viewID) { + super(viewID); + // freqState = UiCommonFactory.getQueue(this); + } + + // ======================================================================== + // Methods + // ======================================================================== + /* + * (non-Javadoc) + * + * @seeorg.eclipse.linuxtools.lttng.state.IStateDataRequestListener# + * processingStarted(org.eclipse.linuxtools.lttng.state.StateDataRequest) + */ + @TmfSignalHandler + public synchronized void processingStarted(RequestStartedSignal signal) { + LttngSyntEventRequest request = signal.getRequest(); + if (request != null) { + // update queue with the id of the current request. + // freqState.requestStarted(request); + + // if there was no new request then this one is still on + // prepare for the reception of new data + waitCursor(true); + + // no new time range for zoom orders + TmfTimeRange trange = null; + // Time Range will be used to filter out events which are + // not visible in one pixel + trange = request.getRange(); + + // indicate if the data model needs to be cleared e.g. a new + // experiment is being selected + boolean clearData = request.isclearDataInd(); + // Indicate if current data needs to be cleared and if so + // specify the new experiment time range that applies + ModelUpdatePrep(trange, clearData); + } + } + + /* + * (non-Javadoc) + * + * @seeorg.eclipse.linuxtools.lttng.state.IStateDataRequestListener# + * processingCompleted(org.eclipse.linuxtools.lttng.state.StateDataRequest) + */ + @TmfSignalHandler + public void processingCompleted(RequestCompletedSignal signal) { + ILttngSyntEventRequest request = signal.getRequest(); + + if (request == null) { + return; + } + + // Update wait cursor + waitCursor(false); + + // No data refresh actions for cancelled requests. + if (request.isCancelled() || request.isFailed()) { + if (TraceDebug.isDEBUG()) { + TmfTimeRange trange = request.getRange(); + if (request.isCancelled()) { + TraceDebug.debug("Request cancelled " + + trange.getStartTime() + "-" + trange.getEndTime() + + " Handled Events: " + request.getSynEventCount() + + " " + request.toString(), 15); + } else if (request.isFailed()) { + TraceDebug.debug("Request Failed " + trange.getStartTime() + + "-" + trange.getEndTime() + " Handled Events: " + + request.getSynEventCount() + " " + + request.toString()); + } + } + + return; + } else { + modelInputChanged(request, true); + } + } + + /** + * Registers as listener of time selection from other views + * + * @param signal + */ + public void synchToTime(TmfTimeSynchSignal signal) { + if (synch) { + Object source = signal.getSource(); + if (signal != null && source != null && source != this) { + // Internal value is expected in nano seconds. + long selectedTime = signal.getCurrentTime().getValue(); + if (tsfviewer != null) { + tsfviewer.setSelectedTime(selectedTime, true, source); + } + } + } + } + + /** + * Process the reception of time window adjustment in this view if the + * source of the update is not this view. + * + * @param signal + * @param clearingData + */ + public void synchToTimeRange(TmfRangeSynchSignal signal, boolean clearingData) { + if (synch) { + Object source = signal.getSource(); + if (signal != null && source != null && source != this) { + // Internal value is expected in nano seconds. + TmfTimeRange trange = signal.getCurrentRange(); + TmfExperiment experiment = TmfExperiment.getCurrentExperiment(); + if (experiment == null) { + TraceDebug.debug("Current selected experiment is null"); + return; + } + + // Clearing of process data is configurable + dataRequest(trange, experiment.getTimeRange(), clearingData); + } + } + } + + /** + * Trigger time synchronisation to other views this method shall be called + * when a check has been performed to note that an actual change of time has + * been performed vs a pure re-selection of the same time + * + * @param time + * @param source + */ + protected void synchTimeNotification(long time, Object source) { + // if synchronisation selected + if (synch) { + // Notify other views + TmfSignalManager.dispatchSignal(new TmfTimeSynchSignal(source, new LttngTimestamp(time))); + } + } + + /** + * Common implementation of ITmfTimeSelectionListener, not used by all the + * views extending this abstract class + * + * @param event + */ + protected void tsfTmProcessSelEvent(TmfTimeSelectionEvent event) { + Object source = event.getSource(); + if (source == null) { + return; + } + + ParamsUpdater paramUpdater = getParamsUpdater(); + Long savedSelTime = paramUpdater.getSelectedTime(); + + long selTimens = event.getSelectedTime(); + + // make sure the new selected time is different than saved before + // executing update + if (savedSelTime == null || savedSelTime != selTimens) { + // Notify listener views. + synchTimeNotification(selTimens, source); + + // Update the parameter updater to save the selected time + paramUpdater.setSelectedTime(selTimens); + + if (TraceDebug.isDEBUG()) { + TraceDebug.debug("Selected Time: " + new LttngTimestamp(selTimens) + "\n\t\t" + getName()); + } + } + } + + /** + * Common implementation of ITmfTimeScaleSelectionListener, not used by all + * the views extending this abstract class + * + * @param event + */ + protected synchronized void tsfTmProcessTimeScaleEvent(TmfTimeScaleSelectionEvent event) { + // source needed to keep track of source values + Object source = event.getSource(); + + if (source != null) { + // Update the parameter updater before carrying out a read request + ParamsUpdater paramUpdater = getParamsUpdater(); + boolean newParams = paramUpdater.processTimeScaleEvent(event); + + if (newParams) { + // Read the updated time window + TmfTimeRange trange = paramUpdater.getTrange(); + if (trange != null) { + + // Notify listener views. to perform data requests + // upon this notification + synchTimeRangeNotification(trange, paramUpdater.getSelectedTime(), source); + } + } + } + } + + /** + * Inform registered listeners about the new time range + * + * @param trange + * @param selectedTime + * @param source + */ + protected void synchTimeRangeNotification(TmfTimeRange trange, Long selectedTime, Object source) { + // if synchronisation selected + if (synch) { + // Notify other views + TmfSignalManager.dispatchSignal(new TmfRangeSynchSignal(source, trange, new LttngTimestamp(selectedTime))); + } + } + + /** + * @param zoomedTRange + * @param experimentTRange + */ + public void dataRequest(TmfTimeRange zoomedTRange, + TmfTimeRange experimentTRange, boolean clearingData) { + + // timeRange is the Experiment time range + boolean sent = processDataRequest(zoomedTRange, experimentTRange, clearingData); + + if (sent) { + waitCursor(true); + } + } + + /** + * send data request directly e.g. doesn't use a queue + * + * @param requestTrange + * @param listener + * @param experimentTRange + * @param processor + * @return + */ + private boolean processDataRequest(TmfTimeRange requestTrange, + TmfTimeRange experimentTRange, boolean clearingData) { + // Validate input + if (requestTrange == null || experimentTRange == null) { + TraceDebug.debug("Invalid input"); + return false; + } + + LttngSyntEventRequest request = new LttngSyntEventRequest( + requestTrange, DEFAULT_OFFSET, TmfDataRequest.ALL_DATA, + DEFAULT_CHUNK, this, experimentTRange, getEventProcessor()) { + + Long fCount = getSynEventCount(); + ITransEventProcessor processor = getProcessor(); + TmfTimestamp frunningTimeStamp; + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.linuxtools.lttng.request.LttngSyntEventRequest#handleData + * () + */ + public void handleData() { + TmfEvent[] result = getData(); + + TmfEvent evt = (result.length > 0) ? result[0] : null; + if (evt != null) { + LttngSyntheticEvent synEvent = (LttngSyntheticEvent) evt; + // process event + SequenceInd indicator = synEvent.getSynType(); + if (indicator == SequenceInd.BEFORE + || indicator == SequenceInd.AFTER) { + processor.process(evt, synEvent.getTraceModel()); + } else if (indicator == SequenceInd.STARTREQ) { + handleRequestStarted(); + } else if (indicator == SequenceInd.ENDREQ) { + processor.process(evt, synEvent.getTraceModel()); + // handleCompleted(); + } + + if (indicator == SequenceInd.BEFORE) { + fCount++; + if (fCount != 0 && fCount % INPUT_CHANGED_REFRESH == 0) { + // send partial update + modelInputChanged(this, false); + + if (TraceDebug.isDEBUG()) { + frunningTimeStamp = evt.getTimestamp(); + TraceDebug.debug("handled: " + fCount + " sequence: " + synEvent.getSynType()); + } + + } + } + } + } + + public void handleRequestStarted() { + notifyStarting(); + } + + public void handleCompleted() { + super.handleCompleted(); + + // Data is not complete and should be handled as such + if (isFailed() || isCancelled()) { + modelIncomplete(this); + } + + if (TraceDebug.isDEBUG()) { + if (frunningTimeStamp != null) { + TraceDebug.debug("Last event time stamp: " + + frunningTimeStamp.getValue()); + } + } + } + }; + + // obtain singleton core provider + LttngSyntheticEventProvider provider = LttngCoreProviderFactory + .getEventProvider(); + + // send the request to TMF + request.startRequestInd(provider); + request.setclearDataInd(clearingData); + return true; + } + + /** + * Returns an initial smaller window to allow the user to select the area of + * interest + * + * @param experimentTRange + * @return + */ + protected TmfTimeRange getInitTRange(TmfTimeRange experimentTRange) { + TmfTimestamp expStartTime = experimentTRange.getStartTime(); + TmfTimestamp expEndTime = experimentTRange.getEndTime(); + TmfTimestamp initialEndOfWindow = new LttngTimestamp(expStartTime + .getValue() + + INITIAL_WINDOW_OFFSET); + if (initialEndOfWindow.compareTo(expEndTime, false) < 0) { + return new TmfTimeRange(expStartTime, initialEndOfWindow); + } + + // The original size of the experiment is smaller than proposed adjusted + // time + return experimentTRange; + } + + /** + * Request the Time Analysis widget to enable or disable the wait cursor + * e.g. data request in progress or data request completed + * + * @param waitInd + */ + protected void waitCursor(final boolean waitInd) { + if (tsfviewer != null) { + Display display = tsfviewer.getControl().getDisplay(); + + // Perform the updates on the UI thread + display.asyncExec(new Runnable() { + public void run() { + tsfviewer.waitCursor(waitInd); + } + }); + } + } + + /** + * View preparation to override the current local information + * + * @param timeRange + * - new total time range e.g. Experiment level + * @param clearAllData + */ + protected void ModelUpdatePrep(TmfTimeRange timeRange, boolean clearAllData) { + ItemContainer itemContainer = getItemContainer(); + if (clearAllData) { + // start fresh e.g. new experiment selected + itemContainer.clearItems(); + } else { + // clear children but keep processes + itemContainer.clearChildren(); + } + + // Obtain the current resource array + ITmfTimeAnalysisEntry[] itemArr = itemContainer.readItems(); + + // clean up data and boundaries + displayModel(itemArr, -1, -1, false, -1, -1, null); + + ParamsUpdater updater = getParamsUpdater(); + if (updater != null) { + // Start over + updater.setEventsDiscarded(0); + + // Update new visible time range if available + if (timeRange != null) { + updater.update(timeRange.getStartTime().getValue(), timeRange.getEndTime().getValue()); + } + } + } + + /** + * Initialize the model and view before reloading items + * + * @param boundaryRange + * @param visibleRange + * @param source + */ + protected void ModelUpdateInit(TmfTimeRange boundaryRange, TmfTimeRange visibleRange, Object source) { + // Update the view boundaries + if (boundaryRange != null) { + ItemContainer itemContainer = getItemContainer(); + if (itemContainer != null) { + itemContainer.clearItems(); + // Obtain the current process array + ITmfTimeAnalysisEntry[] itemArr = itemContainer.readItems(); + + long startTime = boundaryRange.getStartTime().getValue(); + long endTime = boundaryRange.getEndTime().getValue(); + + // Update the view part + displayModel(itemArr, startTime, endTime, true, visibleRange.getStartTime().getValue(), visibleRange + .getEndTime().getValue(), source); + } + } + + // update the view filtering parameters + if (visibleRange != null) { + ParamsUpdater updater = getParamsUpdater(); + if (updater != null) { + // Start over + updater.setEventsDiscarded(0); + // Update new visible time range if available + updater.update(visibleRange.getStartTime().getValue(), visibleRange.getEndTime().getValue()); + } + } + } + + /** + * Actions taken by the view to refresh its widget(s) with the updated data + * model + * + * @param request + * @param complete + * true: yes, false: partial update + */ + protected void modelInputChanged(ILttngSyntEventRequest request, boolean complete) { + long experimentStartTime = -1; + long experimentEndTime = -1; + TmfTimeRange experimentTimeRange = request.getExperimentTimeRange(); + if (experimentTimeRange != null) { + experimentStartTime = experimentTimeRange.getStartTime().getValue(); + experimentEndTime = experimentTimeRange.getEndTime().getValue(); + } + + // Obtain the current resource list + ITmfTimeAnalysisEntry[] itemArr = getItemContainer().readItems(); + + if (itemArr != null) { + // Sort the array by pid + Arrays.sort(itemArr); + + // Update the view part + displayModel(itemArr, experimentStartTime, experimentEndTime, false, request.getRange().getStartTime() + .getValue(), request.getRange().getEndTime().getValue(), request.getSource()); + } + + if (complete) { + // reselect to original time + ParamsUpdater paramUpdater = ResourceModelFactory.getParamsUpdater(); + if (paramUpdater != null && tsfviewer != null) { + final Long selTime = paramUpdater.getSelectedTime(); + if (selTime != null) { + TraceDebug.debug("View: " + getName() + "\n\t\tRestoring the selected time to: " + selTime); + Display display = tsfviewer.getControl().getDisplay(); + display.asyncExec(new Runnable() { + public void run() { + tsfviewer.setSelectedTime(selTime, false, this); + } + }); + } + + if (TraceDebug.isDEBUG()) { + int eventCount = 0; + Long count = request.getSynEventCount(); + for (int pos = 0; pos < itemArr.length; pos++) { + eventCount += itemArr[pos].getTraceEvents().size(); + } + + int discarded = getParamsUpdater().getEventsDiscarded(); + int discardedOutofOrder = paramUpdater.getEventsDiscardedWrongOrder(); + TmfTimeRange range = request.getRange(); + StringBuilder sb = new StringBuilder("View: " + getName() + ", Events handled: " + count + + ", Events loaded in view: " + eventCount + ", Number of events discarded: " + discarded + + "\n\tNumber of events discarded with start time earlier than next good time: " + + discardedOutofOrder); + + sb.append("\n\t\tRequested Time Range: " + range.getStartTime() + "-" + range.getEndTime()); + sb.append("\n\t\tExperiment Time Range: " + experimentStartTime + "-" + experimentEndTime); + TraceDebug.debug(sb.toString()); + } + } + + } + } + + // /** + // * Obtains the remainder fraction on unit Seconds of the entered value in + // * nanoseconds. e.g. input: 1241207054171080214 ns The number of seconds + // can + // * be obtain by removing the last 9 digits: 1241207054 the fractional + // * portion of seconds, expressed in ns is: 171080214 + // * + // * @param v + // * @return + // */ + // protected String formatNs(long v) { + // StringBuffer str = new StringBuffer(); + // boolean neg = v < 0; + // if (neg) { + // v = -v; + // str.append('-'); + // } + // + // String strVal = String.valueOf(v); + // if (v < 1000000000) { + // return strVal; + // } + // + // // Extract the last nine digits (e.g. fraction of a S expressed in ns + // return strVal.substring(strVal.length() - 9); + // } + + /** + * The request was stopped, the data is incomplete + * + * @param request + */ + protected abstract void modelIncomplete(ILttngSyntEventRequest request); + + /** + * Returns the Event processor instance related to a specific view + * + * @return + */ + protected abstract ITransEventProcessor getEventProcessor(); + + /** + * To be overridden by some sub-classes although may not be needed in some + * e.g. statistics view + * + * @param items + * @param startBoundTime + * @param endBoundTime + * @param updateTimeBounds + * - Time bounds updated needed e.g. if a new Experiment or trace + * is selected + * @param startVisibleWindow + * @param endVisibleWindow + * @param source + */ + protected abstract void displayModel(final ITmfTimeAnalysisEntry[] items, final long startBoundTime, + final long endBoundTime, final boolean updateTimeBounds, final long startVisibleWindow, + final long endVisibleWindow, final Object source); + + /** + * To be overridden by some sub-classes although may not be needed in some + * e.g. statistics view + * + * @return + */ + protected abstract ParamsUpdater getParamsUpdater(); + + /** + * Returns the model's item container + * + * @return + */ + protected abstract ItemContainer getItemContainer(); +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/common/ParamsUpdater.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/common/ParamsUpdater.java new file mode 100644 index 0000000000..ae9c3a5bb3 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/common/ParamsUpdater.java @@ -0,0 +1,262 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.common; + +import org.eclipse.linuxtools.lttng.event.LttngTimestamp; +import org.eclipse.linuxtools.lttng.ui.TraceDebug; +import org.eclipse.linuxtools.tmf.event.TmfTimeRange; +import org.eclipse.linuxtools.tmf.event.TmfTimestamp; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeScaleSelectionEvent; + +/** + * + * Preserve the time and space width parameters applicable to a particular view + * in order to facilitate filtering of events and request handling. + * + * @author alvaro + * + */ +public class ParamsUpdater { + // ======================================================================== + // Data + // ======================================================================== + + private long startTime = 0; + private long endTime = Long.MAX_VALUE; + private Long selectedTime = null; + private final int DEFAULT_WIDTH = 2000; // number of estimated pixels + // that + // can hold the time range space + private int width = DEFAULT_WIDTH; // width in pixels used to represent the + // time interval + private double pixelsPerNs = 0; + private int eventsDiscarded = 0; + private int eventsDiscardedWrongOrder = 0; + private TmfTimeRange trange = null; + + // ======================================================================== + // Methods + // ======================================================================== + + /** + * @param event + * @return + */ + public synchronized boolean processTimeScaleEvent( + TmfTimeScaleSelectionEvent event) { + + boolean updated = false; + if (event != null) { + long time0 = event.getTime0(); + long time1 = event.getTime1(); + int dwidth = event.getWidth(); + + updated = update(time0, time1, dwidth); + + // initialization only, otherwise wait for the actual selection + // event to update its value. Note that the time must be different + // upon selection of a new time in order to trigger an update to all + if (selectedTime == null) { + setSelectedTime(event.getSelectedTime()); + } + + } + + return updated; + + } + + /** + * Save the selected time + * @param selTime + */ + public void setSelectedTime(long selTime) { + TraceDebug.debug("Selected time changed from: \n\t" + selectedTime + + " to: \n\t" + selTime); + selectedTime = selTime; + } + + /** + * May return null, if the selected time is invalid + * + * @return + */ + public Long getSelectedTime() { + return selectedTime; + } + + /** + * Update time range but keep width as is + * + * @param time0 + * @param time1 + * @return + */ + public boolean update(long time0, long time1) { + return update(time0, time1, width); + } + + /** + * Only positive attributes are expected + * + * @param time0 + * @param time1 + * @param dwidth + * @return + */ + public boolean update(long time0, long time1, int dwidth) { + boolean updated = false; + + if (time0 == startTime && time1 == endTime && dwidth == width) { + // No updated needed + return updated; + } + + // Negatives are invalid + time0 = time0 > 0 ? time0 : 0; + time1 = time1 > 0 ? time1 : 0; + dwidth = dwidth > 0 ? dwidth : 0; + + if (time1 > time0) { + // Store the new values as long as they are within range + startTime = time0; + endTime = time1; + width = dwidth; + + pixelsPerNs = (double) width / (double) (endTime - startTime); + + TmfTimestamp fTimeStart = new LttngTimestamp(startTime); + TmfTimestamp fTimeEnd = new LttngTimestamp(endTime); + trange = new TmfTimeRange(fTimeStart, fTimeEnd); + + // make sure the selected time is within the new range or else set + // mark it as invalid + if (selectedTime != null) { + setSelectedTime(selectedTime); + } + + // update succeeded + updated = true; + + TraceDebug.debug("Configuration updated to: StartTime: " /* */ + + fTimeStart /* */ + + "-" /* */ + + fTimeEnd /* */ + + " width: " /* */ + + width + " k: " + pixelsPerNs); /* */ + } else { + TraceDebug + .debug("End time is not greater than start time, start time: " + + time0 + " end time: " + time1); + } + + return updated; + } + + /** + * @return + */ + public long getStartTime() { + return startTime; + } + + /** + * @return + */ + public long getEndTime() { + return endTime; + } + + /** + * @return + */ + public int getWidth() { + if (width == 0) { + TraceDebug + .debug("Unexpected width value of 0 pixels, returning default"); + return DEFAULT_WIDTH; + } + + return width; + } + + /** + * Return the current constant "K" of pixels per nano second used for the + * widest time space widget registered in this instance. + * + * @return + */ + public double getPixelsPerNs() { + return pixelsPerNs; + } + + /** + * Set the value of pixels per nano second as long as the value is grater + * positive + * + * @return + */ + public void setPixelsPerNs(double pixperNsec) { + if (pixperNsec > 0) { + pixelsPerNs = pixperNsec; + } + } + + /** + * @param value + */ + public void setEventsDiscarded(int value) { + eventsDiscarded = value; + if (value == 0) { + eventsDiscardedWrongOrder = 0; + } + } + + /** + * + */ + public void incrementEventsDiscarded() { + this.eventsDiscarded++; + } + + /** + * @return + */ + public int getEventsDiscarded() { + return eventsDiscarded; + } + + /** + * increase the number of events discarder since they were not received in a + * later time than previous events + */ + public void incrementEventsDiscardedWrongOrder() { + this.eventsDiscarded++; + this.eventsDiscardedWrongOrder++; + } + + /** + * @return + */ + public int getEventsDiscardedWrongOrder() { + return eventsDiscardedWrongOrder; + + } + + /** + * @return + */ + public TmfTimeRange getTrange() { + return trange; + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/control/ControlView.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/control/ControlView.java new file mode 100644 index 0000000000..5571fac589 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/control/ControlView.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.control; + +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.part.ViewPart; + +/** + * ControlView + *

+ * TODO: Implement me. Please. + */ +public class ControlView extends ViewPart { + + public static final String ID = "org.eclipse.linuxtools.lttng.ui.views.control"; + + /** + * + */ + public ControlView() { + // TODO Auto-generated constructor stub + } + + /* (non-Javadoc) + * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) + */ + @Override + public void createPartControl(Composite parent) { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see org.eclipse.ui.part.WorkbenchPart#setFocus() + */ + @Override + public void setFocus() { + // TODO Auto-generated method stub + + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/ControlFlowView.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/ControlFlowView.java new file mode 100644 index 0000000000..db480780a3 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/ControlFlowView.java @@ -0,0 +1,1094 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are made + * available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Alvaro Sanchez-Leon - Initial implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.controlflow; + +import java.util.Vector; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IMenuListener; +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.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredViewer; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerFilter; +import org.eclipse.linuxtools.lttng.event.LttngTimestamp; +import org.eclipse.linuxtools.lttng.request.ILttngSyntEventRequest; +import org.eclipse.linuxtools.lttng.state.evProcessor.ITransEventProcessor; +import org.eclipse.linuxtools.lttng.ui.TraceDebug; +import org.eclipse.linuxtools.lttng.ui.model.trange.ItemContainer; +import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEventProcess; +import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeViewerProvider; +import org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView; +import org.eclipse.linuxtools.lttng.ui.views.common.ParamsUpdater; +import org.eclipse.linuxtools.lttng.ui.views.controlflow.evProcessor.FlowEventToHandlerFactory; +import org.eclipse.linuxtools.lttng.ui.views.controlflow.model.FlowModelFactory; +import org.eclipse.linuxtools.tmf.event.TmfEvent; +import org.eclipse.linuxtools.tmf.event.TmfTimeRange; +import org.eclipse.linuxtools.tmf.experiment.TmfExperiment; +import org.eclipse.linuxtools.tmf.signal.TmfExperimentSelectedSignal; +import org.eclipse.linuxtools.tmf.signal.TmfRangeSynchSignal; +import org.eclipse.linuxtools.tmf.signal.TmfSignalHandler; +import org.eclipse.linuxtools.tmf.signal.TmfTimeSynchSignal; +import org.eclipse.linuxtools.tmf.ui.viewers.TmfViewerFactory; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.ITmfTimeFilterSelectionListener; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.ITmfTimeScaleSelectionListener; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.ITmfTimeSelectionListener; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeFilterSelectionEvent; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeScaleSelectionEvent; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeSelectionEvent; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITmfTimeAnalysisEntry; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.SashForm; +import org.eclipse.swt.custom.ScrolledComposite; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.ScrollBar; +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.IWorkbenchActionConstants; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.plugin.AbstractUIPlugin; + +/** + * ControlFlowView + */ +/** + * @author alvaro + * + */ +public class ControlFlowView extends AbsTimeUpdateView implements + ITmfTimeSelectionListener, ITmfTimeScaleSelectionListener, + ITmfTimeFilterSelectionListener { + + public static final String ID = "org.eclipse.linuxtools.lttng.ui.views.controlflow"; + + // ======================================================================== + // Table data + // ======================================================================== + private final String PROCESS_COLUMN = "Process"; + private final String BRAND_COLUMN = "Brand"; + private final String PID_COLUMN = "PID"; + private final String TGID_COLUMN = "TGID"; + private final String PPID_COLUMN = "PPID"; + private final String CPU_COLUMN = "CPU"; + private final String BIRTH_SEC_COLUMN = "Birth sec"; + private final String BIRTH_NSEC_COLUMN = "Birth nsec"; + private final String TRACE = "TRACE"; + + private final String[] columnNames = new String[] { PROCESS_COLUMN, /* */ + BRAND_COLUMN,/* */ + PID_COLUMN,/* */ + TGID_COLUMN,/* */ + PPID_COLUMN,/* */ + CPU_COLUMN, /* */ + BIRTH_SEC_COLUMN,/* */ + BIRTH_NSEC_COLUMN,/* */ + TRACE /* */ + }; + + // ======================================================================== + // Data + // ======================================================================== + private TableViewer tableViewer; + // private int totalNumItems = 0; + // Actions + private Action doubleClickAction; + private Action resetScale; + private Action nextEvent; + private Action prevEvent; + private Action nextTrace; + private Action prevTrace; + private Action showLegend; + private Action filterTraces; + private Action zoomIn; + private Action zoomOut; + private Action zoomFilter; + + private ViewProcessFilter tableFilter = null; + private ScrolledComposite scrollFrame = null; + + // private static SimpleDateFormat stimeformat = new SimpleDateFormat( + // "yy/MM/dd HH:mm:ss"); + + // private TraceModelImplFactory fact; + + // ======================================================================== + // Methods + // ======================================================================== + /* + * The content provider class is responsible for providing objects to the + * view. It can wrap existing objects in adapters or simply return objects + * as-is. These objects may be sensitive to the current input of the view, + * or ignore it and always show the same content (like Task List, for + * example). + */ + + class ViewContentProvider implements + /* ILazyContentProvider, */IStructuredContentProvider { + private TableViewer cviewer = null; + private ITmfTimeAnalysisEntry[] elements = null; + + public ViewContentProvider(TableViewer v) { + cviewer = v; + } + + public void inputChanged(Viewer v, Object oldInput, Object newInput) { + this.elements = (ITmfTimeAnalysisEntry[]) newInput; + if (elements != null) { + TraceDebug.debug("Total number of processes provided to Control Flow view: " + elements.length); + } else { + TraceDebug.debug("New input = null"); + } + } + + public void dispose() { + + } + + // Needed with the use of virtual tables in order to initialize items + // which were not initially visible. + public void updateElement(int index) { + cviewer.replace(elements[index], index); + } + + // @Override + public Object[] getElements(Object inputElement) { + return elements; + } + } + + class ViewLabelProvider extends LabelProvider implements + ITableLabelProvider { + public String getColumnText(Object obj, int index) { + String strRes = ""; //$NON-NLS-1$ + LttngTimestamp time; + if (obj instanceof TimeRangeEventProcess) { + TimeRangeEventProcess process = (TimeRangeEventProcess) obj; + switch (index) { + case 0: + strRes = process.getName(); + break; + case 1: + strRes = process.getBrand(); + break; + case 2: + strRes = process.getPid().toString(); + break; + case 3: + strRes = process.getTgid().toString(); + break; + case 4: + strRes = process.getPpid().toString(); + break; + case 5: + strRes = process.getCpu().toString(); + break; + case 6: + time = new LttngTimestamp(process.getCreationTime() + .longValue()); + strRes = time.getSeconds(); + break; + case 7: + time = new LttngTimestamp(process.getCreationTime() + .longValue()); + strRes = time.getNanoSeconds(); + break; + case 8: + strRes = process.getTraceID(); + break; + default: + break; + } + } else { + return getText(obj); + } + + return strRes; + } + + public Image getColumnImage(Object obj, int index) { + return getImage(obj); + } + + @Override + public Image getImage(Object obj) { + // No image needed for the time being + // return PlatformUI.getWorkbench().getSharedImages().getImage( + // ISharedImages.IMG_OBJ_ELEMENT); + return null; + } + } + + class ViewProcessFilter extends ViewerFilter { + + private Vector filteredSet = new Vector(); + StructuredViewer viewer; + + public ViewProcessFilter(StructuredViewer rviewer) { + this.viewer = rviewer; + } + + public void setFilter(Vector filtered) { + if (filtered != null) { + this.filteredSet = filtered; + viewer.refresh(); + } + } + + @Override + public boolean select(Viewer viewer, Object parentElement, + Object element) { + boolean filteredIn = true; + if (element instanceof ITmfTimeAnalysisEntry) { + ITmfTimeAnalysisEntry process = (ITmfTimeAnalysisEntry) element; + if (filteredSet.contains(process)) { + // The element is marked to be filtered out + return false; + } + } else { + TraceDebug.debug("Unexpected type of filter element received: " + + element.toString()); + } + // Compare element versus a list of filtered out + return filteredIn; + } + } + + /** + * The constructor. + */ + public ControlFlowView() { + super(ID); + } + + /** + * This is a callback that will allow us to create the viewer and initialize + * it. + */ + /* + * (non-Javadoc) + * + * @see + * org.eclipse.linuxtools.tmf.ui.views.TmfView#createPartControl(org.eclipse + * .swt.widgets.Composite) + */ + @Override + public void createPartControl(Composite parent) { + + scrollFrame = new ScrolledComposite(parent, SWT.V_SCROLL); + + scrollFrame.setExpandVertical(true); + scrollFrame.setExpandHorizontal(true); + scrollFrame.setAlwaysShowScrollBars(true); + + SashForm sash = new SashForm(scrollFrame, SWT.NONE); + scrollFrame.setContent(sash); + + tableViewer = new TableViewer(sash, SWT.FULL_SELECTION | SWT.H_SCROLL); + tableViewer.setContentProvider(new ViewContentProvider(tableViewer)); + tableViewer.setLabelProvider(new ViewLabelProvider()); + Table table = tableViewer.getTable(); + tableViewer.addSelectionChangedListener(new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + ISelection sel = event.getSelection(); + if (!sel.isEmpty()) { + Object firstSel = null; + if (sel instanceof IStructuredSelection) { + firstSel = ((IStructuredSelection) sel).getFirstElement(); + + // Make sure the selection is visible + updateScrollOrigin(); + + if (firstSel instanceof ITmfTimeAnalysisEntry) { + ITmfTimeAnalysisEntry trace = (ITmfTimeAnalysisEntry) firstSel; + tsfviewer.setSelectedTrace(trace); + } + } + } + } + + /** + * Make sure the selected item is visible + */ + private void updateScrollOrigin() { + Table table = tableViewer.getTable(); + if (table != null && table.getItemCount() > 0) { + TableItem item = table.getSelection()[0]; + if (item == null) { + // no selected reference to go up or down + return; + } + + Rectangle itemRect = item.getBounds(); + int step = itemRect.height; + + // calculate height of horizontal bar + int hscrolly = 0; + ScrollBar hbar = scrollFrame.getHorizontalBar(); + if (hbar != null) { + hscrolly = hbar.getSize().y; + } + + int visibleHeight = scrollFrame.getSize().y - hscrolly; + + // the current scrollbar offset to adjust i.e. start + // of + // the visible window + Point origin = scrollFrame.getOrigin(); + // end of visible window + int endy = origin.y + visibleHeight; + + int itemStartPos = itemRect.y + table.getHeaderHeight() + table.getBorderWidth() + + table.getParent().getBorderWidth(); + + // Item End Position + int itemEndPos = itemStartPos + step; + + // check if need to go up + if (origin.y >= step && itemStartPos < origin.y) { + // one step up + scrollFrame.setOrigin(origin.x, origin.y - step); + + } + + // check if it needs to go down + if (itemEndPos > endy) { + // one step down + scrollFrame.setOrigin(origin.x, origin.y + step); + + } + } + } + }); + + // Listen to page up /down and Home / Enc keys + tableViewer.getTable().addKeyListener(new KeyListener() { + public void keyPressed(KeyEvent e) { + Table table = tableViewer.getTable(); + Point origin = scrollFrame.getOrigin(); + if (table == null || table.getItemCount() < 1) { + // nothing to page + return; + } + + TableItem item; + int count; + + switch (e.keyCode) { + case SWT.PAGE_DOWN: + updateScrollPageDown(); + break; + case SWT.PAGE_UP: + updateScrollUp(); + break; + case SWT.HOME: + // Home + count = table.getItemCount(); + item = table.getItem(0); + // Go to the top + scrollFrame.setOrigin(origin.x, 0); + break; + case SWT.END: + // End Selected + count = table.getItemCount(); + item = table.getItem(count - 1); + int itemStartPos = item.getBounds().y; + // Get to the bottom + scrollFrame.setOrigin(origin.x, itemStartPos); + break; + default: + break; + } + } + + public void keyReleased(KeyEvent e) { + // Nothing to do + + } + + /** + * Scroll one page down + */ + private void updateScrollPageDown() { + // null protection before calling private method + Table table = tableViewer.getTable(); + int step = table.getItemHeight(); + + int hscrolly = 0; + ScrollBar hbar = scrollFrame.getHorizontalBar(); + if (hbar != null) { + hscrolly = hbar.getSize().y; + } + + Point origin = scrollFrame.getOrigin(); + int visibleHeight = scrollFrame.getSize().y - hscrolly; + int endy = origin.y + visibleHeight; + + scrollFrame.setOrigin(origin.x, endy - step); + } + + /** + * Scroll one page up + */ + private void updateScrollUp() { + // null protection before calling private method + Table table = tableViewer.getTable(); + int step = table.getItemHeight(); + + int hscrolly = 0; + ScrollBar hbar = scrollFrame.getHorizontalBar(); + if (hbar != null) { + hscrolly = hbar.getSize().y; + } + + Point origin = scrollFrame.getOrigin(); + int visibleHeight = scrollFrame.getSize().y - hscrolly; + int pageUpPos = origin.y - visibleHeight + step; + pageUpPos = pageUpPos > 0 ? pageUpPos : 0; + scrollFrame.setOrigin(origin.x, pageUpPos); + } + + }); + // Describe table + applyTableLayout(table); + + int borderWidth = table.getBorderWidth(); + + int itemHeight = table.getItemHeight() + checkForSWTBugItemHeightAdjustement(); + int headerHeight = table.getHeaderHeight(); + table.getVerticalBar().setVisible(false); + + tsfviewer = TmfViewerFactory.createViewer(sash, + new TimeRangeViewerProvider()); + + tsfviewer.addWidgetSelectionListner(this); + tsfviewer.addWidgetTimeScaleSelectionListner(this); + + // Traces shall not be grouped to allow synchronisation + tsfviewer.groupTraces(false); + tsfviewer.setItemHeight(itemHeight); + tsfviewer.setBorderWidth(borderWidth); + tsfviewer.setHeaderHeight(headerHeight); + tsfviewer.setVisibleVerticalScroll(false); + // Names provided by the table + tsfviewer.setNameWidthPref(0); + tsfviewer.setAcceptSelectionAPIcalls(true); + + // Viewer to notify selection to this class + // This class will synchronise selections with table. + tsfviewer.addWidgetSelectionListner(this); + tsfviewer.addFilterSelectionListner(this); + tsfviewer.addWidgetTimeScaleSelectionListner(this); + + sash.setWeights(new int[] { 1, 1 }); + // Create the help context id for the viewer's control + // TODO: Associate with help system + PlatformUI.getWorkbench().getHelpSystem().setHelp( + tableViewer.getControl(), + "org.eclipse.linuxtools.lttnng.ui.views.flow.viewer"); //$NON-NLS-1$ + + makeActions(); + hookContextMenu(); + hookDoubleClickAction(); + contributeToActionBars(); + + // scrollFrame.addControlListener(new ControlAdapter() { + // + // @Override + // public void controlResized(ControlEvent e) { + // tsfviewer.resizeControls(); + // updateScrolls(scrollFrame); + // } + // }); + + // set the initial view parameter values + // Experiment start and end time + // as well as time space width in pixels, used by the time analysis + // widget + // Read relevant values + int timeSpaceWidth = tsfviewer.getTimeSpace(); + if (timeSpaceWidth < 0) { + timeSpaceWidth = -timeSpaceWidth; + } + + TmfExperiment experiment = TmfExperiment.getCurrentExperiment(); + if (experiment != null) { + TmfTimeRange experimentTRange = experiment.getTimeRange(); + + // send request and received the adjusted time used + TmfTimeRange adjustedTimeRange = initialExperimentDataRequest(this, + experimentTRange); + + // initialize widget time boundaries and filtering parameters + ModelUpdateInit(experimentTRange, adjustedTimeRange, this); + } else { + TraceDebug.debug("No selected experiment information available"); + } + } + + private void hookContextMenu() { + MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$ + menuMgr.setRemoveAllWhenShown(true); + menuMgr.addMenuListener(new IMenuListener() { + public void menuAboutToShow(IMenuManager manager) { + ControlFlowView.this.fillContextMenu(manager); + } + }); + Menu menu = menuMgr.createContextMenu(tableViewer.getControl()); + tableViewer.getControl().setMenu(menu); + getSite().registerContextMenu(menuMgr, tableViewer); + } + + private void contributeToActionBars() { + IActionBars bars = getViewSite().getActionBars(); + fillLocalPullDown(bars.getMenuManager()); + fillLocalToolBar(bars.getToolBarManager()); + } + + private void fillLocalPullDown(IMenuManager manager) { + manager.add(new Separator()); + // manager.add(showLegend); + manager.add(new Separator()); + manager.add(resetScale); + manager.add(nextEvent); + manager.add(prevEvent); + manager.add(nextTrace); + manager.add(prevTrace); + // manager.add(filterTraces); + manager.add(zoomIn); + manager.add(zoomOut); + manager.add(zoomFilter); + manager.add(new Separator()); + } + + private void fillContextMenu(IMenuManager manager) { + // manager.add(showLegend); + manager.add(new Separator()); + manager.add(resetScale); + manager.add(nextEvent); + manager.add(prevEvent); + manager.add(nextTrace); + manager.add(prevTrace); + // manager.add(showLegend); + // manager.add(filterTraces); + manager.add(zoomIn); + manager.add(zoomOut); + manager.add(zoomFilter); + manager.add(new Separator()); + manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); + } + + private void fillLocalToolBar(IToolBarManager manager) { + // manager.add(showLegend); + manager.add(new Separator()); + manager.add(resetScale); + manager.add(nextEvent); + manager.add(prevEvent); + manager.add(nextTrace); + manager.add(prevTrace); + // manager.add(filterTraces); + manager.add(zoomIn); + manager.add(zoomOut); + manager.add(zoomFilter); + manager.add(new Separator()); + } + + private void makeActions() { + // resetScale + resetScale = new Action() { + @Override + public void run() { + if (tsfviewer != null) { + tsfviewer.resetStartFinishTime(); + } + + } + }; + resetScale.setText(Messages.getString("ControlFlowView.Action.Reset")); //$NON-NLS-1$ + resetScale.setToolTipText(Messages + .getString("ControlFlowView.Action.Reset.ToolTip")); //$NON-NLS-1$ + resetScale.setImageDescriptor(AbstractUIPlugin + .imageDescriptorFromPlugin(Messages + .getString("ControlFlowView.tmf.UI"), + "icons/home_nav.gif")); + + // nextEvent + nextEvent = new Action() { + @Override + public void run() { + if (tsfviewer != null) { + tsfviewer.selectNextEvent(); + } + } + }; + nextEvent.setText(Messages + .getString("ControlFlowView.Action.NextEvent")); //$NON-NLS-1$ + nextEvent.setToolTipText(Messages + .getString("ControlFlowView.Action.NextEvent.Tooltip")); //$NON-NLS-1$ + nextEvent.setImageDescriptor(AbstractUIPlugin + .imageDescriptorFromPlugin(Messages + .getString("ControlFlowView.tmf.UI"), + "icons/next_event.gif")); + + // prevEvent + prevEvent = new Action() { + @Override + public void run() { + if (tsfviewer != null) { + tsfviewer.selectPrevEvent(); + } + } + }; + prevEvent.setText(Messages + .getString("ControlFlowView.Action.PrevEvent")); //$NON-NLS-1$ + prevEvent.setToolTipText(Messages + .getString("ControlFlowView.Action.PrevEvent.Tooltip")); //$NON-NLS-1$ + prevEvent.setImageDescriptor(AbstractUIPlugin + .imageDescriptorFromPlugin(Messages + .getString("ControlFlowView.tmf.UI"), + "icons/prev_event.gif")); + + // nextTrace + nextTrace = new Action() { + @Override + public void run() { + if (tsfviewer != null) { + tsfviewer.selectNextTrace(); + } + } + }; + nextTrace.setText(Messages + .getString("ControlFlowView.Action.NextProcess")); //$NON-NLS-1$ + nextTrace.setToolTipText(Messages + .getString("ControlFlowView.Action.NextProcess.ToolTip")); //$NON-NLS-1$ + nextTrace.setImageDescriptor(AbstractUIPlugin + .imageDescriptorFromPlugin(Messages + .getString("ControlFlowView.tmf.UI"), + "icons/next_item.gif")); + + // prevTrace + prevTrace = new Action() { + @Override + public void run() { + if (tsfviewer != null) { + tsfviewer.selectPrevTrace(); + } + } + }; + prevTrace.setText(Messages + .getString("ControlFlowView.Action.PreviousProcess")); //$NON-NLS-1$ + prevTrace.setToolTipText(Messages + .getString("ControlFlowView.Action.PreviousProcess.Tooltip")); //$NON-NLS-1$ + prevTrace.setImageDescriptor(AbstractUIPlugin + .imageDescriptorFromPlugin(Messages + .getString("ControlFlowView.tmf.UI"), + "icons/prev_item.gif")); + + // showLegend + showLegend = new Action() { + @Override + public void run() { + if (tsfviewer != null) { + tsfviewer.showLegend(); + } + } + }; + showLegend.setText(Messages.getString("ControlFlowView.Action.Legend")); //$NON-NLS-1$ + showLegend.setToolTipText(Messages + .getString("ControlFlowView.Action.Legend.ToolTip")); //$NON-NLS-1$ + + // filterTraces + filterTraces = new Action() { + @Override + public void run() { + if (tsfviewer != null) { + tsfviewer.filterTraces(); + } + } + }; + filterTraces.setText(Messages + .getString("ControlFlowView.Action.Filter")); //$NON-NLS-1$ + filterTraces.setToolTipText(Messages + .getString("ControlFlowView.Action.Filter.ToolTip")); //$NON-NLS-1$ + filterTraces.setImageDescriptor(AbstractUIPlugin + .imageDescriptorFromPlugin(Messages + .getString("ControlFlowView.tmf.UI"), + "icons/filter_items.gif")); + + // zoomIn + zoomIn = new Action() { + @Override + public void run() { + if (tsfviewer != null) { + tsfviewer.zoomIn(); + } + } + }; + zoomIn.setText(Messages.getString("ControlFlowView.Action.ZoomIn")); //$NON-NLS-1$ + zoomIn.setToolTipText(Messages + .getString("ControlFlowView.Action.ZoomIn.Tooltip")); //$NON-NLS-1$ + zoomIn.setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin( + Messages.getString("ControlFlowView.tmf.UI"), + "icons/zoomin_nav.gif")); + + // zoomOut + zoomOut = new Action() { + @Override + public void run() { + if (tsfviewer != null) { + tsfviewer.zoomOut(); + } + } + }; + zoomOut.setText(Messages.getString("ControlFlowView.Action.ZoomOut")); //$NON-NLS-1$ + zoomOut.setToolTipText(Messages + .getString("ControlFlowView.Action.ZoomOut.tooltip")); //$NON-NLS-1$ + zoomOut.setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin( + Messages.getString("ControlFlowView.tmf.UI"), + "icons/zoomout_nav.gif")); + + // zoomFilter + zoomFilter = new Action() { + @Override + public void run() { + // Nothing to do, however the selection status is needed by the + // application + } + }; + zoomFilter.setText(Messages + .getString("ControlFlowView.Action.ZoomFilter")); //$NON-NLS-1$ + zoomFilter.setToolTipText(Messages + .getString("ControlFlowView.Action.ZoomFilter.tooltip")); //$NON-NLS-1$ + zoomFilter.setImageDescriptor(AbstractUIPlugin + .imageDescriptorFromPlugin(Messages + .getString("ControlFlowView.tmf.UI"), + "icons/filter_items.gif")); + zoomFilter.setChecked(false); + + // PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_ELCL_SYNCED); + + doubleClickAction = new Action() { + @Override + public void run() { + ISelection selection = tableViewer.getSelection(); + Object obj = ((IStructuredSelection) selection) + .getFirstElement(); + showMessage("Double-click detected on " + obj.toString()); //$NON-NLS-1$ + } + }; + } + + private void hookDoubleClickAction() { + tableViewer.addDoubleClickListener(new IDoubleClickListener() { + public void doubleClick(DoubleClickEvent event) { + doubleClickAction.run(); + } + }); + } + + private void showMessage(String message) { + MessageDialog.openInformation(tableViewer.getControl().getShell(), + Messages.getString("ControlFlowView.msgSlogan"), message); //$NON-NLS-1$ + } + + /** + * Passing the focus request to the viewer's control. + */ + @Override + public void setFocus() { + tableViewer.getControl().setFocus(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView# + * tsfTmProcessSelEvent + * (org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeSelectionEvent + * ) + */ + public void tsfTmProcessSelEvent(TmfTimeSelectionEvent event) { + // common implementation + super.tsfTmProcessSelEvent(event); + + // Reselect the table viewer to widget selection + ISelection sel = tsfviewer.getSelectionTrace(); + if (sel != null && !sel.isEmpty()) { + tableViewer.setSelection(sel); + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis. + * ITmfTimeScaleSelectionListener + * #tsfTmProcessTimeScaleEvent(org.eclipse.linuxtools + * .tmf.ui.viewers.timeAnalysis.TmfTimeScaleSelectionEvent) + */ + public synchronized void tsfTmProcessTimeScaleEvent(TmfTimeScaleSelectionEvent event) { + super.tsfTmProcessTimeScaleEvent(event); + } + + private void applyTableLayout(Table table) { + for (int i = 0; i < columnNames.length; i++) { + TableColumn tableColumn = new TableColumn(table, SWT.LEFT); + tableColumn.setText(columnNames[i]); + tableColumn.pack(); + } + table.setHeaderVisible(true); + table.setLinesVisible(true); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView#displayModel + * (org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model. + * ITmfTimeAnalysisEntry[], long, long, boolean, long, long, + * java.lang.Object) + */ + public void displayModel(final ITmfTimeAnalysisEntry[] items, + final long startBoundTime, final long endBoundTime, + final boolean updateTimeBounds, final long startVisibleWindow, + final long endVisibleWindow, final Object source) { + final Table table = tableViewer.getTable(); + Display display = table.getDisplay(); + + // Perform the updates on the UI thread) + display.asyncExec(new Runnable() { + public void run() { + + tableViewer.setInput(items); // This shall be the minimal + // initial + tableFilter = new ViewProcessFilter(tableViewer); + tableViewer.setFilters(new ViewerFilter[] { tableFilter }); + + resizeTableColumns(table); + table.update(); + tableViewer.refresh(); + + tsfviewer.display(items, startBoundTime, endBoundTime, + updateTimeBounds); + + // validate visible boundaries + if (startVisibleWindow > -1 && endVisibleWindow > -1) { + tsfviewer.setSelectVisTimeWindow(startVisibleWindow, + endVisibleWindow, source); + } + + tsfviewer.resizeControls(); + + // Adjust the size of the vertical scroll bar to fit the + // contents + if (scrollFrame != null) { + updateScrolls(scrollFrame); + } + } + }); + } + + @Override + public void dispose() { + // dispose parent resources + super.dispose(); + + tsfviewer.removeFilterSelectionListner(this); + tsfviewer.removeWidgetSelectionListner(this); + tsfviewer.removeWidgetTimeScaleSelectionListner(this); + tableViewer = null; + tsfviewer = null; + } + + /** + * @param tableComposite + * @param table + */ + private synchronized void resizeTableColumns(Table table) { + if (table != null) { + Composite parent = table.getParent(); + int tableWidthSum = parent.getBorderWidth(); + + TableColumn[] columns = table.getColumns(); + for (TableColumn column : columns) { + column.pack(); + tableWidthSum += column.getWidth(); + } + } + } + + // @Override + public void tmfTaProcessFilterSelection(TmfTimeFilterSelectionEvent event) { + if (tableFilter != null) { + Vector filteredout = event.getFilteredOut(); + if (filteredout != null) { + tableFilter.setFilter(filteredout); + } else { + tableFilter.setFilter(new Vector()); + } + tableViewer.refresh(); + } + } + + /** + * @param scrollFrame + * @param wrapper + */ + private void updateScrolls(final ScrolledComposite scrollFrame) { + scrollFrame.setMinSize(tableViewer.getTable().computeSize(SWT.DEFAULT, SWT.DEFAULT)); + } + + /** + * Registers as listener of time selection from other views + * + * @param signal + */ + @TmfSignalHandler + public void synchToTime(TmfTimeSynchSignal signal) { + super.synchToTime(signal); + } + + /** + * Annotation Registers as listener of time range selection from other views + * The implementation handles the entry of the signal. + * + * @param signal + */ + @TmfSignalHandler + public void synchToTimeRange(TmfRangeSynchSignal signal) { + if (zoomFilter != null) { + synchToTimeRange(signal, zoomFilter.isChecked()); + } + } + + @Override + public void modelIncomplete(ILttngSyntEventRequest request) { + // Nothing to do + // The data will be refreshed on the next request + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView# + * getEventProcessor() + */ + @Override + public ITransEventProcessor getEventProcessor() { + return FlowEventToHandlerFactory.getInstance(); + } + + /** + * @param signal + */ + @TmfSignalHandler + public void experimentSelected( + TmfExperimentSelectedSignal signal) { + if (signal != null) { + TmfTimeRange experimentTRange = signal.getExperiment() + .getTimeRange(); + + // prepare time intervals in widget + ModelUpdateInit(experimentTRange, experimentTRange, signal + .getSource()); + + // request initial data + initialExperimentDataRequest(signal + .getSource(), experimentTRange); + } + } + + /** + * @param source + * @param experimentTRange + * @return Adjusted time window used for the request (smaller window to + * initialize view) + */ + private TmfTimeRange initialExperimentDataRequest(Object source, + TmfTimeRange experimentTRange) { + // Adjust the initial time window to a shorter interval to allow + // user to select the interesting area based on the perspective + TmfTimeRange initTimeWindow = getInitTRange(experimentTRange); + + dataRequest(initTimeWindow, experimentTRange, true); + if (TraceDebug.isDEBUG()) { + TraceDebug.debug("Initialization request time range is: " + + initTimeWindow.getStartTime().toString() + "-" + + initTimeWindow.getEndTime().toString()); + } + + return initTimeWindow; + } + + // *** HACK *** + // + // + // + public int checkForSWTBugItemHeightAdjustement() { + int returnedAjustement = 0; + String desktopSessionName = System.getenv("DESKTOP_SESSION"); + + // Gnome : most common case, no adjustement + if ( desktopSessionName.equals("gnome") ) { + returnedAjustement = 0; + } + // Kde : ajustement of 2 is needed + else if ( desktopSessionName.equals("kde") ) { + returnedAjustement = 2; + } + + return returnedAjustement; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView# + * getParamsUpdater() + */ + @Override + protected ParamsUpdater getParamsUpdater() { + return FlowModelFactory.getParamsUpdater(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView# + * getItemContainer() + */ + @Override + protected ItemContainer getItemContainer() { + return FlowModelFactory.getProcContainer(); + } +} \ No newline at end of file diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/Messages.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/Messages.java new file mode 100644 index 0000000000..a7c8bc99b3 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/Messages.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.controlflow; + +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +public class Messages { + private static final String BUNDLE_NAME = "org.eclipse.linuxtools.lttng.ui.views.controlflow.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 + '!'; + } + } +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/evProcessor/AbsFlowTRangeUpdate.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/evProcessor/AbsFlowTRangeUpdate.java new file mode 100644 index 0000000000..0417d05850 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/evProcessor/AbsFlowTRangeUpdate.java @@ -0,0 +1,214 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are made + * available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Alvaro Sanchez-Leon - Initial implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.controlflow.evProcessor; + +import java.util.Vector; + +import org.eclipse.linuxtools.lttng.state.StateStrings.ProcessStatus; +import org.eclipse.linuxtools.lttng.state.evProcessor.ILttngEventProcessor; +import org.eclipse.linuxtools.lttng.state.model.LttngProcessState; +import org.eclipse.linuxtools.lttng.state.model.LttngTraceState; +import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeComponent; +import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEvent; +import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEventProcess; +import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEvent.Type; +import org.eclipse.linuxtools.lttng.ui.views.common.AbsTRangeUpdate; +import org.eclipse.linuxtools.lttng.ui.views.common.ParamsUpdater; +import org.eclipse.linuxtools.lttng.ui.views.controlflow.model.FlowModelFactory; +import org.eclipse.linuxtools.lttng.ui.views.controlflow.model.FlowProcessContainer; + +public abstract class AbsFlowTRangeUpdate extends AbsTRangeUpdate implements ILttngEventProcessor { + + // ======================================================================== + // Data + // ======================================================================= + + protected FlowProcessContainer procContainer = FlowModelFactory.getProcContainer(); + protected ParamsUpdater params = FlowModelFactory.getParamsUpdater(); + protected static final Long ANY_CPU = 0L; + + + // ======================================================================== + // Methods + // ======================================================================= + protected TimeRangeEventProcess addLocalProcess(LttngProcessState stateProcess, long traceStartTime, long traceEndTime, String traceId) { + // TimeRangeEventProcess localProcess = new TimeRangeEventProcess(id, name, startTime, stopTime, groupName, className) + TimeRangeEventProcess localProcess = new TimeRangeEventProcess( + procContainer.getUniqueId(), stateProcess.getName(), + traceStartTime, traceEndTime, "", stateProcess.getType() + .getInName(), stateProcess.getCpu(), stateProcess + .getInsertion_time()); + + + localProcess.setCreationTime(stateProcess.getCreation_time()); + localProcess.setPid(stateProcess.getPid()); + localProcess.setTgid(stateProcess.getTgid()); + localProcess.setPpid(stateProcess.getPpid()); + localProcess.setName(stateProcess.getName()); + localProcess.setBrand(stateProcess.getBrand()); + localProcess.setTraceID(traceId); + localProcess.setProcessType(stateProcess.getType().getInName()); + procContainer.addItem(localProcess); + return localProcess; + } + + /** + * Used to check if the event is visible within the current visible time + * window + * + * @return + */ + protected boolean withinViewRange(long stime, long etime) { + long windowStartTime = params.getStartTime(); + long windowEndTime = params.getEndTime(); + + // start time is within window + if (stime >= windowStartTime && stime <= windowEndTime) { + // The event or part of it shall be displayed. + return true; + } + + // end time is within window + if (etime >= windowStartTime && etime <= windowEndTime) { + // The event or part of it shall be displayed. + return true; + } + + // check that a portion is within the window + if (stime < windowStartTime && etime > windowEndTime) { + // The time range is bigger than the selected time window and + // crosses it + return true; + } + + return false; + } + + /** + * @param traceSt + * @param startTime + * @param endTime + * @param localProcess + * @param params + * @param stateMode + * @return + */ + protected boolean makeDraw(LttngTraceState traceSt, long startTime, + long endTime, TimeRangeEventProcess localProcess, + ParamsUpdater params, String stateMode) { + + // Determine start and end times to establish duration + Long stime = startTime; + Long etime = endTime; + + if (etime < stime) { + // Validate the sequential order of events + params.incrementEventsDiscardedWrongOrder(); + return false; + } + + // Store the next good time to start drawing the next event + // this is done this early to display an accurate start time of the + // first event + // within the display window + // ****** moved at the end since it produces gaps among the coloured rectangles + // localProcess.setNext_good_time(etime); + if (!withinViewRange(stime, etime)) { + // No use to process the event since it's outside + // the visible time range of the window + params.incrementEventsDiscarded(); + return false; + } + + // Determine if the time range event will fit it the current + // pixel map + double duration = etime - stime; + double k = getPixelsPerNs(traceSt, params); + double pixels = duration * k; + + // Visibility check + // Display a "more information" indication by allowing non visible event + // as long as its previous event is visible. + boolean visible = true; + if (pixels < 1) { + boolean prevEventVisibility = true; + // Get the visibility indication on previous event for + // this process + Vector inMemEvents = localProcess + .getTraceEvents(); + if (inMemEvents.size() != 0) { + TimeRangeComponent prevEvent = inMemEvents.get(inMemEvents + .size() - 1); + prevEventVisibility = prevEvent.isVisible(); + + // if previous event visibility is false and the time span + // between events less than two pixels, there is no need to + // load it in memory i.e. not visible and a more indicator is + // within two pixels. + // return i.e. event discarded to free up memory + Long eventSpan = stime - prevEvent.getStartTime(); + if (prevEventVisibility == false + && ((double) eventSpan * k) < 2) { + + // discard the item + params.incrementEventsDiscarded(); + return false; + + } + } + + // if previous event is visible, set this one to not + // visible and continue + visible = false; + } + + // Create the time-range event + TimeRangeEvent time_window = new TimeRangeEvent(stime, etime, + localProcess, Type.PROCESS_MODE, stateMode); + + time_window.setVisible(visible); + localProcess.getTraceEvents().add(time_window); + localProcess.setNext_good_time(etime); + + return false; + } + + /** + * @param traceSt + * @param evTime + * @param process + * @param localProcess + * @param params + * @return + */ + protected boolean makeDraw(LttngTraceState traceSt, long evTime, + LttngProcessState process, TimeRangeEventProcess localProcess, + ParamsUpdater params) { + + // TmfTimestamp stime = process.getState().getChange_LttTime(); + long stime = localProcess.getNext_good_time(); + + String stateMode; + ProcessStatus procStatus = process.getState().getProc_status(); + // Use Execution mode if process state is RUN otherwise use the actual + // process state, + // this selection will determine the actual color selected for the event + if (procStatus == ProcessStatus.LTTV_STATE_RUN) { + stateMode = process.getState().getExec_mode().getInName(); + } else { + stateMode = procStatus.getInName(); + } + + return makeDraw(traceSt, stime, evTime, localProcess, params, stateMode); + + } + +} \ No newline at end of file diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/evProcessor/FlowAfterUpdateHandlers.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/evProcessor/FlowAfterUpdateHandlers.java new file mode 100644 index 0000000000..0f7c18baf8 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/evProcessor/FlowAfterUpdateHandlers.java @@ -0,0 +1,380 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.controlflow.evProcessor; + +import org.eclipse.linuxtools.lttng.event.LttngEvent; +import org.eclipse.linuxtools.lttng.state.StateStrings.Fields; +import org.eclipse.linuxtools.lttng.state.evProcessor.ILttngEventProcessor; +import org.eclipse.linuxtools.lttng.state.model.LttngProcessState; +import org.eclipse.linuxtools.lttng.state.model.LttngTraceState; +import org.eclipse.linuxtools.lttng.ui.TraceDebug; +import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEventProcess; +import org.eclipse.linuxtools.tmf.event.TmfTimeRange; + +/** + * Creates instances of specific after state update handlers, per corresponding + * event. + * + * @author alvaro + * + */ +class FlowAfterUpdateHandlers { + /** + *

+ * Handles: LTT_EVENT_SCHED_SCHEDULE + *

+ * Replace C function "after_schedchange_hook" in eventhooks.c + *

+ * Fields: LTT_FIELD_PREV_PID, LTT_FIELD_NEXT_PID + *

+ * + * @return + */ + final ILttngEventProcessor getSchedChangeHandler() { + AbsFlowTRangeUpdate handler = new AbsFlowTRangeUpdate() { + + // @Override + public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { + + // get event time, cpu, trace_number, process, pid + LttngProcessState process_in = traceSt.getRunning_process().get(trcEvent.getCpuId()); + + // pid_out is never used, even in LTTv! + //Long pid_out = getAFieldLong(trcEvent, traceSt, Fields.LTT_FIELD_PREV_PID); + Long pid_in = getAFieldLong(trcEvent, traceSt, Fields.LTT_FIELD_NEXT_PID); + + if ( !(pid_in.equals(process_in.getPid())) ) { + TraceDebug.debug("pid_in != PID! (getSchedChangeHandler)"); + } + + //hashed_process_data = processlist_get_process_data(process_list,pid_out,process->cpu,&birth,trace_num); + TimeRangeEventProcess localProcess = procContainer.findProcess(process_in.getPid(), process_in.getCpu(), traceSt.getTraceId(),process_in.getCreation_time() ); + + if ( localProcess == null ) { + if ( (pid_in == 0) || (pid_in != process_in.getPpid()) ) { + TmfTimeRange timeRange = traceSt.getContext().getTraceTimeWindow(); + localProcess = addLocalProcess(process_in, timeRange.getStartTime().getValue(), timeRange.getEndTime().getValue(), traceSt.getTraceId()); + } + else { + TraceDebug + .debug("pid_in is not 0 or pid_in == PPID! (getSchedChangeHandler)"); + } + } + + // There is no drawing done by the C code below, only refreshing + // the references to the current hash data to make it ready for + // next event + + // This current implementation does not support the use of + // current hashed data + // although an equivalent would be good in order to improve the + // time to find the currently running process per cpu. + /* + if(ltt_time_compare(hashed_process_data_in->next_good_time, evtime) <= 0) + { + TimeWindow time_window = lttvwindow_get_time_window(control_flow_data->tab); + + #ifdef EXTRA_CHECK + if(ltt_time_compare(evtime, time_window.start_time) == -1 || ltt_time_compare(evtime, time_window.end_time) == 1) + return FALSE; + #endif //EXTRA_CHECK + + Drawing_t *drawing = control_flow_data->drawing; + guint width = drawing->width; + guint new_x; + + convert_time_to_pixels(time_window,evtime,width,&new_x); + + if(hashed_process_data_in->x.middle != new_x) { + hashed_process_data_in->x.middle = new_x; + hashed_process_data_in->x.middle_used = FALSE; + hashed_process_data_in->x.middle_marked = FALSE; + } + }*/ + + return false; + + } + }; + return handler; + } + + /** + *

+ * Handles: LTT_EVENT_PROCESS_FORK + *

+ * Replace C function "after_process_fork_hook" in eventhooks.c + *

+ * Fields: LTT_FIELD_CHILD_PID + *

+ * + * @return + */ + final ILttngEventProcessor getProcessForkHandler() { + AbsFlowTRangeUpdate handler = new AbsFlowTRangeUpdate() { + + // @Override + public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { + + Long child_pid = getAFieldLong(trcEvent, traceSt, Fields.LTT_FIELD_CHILD_PID); + LttngProcessState process_child = lttv_state_find_process(traceSt, trcEvent.getCpuId(), child_pid ); + + if ( process_child != null ) { + TimeRangeEventProcess localProcess = procContainer.findProcess(process_child.getPid(), process_child.getCpu(), traceSt.getTraceId(), process_child.getCreation_time() ); + + if ( localProcess == null ) { + if ( (child_pid == 0) || (child_pid != process_child.getPpid()) ) { + TmfTimeRange timeRange = traceSt.getContext().getTraceTimeWindow(); + localProcess = addLocalProcess(process_child, timeRange.getStartTime().getValue(), timeRange.getEndTime().getValue(), traceSt.getTraceId()); + } + else { + TraceDebug.debug("localProcess is null with child_pid not 0 or child_pid equals PPID (getProcessForkHandler)"); + } + } else { + // If we found the process, the Ppid and the Tgid might + // be missing, let's add them + localProcess.setPpid(process_child.getPpid()); + localProcess.setTgid(process_child.getTgid()); + } + } + else { + TraceDebug.debug("process_child is null! (getProcessForkHandler)"); + } + + return false; + } + }; + return handler; + } + + /** + *

+ * Handles: LTT_EVENT_PROCESS_EXIT + *

+ * Replace C function "after_process_exit_hook" in eventhooks.c + * + * @return + */ + final ILttngEventProcessor getProcessExitHandler() { + AbsFlowTRangeUpdate handler = new AbsFlowTRangeUpdate() { + + // @Override + public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { + + LttngProcessState process = traceSt.getRunning_process().get(trcEvent.getCpuId()); + + if ( process != null ) { + + // *** TODO: *** + // We shall look into a way to find the current process + // faster, see the c library + // (current_hash) in order to speed up the find. see c-code + // if(likely(process_list->current_hash_data[trace_num][cpu] != NULL) ){ + // hashed_process_data = process_list->current_hash_data[trace_num][cpu]; + // } + TimeRangeEventProcess localProcess = procContainer.findProcess(process.getPid(), process.getCpu(), traceSt.getTraceId(), process.getCreation_time()); + + if ( localProcess == null ) { + if ( (process.getPid() == 0) || (process.getPid() != process.getPpid()) ) { + TmfTimeRange timeRange = traceSt.getContext().getTraceTimeWindow(); + localProcess = addLocalProcess(process, timeRange.getStartTime().getValue(), timeRange.getEndTime().getValue(), traceSt.getTraceId()); + } + else { + TraceDebug.debug("process pid is not 0 or pid equals ppid! (getProcessExitHandler)"); + } + } + } + else { + TraceDebug.debug("process is null! (getProcessExitHandler)"); + } + + return false; + } + }; + return handler; + } + + + /** + *

+ * Handles: LTT_EVENT_EXEC + *

+ * Replace C function "after_fs_exec_hook" in eventhooks.c + * + * @return + */ + final ILttngEventProcessor getProcessExecHandler() { + AbsFlowTRangeUpdate handler = new AbsFlowTRangeUpdate() { + + // @Override + public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { + + LttngProcessState process = traceSt.getRunning_process().get(trcEvent.getCpuId()); + + if ( process != null ) { + + TimeRangeEventProcess localProcess = procContainer.findProcess(process.getPid(), process.getCpu(), traceSt.getTraceId(), process.getCreation_time()); + + if ( localProcess == null ) { + if ( (process.getPid() == 0) || (process.getPid() != process.getPpid()) ) { + TmfTimeRange timeRange = traceSt.getContext().getTraceTimeWindow(); + localProcess = addLocalProcess(process, timeRange.getStartTime().getValue(), timeRange.getEndTime().getValue(), traceSt.getTraceId()); + } + else { + TraceDebug.debug("process pid is not 0 or pid equals ppid! (getProcessExecHandler)"); + } + } + else { + // If we found the process, the name might be missing. Let's add it here. + localProcess.setName(process.getName()); + } + } + else { + TraceDebug.debug("process is null! (getProcessExecHandler)"); + } + + return false; + } + }; + return handler; + } + + /** + *

+ * LTT_EVENT_THREAD_BRAND + *

+ * Replace C function "after_user_generic_thread_brand_hook" in eventhooks.c + * + * @return + */ + final ILttngEventProcessor GetThreadBrandHandler() { + AbsFlowTRangeUpdate handler = new AbsFlowTRangeUpdate() { + + // @Override + public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { + + LttngProcessState process = traceSt.getRunning_process().get(trcEvent.getCpuId()); + + if ( process != null ) { + + // Similar to above comments, implement a faster way to find + // the local process + // if(likely(process_list->current_hash_data[trace_num][cpu] != NULL) ){ + // hashed_process_data = process_list->current_hash_data[trace_num][cpu]; + // } + TimeRangeEventProcess localProcess = procContainer.findProcess(process.getPid(), process.getCpu(), traceSt.getTraceId(), process.getCreation_time()); + + if ( localProcess == null ) { + if ( (process.getPid() == 0) || (process.getPid() != process.getPpid()) ) { + TmfTimeRange timeRange = traceSt.getContext().getTraceTimeWindow(); + localProcess = addLocalProcess(process, timeRange.getStartTime().getValue(), timeRange.getEndTime().getValue(), traceSt.getTraceId()); + } + else { + TraceDebug.debug("process pid is not 0 or pid equals ppid! (GetThreadBrandHandler)"); + } + } + else { + // If we found the process, the brand might be missing + // on it, add it. + localProcess.setBrand(process.getBrand()); + } + } + else { + TraceDebug.debug("process is null! (GetThreadBrandHandler)"); + } + + return false; + + } + }; + return handler; + } + + /** + *

+ * LTT_EVENT_PROCESS_STATE + *

+ * Replace C function "after_event_enum_process_hook" in eventhooks.c + *

+ *

+ * Creates the processlist entry for the child process. Put the last + * position in x at the current time value. + *

+ * + *

+ * Fields: LTT_FIELD_PID + *

+ * + * @return + */ + final ILttngEventProcessor getEnumProcessStateHandler() { + AbsFlowTRangeUpdate handler = new AbsFlowTRangeUpdate() { + + // @Override + public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { + + int first_cpu; + int nb_cpus; + + Long pid_in = getAFieldLong(trcEvent, traceSt, + Fields.LTT_FIELD_PID); + + // Lttv assume that pid_in will NEVER be null or incoherent + // What if ... ? (let's add some debug) + if ( pid_in != null ) { + if(pid_in == 0L) { + first_cpu = 0; + nb_cpus = traceSt.getNumberOfCPUs(); + } + else { + first_cpu = ANY_CPU.intValue(); + nb_cpus = ANY_CPU.intValue() + 1; + } + + for (int cpu = first_cpu; cpu < nb_cpus; cpu++) { + LttngProcessState process_in = lttv_state_find_process(traceSt, trcEvent.getCpuId(), pid_in ); + + if ( process_in != null ) { + TimeRangeEventProcess localProcess = procContainer.findProcess(process_in.getPid(), process_in.getCpu(), traceSt.getTraceId(), process_in.getCreation_time()); + + if (localProcess == null) { + if ( (process_in.getPid() == 0) || (process_in.getPid() != process_in.getPpid()) ) { + TmfTimeRange timeRange = traceSt.getContext().getTraceTimeWindow(); + localProcess = addLocalProcess(process_in, timeRange.getStartTime().getValue(), timeRange.getEndTime().getValue(), traceSt.getTraceId()); + } + else { + TraceDebug.debug("process pid is not 0 or pid equals ppid! (getEnumProcessStateHandler)"); + } + } + else { + // If the process was found, it might be missing informations, add it here + localProcess.setName(process_in.getName()); + localProcess.setPpid(process_in.getPpid()); + localProcess.setTgid(process_in.getTgid()); + } + } + else { + TraceDebug.debug("process_in is null! This should never happen. (getEnumProcessStateHandler)"); + } + } + } + else { + TraceDebug.debug("pid_in is null! This should never happen, really... (getEnumProcessStateHandler)"); + } + + return false; + } + }; + return handler; + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/evProcessor/FlowBeforeUpdateHandlers.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/evProcessor/FlowBeforeUpdateHandlers.java new file mode 100644 index 0000000000..78a9fd2dc0 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/evProcessor/FlowBeforeUpdateHandlers.java @@ -0,0 +1,390 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.controlflow.evProcessor; + +import org.eclipse.linuxtools.lttng.event.LttngEvent; +import org.eclipse.linuxtools.lttng.state.StateStrings.Fields; +import org.eclipse.linuxtools.lttng.state.evProcessor.ILttngEventProcessor; +import org.eclipse.linuxtools.lttng.state.model.LttngProcessState; +import org.eclipse.linuxtools.lttng.state.model.LttngTraceState; +import org.eclipse.linuxtools.lttng.ui.TraceDebug; +import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEventProcess; +import org.eclipse.linuxtools.tmf.event.TmfTimeRange; + +/** + * Creates instances of specific before state update handlers, per corresponding + * event. + * + * @author alvaro + * + */ +class FlowBeforeUpdateHandlers { + /** + *

+ * Handles: LTT_EVENT_SYSCALL_ENTRY + *

+ * Replace C function named "before_execmode_hook" in eventhooks.c + * + * @return + */ + final ILttngEventProcessor getStateModesHandler() { + AbsFlowTRangeUpdate handler = new AbsFlowTRangeUpdate() { + + // @Override + public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { + + Long cpu = trcEvent.getCpuId(); + LttngProcessState stateProcess = traceSt.getRunning_process() + .get(cpu); + // TraceDebug.debug("Before handler called"); + String traceId = traceSt.getTraceId(); + + if (stateProcess != null) { + // Find process within the list of registered time-range + // related + // processes + + // key process attributes to look for it or store it + // are: pid, birth, trace_num, note: cpu not relevant since + // it + // may change + TimeRangeEventProcess localProcess = procContainer + .findProcess(stateProcess.getPid(), stateProcess.getCpu(), traceId, stateProcess + .getCreation_time()); + + // Add process to process list if not present + if (localProcess == null) { + TmfTimeRange timeRange = traceSt.getContext() + .getTraceTimeWindow(); + localProcess = addLocalProcess(stateProcess, timeRange + .getStartTime().getValue(), timeRange + .getEndTime().getValue(), traceId); + } + + // Do the actual drawing + makeDraw(traceSt, trcEvent.getTimestamp().getValue(), + stateProcess, localProcess, params); + } else { + TraceDebug + .debug("Running state process is null! (getStateModesHandler)"); + } + + return false; + } + }; + return handler; + } + + /** + *

+ * Handles: LTT_EVENT_SCHED_SCHEDULE + *

+ * Replace C function named "before_schedchange_hook" in eventhooks.c + *

+ * Fields: LTT_FIELD_PREV_PID, LTT_FIELD_NEXT_PID, LTT_FIELD_PREV_STATE (?) + *

+ * + * @return + */ + final ILttngEventProcessor getBeforeSchedChangeHandler() { + AbsFlowTRangeUpdate handler = new AbsFlowTRangeUpdate() { + + // @Override + public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { + + Long pid_out = getAFieldLong(trcEvent, traceSt, + Fields.LTT_FIELD_PREV_PID); + Long pid_in = getAFieldLong(trcEvent, traceSt, + Fields.LTT_FIELD_NEXT_PID); + + // This is useless even in Lttv !! + // Long state_out = getAFieldLong(trcEvent, traceSt, + // Fields.LTT_FIELD_PREV_STATE); + + // We need to process information. + LttngProcessState process = traceSt.getRunning_process().get( + trcEvent.getCpuId()); + + if (process != null) { + if (process.getPid().equals(pid_out) == false) { + // To replace : + // process = lttv_state_find_process(ts,tfs->cpu, + // pid_out); + process = lttv_state_find_process(traceSt, trcEvent + .getCpuId(), pid_out); + // Also, removed : + // guint trace_num = ts->parent.index; + } + + if (process != null) { + // TODO: Implement something similar to current hash in + // order to keep track of the current process and speed + // up finding the local resource. + + // HashedProcessData *hashed_process_data = NULL; + // hashed_process_data = + // processlist_get_process_data(process_list,pid_out,process->cpu,&birth,trace_num); + TimeRangeEventProcess localProcess = procContainer + .findProcess(process.getPid(), process.getCpu(), traceSt + .getTraceId(), process.getCreation_time()); + + // Add process to process list if not present + // Replace C Call : + // processlist_add(process_list,drawing,pid_out,process->tgid,process->cpu,process->ppid,&birth,trace_num,process->name,process->brand,&pl_height,&process_info,&hashed_process_data); + if (localProcess == null) { + TmfTimeRange timeRange = traceSt.getContext() + .getTraceTimeWindow(); + localProcess = addLocalProcess(process, timeRange + .getStartTime().getValue(), timeRange + .getEndTime().getValue(), traceSt + .getTraceId()); + } + + // Do the actual drawing + makeDraw(traceSt, trcEvent.getTimestamp().getValue(), + process, + localProcess, params); + } else { + // Process may be null if the process started BEFORE the + // trace start + // TraceDebug.debug("Process is null for pid_out! (getBeforeSchedChangeHandler)"); + } + + // PID_IN section + process = lttv_state_find_process(traceSt, trcEvent + .getCpuId(), pid_in); + + if (process != null) { + // HashedProcessData *hashed_process_data = NULL; + // hashed_process_data = + // processlist_get_process_data(process_list, pid_in, + // tfs->cpu, &birth, trace_num); + TimeRangeEventProcess localProcess = procContainer + .findProcess(process.getPid(), process.getCpu(), traceSt + .getTraceId(), process.getCreation_time()); + + // Add process to process list if not present + // Replace C Call : + // processlist_add(process_list, drawing, pid_in, + // process->tgid, tfs->cpu, process->ppid, &birth, + // trace_num, process->name, process->brand, &pl_height, + // &process_info, &hashed_process_data); + if (localProcess == null) { + TmfTimeRange timeRange = traceSt.getContext() + .getTraceTimeWindow(); + localProcess = addLocalProcess(process, timeRange + .getStartTime().getValue(), timeRange + .getEndTime().getValue(), traceSt + .getTraceId()); + } + + // Do the actual drawing + makeDraw(traceSt, trcEvent.getTimestamp().getValue(), + process, + localProcess, params); + + } else { + // Process can be null if it started AFTER the trace + // end. Do nothing... + // TraceDebug.debug("No process found for pid_in! Something is wrong? (getBeforeSchedChangeHandler)"); + } + } else { + TraceDebug + .debug("Running process is null! (getBeforeSchedChangeHandler)"); + } + + return false; + } + }; + + return handler; + } + + /** + *

+ * Handles: LTT_EVENT_PROCESS_EXIT + *

+ * Replace C function named "before_process_exit_hook" in eventhooks.c + * + * @return + */ + final ILttngEventProcessor getProcessExitHandler() { + AbsFlowTRangeUpdate handler = new AbsFlowTRangeUpdate() { + + // @Override + public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { + + // We need to process information. + LttngProcessState process = traceSt.getRunning_process().get( + trcEvent.getCpuId()); + + if (process != null) { + // TODO: Implement a similar method to track the current + // local process in order to speed up finding the local + // resource + + // hashed_process_data = + // processlist_get_process_data(process_list, pid, + // process->cpu, &birth,trace_num); + TimeRangeEventProcess localProcess = procContainer + .findProcess(process.getPid(), process.getCpu(), traceSt + .getTraceId(), process.getCreation_time()); + + // Add process to process list if not present + // Replace C Call : + // processlist_add(process_list, drawing, pid, + // process->tgid, process->cpu, process->ppid, &birth, + // trace_num, process->name, process->brand,&pl_height, + // &process_info, &hashed_process_data); + if (localProcess == null) { + TmfTimeRange timeRange = traceSt.getContext() + .getTraceTimeWindow(); + localProcess = addLocalProcess(process, timeRange + .getStartTime().getValue(), timeRange + .getEndTime().getValue(), traceSt.getTraceId()); + } + + // Call the function that does the actual drawing + makeDraw(traceSt, trcEvent.getTimestamp().getValue(), + process, localProcess, params); + + } else { + TraceDebug + .debug("Running process is null! (getProcessExitHandler)"); + } + + return false; + } + }; + return handler; + } + + /** + *

+ * Handles: LTT_EVENT_PROCESS_FREE + *

+ * Replace C function named "before_process_release_hook" in eventhooks.c + *

+ * Fields: LTT_FIELD_PID + *

+ * + * @return + */ + final ILttngEventProcessor getProcessFreeHandler() { + AbsFlowTRangeUpdate handler = new AbsFlowTRangeUpdate() { + + // @Override + public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { + // PID of the process to release + Long release_pid = getAFieldLong(trcEvent, traceSt, + Fields.LTT_FIELD_PID); + + if ((release_pid != null)) { + LttngProcessState process = lttv_state_find_process( + traceSt, ANY_CPU, release_pid); + if (process != null) { + + // Replace the C call : + // hashed_process_data = + // processlist_get_process_data(process_list,pid,process->cpu,&birth,trace_num); + TimeRangeEventProcess localProcess = procContainer + .findProcess(process.getPid(), process.getCpu(), traceSt + .getTraceId(), process + .getCreation_time()); + + // This is as it was in the C ... ? + if (localProcess == null) { + return false; + } + + // Perform the drawing + makeDraw(traceSt, trcEvent.getTimestamp().getValue(), + process, + localProcess, params); + } + } else { + TraceDebug + .debug("Release_pid is null! (getProcessFreeHandler)"); + } + + return false; + } + }; + return handler; + } + + /** + *

+ * Handles: LTT_EVENT_STATEDUMP_END + *

+ * Replace C function named "before_statedump_end" in eventhooks.c + * + * @return + */ + final ILttngEventProcessor getStateDumpEndHandler() { + AbsFlowTRangeUpdate handler = new AbsFlowTRangeUpdate() { + + // @Override + public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { + + // What's below should replace the following call in C : + // ClosureData closure_data; + // closure_data.events_request = events_request; + // closure_data.tss = tss; + // closure_data.end_time = evtime; + // convert_time_to_pixels(time_window,evtime,width,&closure_data.x_end); + // g_hash_table_foreach(process_list->process_hash, + // draw_closure,(void*)&closure_data); + // + // And the draw is always the same then... + + // The c-library loops through the local processes, search for + // the local processes in the state provider and then draws + // If it's present is the local processes why shuldn't they be + // present in the state provider? + // This seems more direct. and makes sure all processes are + // reflected in the control flow view. + LttngProcessState[] processes = traceSt.getProcesses(); + for (int pos=0; pos < processes.length; pos++) { + LttngProcessState process = processes[pos]; + + // Replace the C call : + // hashed_process_data = + // processlist_get_process_data(process_list,pid,process->cpu,&birth,trace_num); + TimeRangeEventProcess localProcess = procContainer + .findProcess(process.getPid(), process.getCpu(), traceSt + .getTraceId(), process + .getCreation_time()); + + // Add process to process list if not present + if (localProcess == null) { + TmfTimeRange timeRange = traceSt.getContext() + .getTraceTimeWindow(); + localProcess = addLocalProcess(process, timeRange + .getStartTime().getValue(), timeRange + .getEndTime().getValue(), traceSt.getTraceId()); + } + + // Call the function that will does the actual + // drawing + makeDraw(traceSt, trcEvent.getTimestamp().getValue(), + process, localProcess, params); + } + + return false; + } + }; + + return handler; + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/evProcessor/FlowEventToHandlerFactory.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/evProcessor/FlowEventToHandlerFactory.java new file mode 100644 index 0000000000..ea60199f4e --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/evProcessor/FlowEventToHandlerFactory.java @@ -0,0 +1,177 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.controlflow.evProcessor; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.linuxtools.lttng.state.StateStrings; +import org.eclipse.linuxtools.lttng.state.evProcessor.AbsEventToHandlerResolver; +import org.eclipse.linuxtools.lttng.state.evProcessor.ILttngEventProcessor; + +/** + * Builds a Map from string event name to a processing handler object, the + * processors implement the same interface to facilitate transparent methods + * call, + * + * The map key STring is the entry point of the raw events, using a hash speeds + * up the resolution of the appropriate processor + * + * @author alvaro + * + */ +public class FlowEventToHandlerFactory extends AbsEventToHandlerResolver { + // ======================================================================== + // Data + // ======================================================================= + private final Map eventNametoBeforeProcessor = new HashMap(); + private final Map eventNametoAfterProcessor = new HashMap(); + private ILttngEventProcessor finishProcesor = null; + private static FlowEventToHandlerFactory instance = null; + private FlowBeforeUpdateHandlers instantiateBeforeHandler = new FlowBeforeUpdateHandlers(); + private FlowAfterUpdateHandlers instantiateAfterHandler = new FlowAfterUpdateHandlers(); + + // ======================================================================== + // Constructors + // ======================================================================= + private FlowEventToHandlerFactory() { + super(); + // Create one instance of each individual event handler and add the + // instance to the map + + // BEFORE HOOKS + eventNametoBeforeProcessor.put( + StateStrings.Events.LTT_EVENT_SYSCALL_ENTRY.getInName(), + instantiateBeforeHandler.getStateModesHandler()); + + eventNametoBeforeProcessor.put( + StateStrings.Events.LTT_EVENT_SYSCALL_EXIT.getInName(), + instantiateBeforeHandler.getStateModesHandler()); + + eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_TRAP_ENTRY + .getInName(), instantiateBeforeHandler.getStateModesHandler()); + + eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_TRAP_EXIT + .getInName(), instantiateBeforeHandler.getStateModesHandler()); + + eventNametoBeforeProcessor.put( + StateStrings.Events.LTT_EVENT_PAGE_FAULT_ENTRY.getInName(), + instantiateBeforeHandler.getStateModesHandler()); + + eventNametoBeforeProcessor.put( + StateStrings.Events.LTT_EVENT_PAGE_FAULT_EXIT.getInName(), + instantiateBeforeHandler.getStateModesHandler()); + + eventNametoBeforeProcessor.put( + StateStrings.Events.LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY + .getInName(), instantiateBeforeHandler + .getStateModesHandler()); + + eventNametoBeforeProcessor + .put(StateStrings.Events.LTT_EVENT_PAGE_FAULT_NOSEM_EXIT + .getInName(), instantiateBeforeHandler + .getStateModesHandler()); + + eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_IRQ_ENTRY + .getInName(), instantiateBeforeHandler.getStateModesHandler()); + + eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_IRQ_EXIT + .getInName(), instantiateBeforeHandler.getStateModesHandler()); + + eventNametoBeforeProcessor.put( + StateStrings.Events.LTT_EVENT_SOFT_IRQ_ENTRY.getInName(), + instantiateBeforeHandler.getStateModesHandler()); + + eventNametoBeforeProcessor.put( + StateStrings.Events.LTT_EVENT_SOFT_IRQ_EXIT.getInName(), + instantiateBeforeHandler.getStateModesHandler()); + + eventNametoBeforeProcessor.put( + StateStrings.Events.LTT_EVENT_SCHED_SCHEDULE.getInName(), + instantiateBeforeHandler.getBeforeSchedChangeHandler()); + + eventNametoBeforeProcessor.put( + StateStrings.Events.LTT_EVENT_PROCESS_EXIT.getInName(), + instantiateBeforeHandler.getProcessExitHandler()); + + eventNametoBeforeProcessor.put( + StateStrings.Events.LTT_EVENT_PROCESS_FREE.getInName(), + instantiateBeforeHandler.getProcessFreeHandler()); + + eventNametoBeforeProcessor.put( + StateStrings.Events.LTT_EVENT_STATEDUMP_END.getInName(), + instantiateBeforeHandler.getStateDumpEndHandler()); + + + // AFTER HOOKS + eventNametoAfterProcessor.put( + StateStrings.Events.LTT_EVENT_SCHED_SCHEDULE.getInName(), + instantiateAfterHandler.getSchedChangeHandler()); + + eventNametoAfterProcessor.put( + StateStrings.Events.LTT_EVENT_PROCESS_FORK.getInName(), + instantiateAfterHandler.getProcessForkHandler()); + + eventNametoAfterProcessor.put( + StateStrings.Events.LTT_EVENT_PROCESS_EXIT.getInName(), + instantiateAfterHandler.getProcessExitHandler()); + + eventNametoAfterProcessor.put(StateStrings.Events.LTT_EVENT_EXEC + .getInName(), instantiateAfterHandler.getProcessExecHandler()); + + eventNametoAfterProcessor.put( + StateStrings.Events.LTT_EVENT_THREAD_BRAND.getInName(), + instantiateAfterHandler.GetThreadBrandHandler()); + + eventNametoAfterProcessor.put( + StateStrings.Events.LTT_EVENT_PROCESS_STATE.getInName(), + instantiateAfterHandler.getEnumProcessStateHandler()); + + finishProcesor = new FlowFinishUpdateHandler(); + } + + // ======================================================================== + // Public methods + // ======================================================================= + /** + * The event processors are common to all traces an multiple instances will + * use more memory unnecessarily + * + * @return + */ + public static AbsEventToHandlerResolver getInstance() { + if (instance == null) { + instance = new FlowEventToHandlerFactory(); + } + return instance; + } + + @Override + public ILttngEventProcessor getAfterProcessor(String eventType) { + return eventNametoAfterProcessor.get(eventType); + } + + @Override + public ILttngEventProcessor getBeforeProcessor(String eventType) { + return eventNametoBeforeProcessor.get(eventType); + } + + @Override + public ILttngEventProcessor getfinishProcessor() { + return finishProcesor; + } + + @Override + public ILttngEventProcessor getStateUpdaterProcessor(String eventType) { + return null; + } +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/evProcessor/FlowFinishUpdateHandler.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/evProcessor/FlowFinishUpdateHandler.java new file mode 100644 index 0000000000..c441c5d0f1 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/evProcessor/FlowFinishUpdateHandler.java @@ -0,0 +1,109 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are made + * available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Alvaro Sanchez-Leon - Initial implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.controlflow.evProcessor; + +import java.util.Vector; + +import org.eclipse.linuxtools.lttng.event.LttngEvent; +import org.eclipse.linuxtools.lttng.state.StateStrings.Events; +import org.eclipse.linuxtools.lttng.state.evProcessor.ILttngEventProcessor; +import org.eclipse.linuxtools.lttng.state.model.LttngProcessState; +import org.eclipse.linuxtools.lttng.state.model.LttngTraceState; +import org.eclipse.linuxtools.lttng.ui.TraceDebug; +import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeComponent; +import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEvent; +import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEventProcess; + +/** + * Creates specific finish state data request + * + * @author alvaro + * + */ +public class FlowFinishUpdateHandler extends AbsFlowTRangeUpdate + implements ILttngEventProcessor { + + public Events getEventHandleType() { + // No specific event + return null; + } + + public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { + // Draw a last known state to the end of the trace + long endReqTime = traceSt.getContext().getTraceTimeWindow() + .getEndTime().getValue(); + TraceDebug.debug("Number of localProcesses: " + + procContainer.readItems().length); + // to identify the process relevant to the traceState + String traceId = traceSt.getTraceId(); + int numLocalFound = 0; + int numLocalNotFound = 0; + int numWithNoChildren = 0; + for (TimeRangeEventProcess localProcess : procContainer.readItems()) { + LttngProcessState stateProcess = lttv_state_find_process(traceSt, + localProcess.getCpu(), localProcess.getPid()); + + // Drawing the last state for processes related to the current trace + // id. + if (!localProcess.getTraceID().equals(traceId)) { + continue; + } + + // Check if the process is in the state provider, it is the case + // when the requested time frame did not include any events for a + // process + if (stateProcess == null) { + // Get Start time from the end time of previous event + Vector childrenEvents = localProcess + .getTraceEvents(); + long nextGoodTime; + String stateMode; + if (childrenEvents.size() > 0) { + TimeRangeComponent prevEvent = childrenEvents + .get(childrenEvents.size() - 1); + if (prevEvent instanceof TimeRangeEvent) { + TimeRangeEvent prevTimeRange = (TimeRangeEvent) prevEvent; + // calculate the next good time to draw the event + // nextGoodTime = prevTimeRange.getStopTime() + 1; + nextGoodTime = localProcess.getNext_good_time(); + stateMode = prevTimeRange.getStateMode(); + + // Draw with the Local information since the current + // request did + // not contain events related to this process + makeDraw(traceSt, nextGoodTime, + endReqTime, localProcess, params, stateMode); + } else { + TraceDebug + .debug("previous event not instance of TimeRangeEvent?: " + + prevEvent.getClass().getSimpleName()); + } + } else { + numWithNoChildren++; + } + + numLocalNotFound++; + continue; + } + numLocalFound++; + // Draw the last state for this process + + makeDraw(traceSt, endReqTime, stateProcess, localProcess, params); + } + + TraceDebug.debug("Print Last Event: NumLocalFound " + numLocalFound + + "; NumLocalNotFound: " + numLocalNotFound + + "; NumWithNoChildren: " + numWithNoChildren); + + return false; + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/messages.properties b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/messages.properties new file mode 100644 index 0000000000..0260851313 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/messages.properties @@ -0,0 +1,26 @@ +ControlFlowView.Action.Filter=Filter +ControlFlowView.Action.Filter.ToolTip=Process Filter options +ControlFlowView.Action.Legend=Legend +ControlFlowView.Action.Legend.ToolTip=Show Legend +ControlFlowView.Action.LoadData=LoadData +ControlFlowView.Action.LoadData.ToolTip=Load data from external plug-in +ControlFlowView.Action.NextEvent=NextEv +ControlFlowView.Action.NextEvent.Tooltip=Next Event +ControlFlowView.Action.NextProcess=NextProcess +ControlFlowView.Action.NextProcess.ToolTip=Select Next Process +ControlFlowView.Action.PrevEvent=PrevEv +ControlFlowView.Action.PrevEvent.Tooltip=Previous Event +ControlFlowView.Action.PreviousProcess=PreviousProcess +ControlFlowView.Action.PreviousProcess.Tooltip=Select Previous Process +ControlFlowView.Action.Reset=Reset +ControlFlowView.Action.Reset.ToolTip=Reset the Time Scale to Default +ControlFlowView.Action.Synchronize=Synchronise +ControlFlowView.Action.Synchronize.ToolTip=Synchronise by listening to external API selection calls +ControlFlowView.Action.ZoomIn=Zoom In +ControlFlowView.Action.ZoomIn.Tooltip=Zoom In +ControlFlowView.Action.ZoomOut=Zoom Out +ControlFlowView.Action.ZoomOut.tooltip=Zoom Out +ControlFlowView.Action.ZoomFilter=Zoom Filter +ControlFlowView.Action.ZoomFilter.tooltip=Display elements with events within the zoomed time window +ControlFlowView.msgSlogan=Control Flow View +ControlFlowView.tmf.UI=org.eclipse.linuxtools.tmf.ui diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/model/FlowModelFactory.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/model/FlowModelFactory.java new file mode 100644 index 0000000000..25a14ff576 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/model/FlowModelFactory.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.controlflow.model; + +import org.eclipse.linuxtools.lttng.ui.views.common.ParamsUpdater; + +/** + * Instantiates the entry point classes to build the data model for this view + * + * @author alvaro + * + */ +public class FlowModelFactory { + // ======================================================================== + // Data + // ======================================================================== + private static FlowProcessContainer procContainer = null; + private static ParamsUpdater updater = null; + + + // ======================================================================== + // Methods + // ======================================================================== + /** + * Get Process data container + * @return + */ + public static FlowProcessContainer getProcContainer() { + if (procContainer == null) { + procContainer = new FlowProcessContainer(); + } + return procContainer; + } + + public static ParamsUpdater getParamsUpdater() { + if (updater == null) { + updater = new ParamsUpdater(); + } + return updater; + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/model/FlowProcessContainer.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/model/FlowProcessContainer.java new file mode 100644 index 0000000000..edcd1073c0 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/controlflow/model/FlowProcessContainer.java @@ -0,0 +1,251 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.controlflow.model; + +import java.util.HashMap; +import java.util.Iterator; + +import org.eclipse.linuxtools.lttng.TraceDebug; +import org.eclipse.linuxtools.lttng.ui.model.trange.ItemContainer; +import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEventProcess; + +/** + * Contains the processes in use by the Control flow view + * + * @author alvaro + * + */ +public class FlowProcessContainer implements ItemContainer { + // ======================================================================== + // Data + // ======================================================================== + private final HashMap allProcesses = new HashMap(); + private static Integer uniqueId = 0; + + // ======================================================================== + // Constructor + // ======================================================================== + + /** + * Package level constructor + */ + FlowProcessContainer() { + + } + + // ======================================================================== + // Methods + // ======================================================================== + /** + * Interface to add a new process.

+ * + * Note : Process with the same key will be overwritten, it's calling function job to make sure the new process is unique. + * + * @param newProcess The process to add + */ + public void addItem(TimeRangeEventProcess newItem) { + if (newItem != null) { + allProcesses.put(new ProcessKey(newItem), newItem); + } + } + + /** + * Request a unique ID + * + * @return Integer + */ + public Integer getUniqueId() { + return uniqueId++; + } + + /** + * This method is intended for read only purposes in order to keep the + * internal data structure in synch + * + * @return TimeRangeEventProcess[] + */ + public TimeRangeEventProcess[] readItems() { + + // This allow us to return an Array of the correct type of the exact correct dimension, without looping + return allProcesses.values().toArray(new TimeRangeEventProcess[allProcesses.size()]); + } + + /** + * Clear the children information for processes e.g. just before refreshing + * data with a new time range + */ + public void clearChildren() { + TimeRangeEventProcess process = null; + Iterator iterator = allProcesses.keySet().iterator(); + + while (iterator.hasNext()) { + process = allProcesses.get(iterator.next()); + process.reset(); + } + } + + /** + * Clear all process items + */ + public void clearItems() { + allProcesses.clear(); + } + + /** + * Remove the process related to a specific trace e.g. during trace + * removal + * + * @param traceId The trace unique id (trace name?) on which we want to remove process + */ + public void removeItems(String traceId) { + ProcessKey iterKey = null; + + Iterator iterator = allProcesses.keySet().iterator(); + while (iterator.hasNext()) { + iterKey = iterator.next(); + + if (allProcesses.get(iterKey).getTraceID().equals(traceId)) { + allProcesses.remove(iterKey); + } + } + } + + /** + * Search by keys (pid, cpuId, traceId and creationTime)

+ * + * A match is returned if the four arguments received match an entry + * Otherwise null is returned + * + * @param searchedPid The processId (Pid) we are looking for + * @param searchedCpuId The cpu Id we are looking for + * @param searchedTraceID The traceId (trace name?) we are looking for + * @param searchedCreationtime The creation time we are looking for + * + * @return TimeRangeEventProcess + */ + public TimeRangeEventProcess findProcess(Long searchedPid, Long searchedCpuId, String searchedTraceID, Long searchedCreationtime) { + // Get the TimeRangeEventProcess associated to a key we create here + TimeRangeEventProcess foundProcess = allProcesses.get( new ProcessKey(searchedPid, searchedCpuId, searchedTraceID, searchedCreationtime) ); + + return foundProcess; + } +} + + +class ProcessKey { + private TimeRangeEventProcess valueRef = null; + + private Long pid = null; + private Long cpuId = null; + private String traceId = null; + private Long creationtime = null; + + @SuppressWarnings("unused") + private ProcessKey() { } + + public ProcessKey(TimeRangeEventProcess newRef) { + valueRef = newRef; + } + + public ProcessKey(Long newPid, Long newCpuId, String newTraceId, Long newCreationTime) { + pid = newPid; + cpuId = newCpuId; + traceId = newTraceId; + creationtime = newCreationTime; + } + + @Override + public boolean equals(Object obj) { + boolean isSame = false; + + if ( obj instanceof ProcessKey ) { + ProcessKey procKey = (ProcessKey) obj; + + if ( valueRef != null ) { + if ( (procKey.getPid().equals(valueRef.getPid()) ) && + (procKey.getTraceId().equals(valueRef.getTraceID()) ) && + (procKey.getCpuId().equals(valueRef.getCpu()) ) && + (procKey.getCreationtime().equals(valueRef.getCreationTime()) ) ) + { + isSame = true; + } + } + else { + if ( (procKey.getPid().equals(this.pid ) ) && + (procKey.getTraceId().equals(this.traceId ) ) && + (procKey.getCpuId().equals(this.cpuId ) ) && + (procKey.getCreationtime().equals(this.creationtime ) ) ) + { + isSame = true; + } + } + } + else { + TraceDebug.debug("ERROR : The given key is not of the type ProcessKey!" + obj.getClass().toString()); + } + + return isSame; + } + + // *** WARNING : Everything in there work because the check "valueRef != null" is the same for ALL getter + // Do NOT change this check without checking. + public Long getPid() { + if ( valueRef != null ) { + return valueRef.getPid(); + } + else { + return pid; + } + } + + public Long getCpuId() { + if ( valueRef != null ) { + return valueRef.getCpu(); + } + else { + return cpuId; + } + } + + public String getTraceId() { + if ( valueRef != null ) { + return valueRef.getTraceID(); + } + else { + return traceId; + } + } + + public Long getCreationtime() { + if ( valueRef != null ) { + return valueRef.getCreationTime(); + } + else { + return creationtime; + } + } + + @Override + public int hashCode() { + return this.toString().hashCode(); + } + + + @Override + public String toString() { + if ( valueRef != null ) { + return (valueRef.getPid().toString() + ":" + valueRef.getCpu().toString() + ":" + valueRef.getTraceID().toString() + ":" + valueRef.getCreationTime().toString()); + } + + return (pid.toString() + ":" + cpuId.toString() + ":" + traceId.toString() + ":" + creationtime.toString()); + } +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/events/EventsView.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/events/EventsView.java new file mode 100644 index 0000000000..306adfe059 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/events/EventsView.java @@ -0,0 +1,133 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.events; + +import org.eclipse.linuxtools.lttng.event.LttngEventContent; +import org.eclipse.linuxtools.tmf.event.TmfEvent; +import org.eclipse.linuxtools.tmf.ui.views.TmfEventsView; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; + +/** + * EventsView + *

+ * TODO: Implement me. Please. + */ +public class EventsView extends TmfEventsView { + + public static final String ID = "org.eclipse.linuxtools.lttng.ui.views.events"; + + // ------------------------------------------------------------------------ + // Table data + // ------------------------------------------------------------------------ + + // Table column names + private final String TIMESTAMP_COLUMN = "Timestamp"; + private final String SOURCE_COLUMN = "Source"; + private final String TYPE_COLUMN = "Type"; + private final String REFERENCE_COLUMN = "Reference"; + private final String CONTENT_COLUMN = "Content"; + private final String[] columnProperties = new String[] { + TIMESTAMP_COLUMN, + SOURCE_COLUMN, + TYPE_COLUMN, + REFERENCE_COLUMN, + CONTENT_COLUMN + }; + + // Column data + private class ColumnData { + public final String header; + public final int width; + public final int alignment; + + public ColumnData(String h, int w, int a) { + header = h; + width = w; + alignment = a; + } + }; + + private ColumnData[] columnData = new ColumnData[] { + new ColumnData(columnProperties[0], 125, SWT.LEFT), + new ColumnData(columnProperties[1], 100, SWT.LEFT), + new ColumnData(columnProperties[2], 200, SWT.LEFT), + new ColumnData(columnProperties[3], 200, SWT.LEFT), + new ColumnData(columnProperties[4], 100, SWT.LEFT) + }; + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + + public EventsView() { + super(1); + } + + /** + * @param table + * + * FIXME: Add support for column selection + */ + @Override + protected void createColumnHeaders(Table table) { + for (int i = 0; i < columnData.length; i++) { + final TableColumn column = new TableColumn(table, columnData[i].alignment, i); + column.setText(columnData[i].header); + column.setWidth(columnData[i].width); + // TODO: Investigate why the column resizing doesn't work by default + // Anything to do with SWT_VIRTUAL? + column.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + // TODO Auto-generated method stub + } + public void widgetSelected(SelectionEvent e) { + column.pack(); + } + }); + } + } + + /** + * @param event + * @return + */ + @Override + protected String[] extractItemFields(TmfEvent event) { + String[] fields = new String[0]; + + if (event != null) { + fields = new String[] { + event.getTimestamp().toString(), + event.getSource().toString(), + event.getType().toString(), + event.getReference().toString(), + ((LttngEventContent)event.getContent()).toString() + }; + } + return fields; + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "[EventsView]"; + } + + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/ChildrenHistogramCanvas.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/ChildrenHistogramCanvas.java new file mode 100644 index 0000000000..87464d0c65 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/ChildrenHistogramCanvas.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * William Bourque - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.histogram; + +import org.eclipse.swt.widgets.Composite; + +/** + * ChildrenHistogramCanvas + *

+ * Extended implementation of the HistogramCanvas. + *

+ * This canvas goal is to display the "SelectionWindow" in details. + */ +public class ChildrenHistogramCanvas extends HistogramCanvas { + + protected HistogramView parentHistogramWindow = null; + + /** + * ChildrenHistogramCanvas constructor.

+ * Same as HistogramCanvas, but receive a parent HistogramView that we can call from here. + * + * @param parent Composite control which will be the parent of the new instance (cannot be null) + * @param Style the style of control to construct + */ + public ChildrenHistogramCanvas(HistogramView newParentWindow, Composite parent, int style) { + super(parent, style); + + parentHistogramWindow = newParentWindow; + } + + /** + * Notify the parent HistogramView that we have updated information.

+ * This is intended to be called at the end of the request when we know we have up-to-date information. + */ + @Override + public void notifyParentUpdatedInformation() { + parentHistogramWindow.updateSelectedWindowInformation(); + } +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramCanvas.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramCanvas.java new file mode 100644 index 0000000000..b362367446 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramCanvas.java @@ -0,0 +1,369 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * William Bourque - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.histogram; + +import org.eclipse.swt.widgets.Canvas; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; + +/** + * HistogramCanvas + *

+ * Canvas implementation aimed to draw histograms. + *

+ * This canvas goal is to display certain "HistogramContent" onto an histogram.

+ * Several method exist to extend it so it should suit most needs. + */ +public class HistogramCanvas extends Canvas +{ + protected AsyncCanvasRedrawer canvasRedrawer = null; + protected HistogramContent histogramContent = null; + + protected HistogramCanvasPaintListener paintListener = null; + protected HistogramCanvasMouseListener mouseListener = null; + protected HistogramCanvasKeyListener keyListener = null; + protected HistogramCanvasFocusListener focusListener = null; + protected HistogramCanvasControlListener controlListener = null; + + protected HistogramSelectedWindow currentWindow = null; + + + /** + * HistogramCanvas constructor + * + * @param parent Composite control which will be the parent of the new instance (cannot be null) + * @param Style the style of control to construct + */ + public HistogramCanvas(Composite parent, int style) { + super(parent, style); + addNeededListeners(); + + // New selected window, not visible by default + createNewSelectedWindow(0L); + } + + /* + * Create the needed "event listeners" and hook them to the Canvas. + */ + protected void addNeededListeners() { + createAndAddCanvasRedrawer(); + createAndAddPaintListener(); + createAndAddMouseListener(); + createAndAddKeyListener(); + createAndAddFocusListener(); + createAndAddControlListener(); + } + + /* + * Create a canvas redrawer and bind it to this canvas.

+ * + * Note : AsyncCanvasRedrawer is an internal class + * This is used to redraw the canvas from a different thread + * without^H^H^H with less danger. + */ + protected void createAndAddCanvasRedrawer() { + canvasRedrawer = new AsyncCanvasRedrawer(this); + } + + /* + * Create a histogram paint listener and bind it to this canvas.

+ * + * @see org.eclipse.linuxtools.lttng.ui.views.histogram.HistogramCanvasPaintListener + */ + protected void createAndAddPaintListener() { + paintListener = new HistogramCanvasPaintListener(this); + this.addPaintListener( paintListener ); + } + + /* + * Create a histogram mouse listener and bind it to this canvas.

+ * Note : this mouse listener handle the mouse, the move and the wheel at once. + * + * @see org.eclipse.linuxtools.lttng.ui.views.histogram.HistogramCanvasMouseListener + */ + protected void createAndAddMouseListener() { + mouseListener = new HistogramCanvasMouseListener(this); + this.addMouseListener(mouseListener); + this.addMouseMoveListener(mouseListener); + this.addMouseWheelListener(mouseListener); + } + + /* + * Create a histogram key listener and bind it to this canvas.

+ * + * @see org.eclipse.linuxtools.lttng.ui.views.histogram.HistogramCanvasKeyListener + */ + protected void createAndAddKeyListener() { + keyListener = new HistogramCanvasKeyListener(this); + this.addKeyListener(keyListener); + } + + /* + * Create a histogram focus listener and bind it to this canvas.

+ * + * @see org.eclipse.linuxtools.lttng.ui.views.histogram.HistogramCanvasFocusListener + */ + protected void createAndAddFocusListener() { + focusListener = new HistogramCanvasFocusListener(this); + this.addFocusListener(focusListener); + } + + /* + * Create a histogram control listener and bind it to this canvas.

+ * + * @see org.eclipse.linuxtools.lttng.ui.views.histogram.HistogramCanvasControlListener + */ + protected void createAndAddControlListener() { + controlListener = new HistogramCanvasControlListener(this); + this.addControlListener(controlListener); + } + + /** + * Create a new HistogramContent for this HistogramCanvas

+ * A new empty content will then be created. + * + * IMPORTANT NOTE : Canvas size, bar width and bar height need to be known at this point, as these dimension are used to create a content + * of the correct size. + * + * @param canvasSize Size of the parent canvas. + * @param widthPerBar Width of the histogram "bars" + * @param barsHeight Height of the histogram "bars" + * @param maxBarsDifferenceToAverage Factor used to "chop" bars that are too tall. Set to something big (100.0?) if not needed. + */ + public void createNewHistogramContent(int canvasSize, int widthPerBar, int barsHeight, double maxBarsDifferenceToAverage) { + histogramContent = new HistogramContent( canvasSize / widthPerBar, canvasSize, widthPerBar, barsHeight, maxBarsDifferenceToAverage); + } + + /** + * Create a new selection window of the size (time width) given.

+ * The window initial position is at X = 0. + * The window is created hidden, it won't be draw unless it is set to visible.

+ * + * @param windowTimeDuration Time width (in nanosecond) of the window. + */ + public void createNewSelectedWindow(long windowTimeDuration) { + currentWindow = new HistogramSelectedWindow(histogramContent); + + currentWindow.setWindowTimeWidth(windowTimeDuration); + currentWindow.setWindowXPositionCenter(0); + } + + public HistogramContent getHistogramContent() { + return histogramContent; + } + + /** + * Getter for the selection window

+ * + * @return the current selection window + * + * @see org.eclipse.linuxtools.lttng.ui.views.histogram.HistogramSelectedWindow + */ + public HistogramSelectedWindow getCurrentWindow() { + return currentWindow; + } + + /** + * Getter for the selection window width

+ * + * @return Time width (in nanosecond) of the selection window. + */ + public long getSelectedWindowSize() { + return currentWindow.getWindowTimeWidth(); + } + + /** + * Setter for the selection window width

+ * The window size will be ajusted if it does not respect one of these constraints : + * - The window size cannot be smaller than a single histogram content interval.

+ * - The window size cannot be larger than twice the histogram content complete time interval.

+ * + * @param newSelectedWindowSize New time width (in nanosecond) of the selection window. + */ + public void setSelectedWindowSize(long newSelectedWindowSize) { + + if ( newSelectedWindowSize <= 0 ) { + newSelectedWindowSize = 1L; + } + else if ( newSelectedWindowSize > (2*histogramContent.getCompleteTimeInterval()) ) { + newSelectedWindowSize = (2*histogramContent.getCompleteTimeInterval()); + } + + currentWindow.setWindowTimeWidth(newSelectedWindowSize); + } + + /** + * Method to call the "Asynchronous redrawer" for this canvas

+ * This allow safe redraw from different threads. + * + */ + public void redrawAsynchronously() { + // Create a new redrawer in case it doesn't exist yet (we never know with thread!) + if ( canvasRedrawer == null ) { + canvasRedrawer = new AsyncCanvasRedrawer(this); + } + + canvasRedrawer.asynchronousRedraw(); + } + + /** + * Method to call the "Asynchronous NotifyParentSelectionWindowChanged" for this canvas

+ * This allow safe update UI objects from different threads. + * + */ + public void notifyParentSelectionWindowChangedAsynchronously() { + // Create a new redrawer in case it doesn't exist yet (we never know with thread!) + if ( canvasRedrawer == null ) { + canvasRedrawer = new AsyncCanvasRedrawer(this); + } + + canvasRedrawer.asynchronousNotifyParentSelectionWindowChanged(); + } + + /** + * Method to call the "Asynchronous NotifyParentUpdatedInformation" for this canvas

+ * This allow safe redraw from different threads. + * + */ + public void notifyParentUpdatedInformationAsynchronously() { + // Create a new redrawer in case it doesn't exist yet (we never know with thread!) + if ( canvasRedrawer == null ) { + canvasRedrawer = new AsyncCanvasRedrawer(this); + } + + canvasRedrawer.asynchronousNotifyParentUpdatedInformation(); + } + + /** + * Function that is called when the selection window is moved.

+ * Note: Given position should be relative to the previous (centered) absolute position. + * + * METHOD INTENDED TO BE EXTENDED + * + * @param newRelativeXPosition New position relative to the last known absolute position. + */ + public void moveWindow(int newRelativeXPosition) { + // Nothing : function is a place holder + } + + /** + * Function that is called when the selection window is re-centered.

+ * Note: Given position should be absolute to the window and need to be the selection window center. + * + * METHOD INTENDED TO BE EXTENDED + * + * @param newRelativeXPosition New absolute position. + */ + public void setWindowCenterPosition(int newAbsoluteXPosition) { + // Nothing : function is a place holder + } + + /** + * Function that is called when the selection window size (time width) changed by an absolute time.

+ * Note: Given time should be in nanoseconds, positive. + * + * METHOD INTENDED TO BE EXTENDED + * + * @param newTime New absoulte time (in nanoseconds) to apply to the window. + */ + public void resizeWindowByAbsoluteTime(long newTime) { + // Nothing : function is a place holder + } + + /** + * Function that is called to tell the parent that the selection window changed.

+ * + * METHOD INTENDED TO BE EXTENDED + * + */ + public void notifyParentSelectionWindowChanged() { + // Nothing : function is a place holder + } + + /** + * Function that is called to tell the parent that some information changed.

+ * + * METHOD INTENDED TO BE EXTENDED + * + */ + public void notifyParentUpdatedInformation() { + // Nothing : function is a place holder + } +} + + +/** + * AsyncCanvasRedrawer Inner Class + *

+ * Asynchronous redrawer for the HistogramCanvas + *

+ * This class role is to call method that update the UI on asynchronously. + * This should prevent any "invalid thread access" exception when trying to update UI from a different thread. + */ +class AsyncCanvasRedrawer { + + private HistogramCanvas parentCanvas = null; + + /** + * AsyncCanvasRedrawer constructor. + * + * @param newCanvas Related histogram canvas. + */ + public AsyncCanvasRedrawer(HistogramCanvas newCanvas) { + parentCanvas = newCanvas; + } + + /** + * Function to redraw the related canvas asynchonously.

+ * + * Basically, it just run "canvas.redraw()" in asyncExec. + * + */ + public void asynchronousRedraw() { + Display display = parentCanvas.getDisplay(); + display.asyncExec(new Runnable() { + public void run() { + parentCanvas.redraw(); + } + }); + } + + /** + * Function to asynchonously notify the parent of the related canvas that the window changed.

+ * + * Basically, it just run "notifyParentSelectionWindowChanged()" in asyncExec. + * + */ + public void asynchronousNotifyParentSelectionWindowChanged() { + Display display = parentCanvas.getDisplay(); + display.asyncExec(new Runnable() { + public void run() { + parentCanvas.notifyParentSelectionWindowChanged(); + } + }); + } + + /** + * Function to asynchonously notify the parent of the related canvas that information changed.

+ * + * Basically, it just run "notifyParentUpdatedInformation()" in asyncExec. + * + */ + public void asynchronousNotifyParentUpdatedInformation() { + Display display = parentCanvas.getDisplay(); + display.asyncExec(new Runnable() { + public void run() { + parentCanvas.notifyParentUpdatedInformation(); + } + }); + } +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramCanvasControlListener.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramCanvasControlListener.java new file mode 100644 index 0000000000..f361717efb --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramCanvasControlListener.java @@ -0,0 +1,63 @@ +package org.eclipse.linuxtools.lttng.ui.views.histogram; + +import org.eclipse.swt.events.ControlEvent; +import org.eclipse.swt.events.ControlListener; + +/** + * HistogramCanvasControlListener + *

+ * Implementation of a ControlListener for the need of the HistogramCanvas + *

+ */ +public class HistogramCanvasControlListener implements ControlListener { + + protected HistogramCanvas parentCanvas = null; + + /** + * HistogramCanvasControlListener constructor + * + * @param newCanvas Related canvas + */ + public HistogramCanvasControlListener(HistogramCanvas newCanvas) { + parentCanvas = newCanvas; + } + + + /** + * Method called when the canvas is moved.

+ * + * Just redraw the canvas... + * + * @param event The controle event generated by the move. + */ + public void controlMoved(ControlEvent event) { + parentCanvas.redraw(); + } + + /** + * Method called when the canvas is resized.

+ * + * We need to tell the content that the canvas size changed and to recenter the windows + * + * @param event The control event generated by the resize. + */ + public void controlResized(ControlEvent event) { + + if ( (parentCanvas != null) && (parentCanvas.getHistogramContent() != null) ) { + int newSize = parentCanvas.getSize().x; + int oldSize = parentCanvas.getHistogramContent().getCanvasWindowSize(); + + // Set the new canvas size + parentCanvas.getHistogramContent().setCanvasWindowSize(newSize); + + // Try to recenter to window at the same place it was + // Note : this is a best hope approach and is not intended to be precise; + // the idea is to avoid issuing a (maybe) long request fo the selection window; + // There WILL be slight discrepancy between the "window values" (timestamp, etc...) showed + // and what it really points to. The user should reclick by himself to refresh it. + int oldWindowCenter = parentCanvas.getCurrentWindow().getWindowXPositionCenter(); + int newWindowCenter = (int)Math.ceil((double)newSize * ((double)oldWindowCenter / (double)oldSize)); + parentCanvas.setWindowCenterPosition(newWindowCenter); + } + } +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramCanvasFocusListener.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramCanvasFocusListener.java new file mode 100644 index 0000000000..8bf3dffe0b --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramCanvasFocusListener.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * William Bourque - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.histogram; + +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; + +/** + * HistogramCanvasFocusListener + *

+ * Implementation of a FocusListener for the need of the HistogramCanvas + *

+ */ +public class HistogramCanvasFocusListener implements FocusListener { + + protected HistogramCanvas parentCanvas = null; + + /** + * HistogramCanvasFocusListener constructor + * + * @param newCanvas Related canvas + */ + public HistogramCanvasFocusListener(HistogramCanvas newCanvas) { + parentCanvas = newCanvas; + } + + /** + * Function that is called when the canvas get focus.

+ * + * Redraw the screen to make sure everything is sane. + * + * @param event The focus event generated. + */ + public void focusGained(FocusEvent event) { + parentCanvas.redrawAsynchronously(); + } + + /** + * Function that is called when the canvas loose focus.

+ * + * Doesn't do anything yet... + * + * @param event The focus event generated. + */ + public void focusLost(FocusEvent event) { + // Nothing to do yet + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramCanvasKeyListener.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramCanvasKeyListener.java new file mode 100644 index 0000000000..84408e15ca --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramCanvasKeyListener.java @@ -0,0 +1,95 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * William Bourque - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.histogram; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; + +/** + * HistogramCanvasKeyListener + *

+ * Implementation of a KeyListener for the need of the HistogramCanvas + *

+ */ +public class HistogramCanvasKeyListener implements KeyListener +{ + protected HistogramCanvas parentCanvas = null; + protected boolean isShiftPressed = false; + + /** + * HistogramCanvasKeyListener constructor + * + * @param newCanvas Related canvas + */ + public HistogramCanvasKeyListener(HistogramCanvas newCanvas) { + parentCanvas = newCanvas; + } + + /** + * Function that is called when a key is pressed.

+ * Possible actions : + * - Left arrow : move the selection window left.

+ * - Right arrow : move the selection window right.

+ * - Shift : turn on "fast move" mode.

+ * + * @param event The KeyEvent generated when the key was pressed. + */ + public void keyPressed(KeyEvent event) { + switch (event.keyCode) { + case SWT.SHIFT: + isShiftPressed = true; + break; + case SWT.ARROW_LEFT: + moveWindowPosition(HistogramConstant.BASIC_DISPLACEMENT_FACTOR * -1); + break; + case SWT.ARROW_RIGHT: + moveWindowPosition(HistogramConstant.BASIC_DISPLACEMENT_FACTOR); + break; + default: + break; + } + } + + /** + * Function that is called when a key is released.

+ * Possible actions : + * - Shift : turn off "fast move" mode. + * + * @param event The KeyEvent generated when the key was pressed. + */ + public void keyReleased(KeyEvent event) { + switch (event.keyCode) { + case SWT.SHIFT: + isShiftPressed = false; + break; + default: + break; + } + } + + /** + * Function to move the window position of a given displacemnt.

+ * + * @param displacementFactor The basic displacement to perform (positive or negative value) + */ + public void moveWindowPosition(int displacementFactor) { + + // If we are in "fast move mode", multiply the basic displacement by a factor + if ( isShiftPressed == true ) { + displacementFactor = (int)((double)displacementFactor * HistogramConstant.FAST_DISPLACEMENT_MULTIPLE); + } + + parentCanvas.moveWindow(displacementFactor); + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramCanvasMouseListener.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramCanvasMouseListener.java new file mode 100644 index 0000000000..7c06cd6ae0 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramCanvasMouseListener.java @@ -0,0 +1,233 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * William Bourque - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.histogram; + +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.events.MouseMoveListener; +import org.eclipse.swt.events.MouseWheelListener; + +/** + * HistogramCanvasMouseListener + *

+ * Implementation of a MouseListener for the need of the HistogramCanvas + *

+ */ +public class HistogramCanvasMouseListener implements MouseMoveListener, MouseListener, MouseWheelListener +{ + protected DelayedMouseScroll mouseScrollListener = null; + protected HistogramCanvas parentCanvas = null; + + protected boolean isWindowMoving = false; + + /** + * HistogramCanvasMouseListener constructor + * + * @param newCanvas Related canvas + */ + public HistogramCanvasMouseListener(HistogramCanvas newCanvas) { + parentCanvas = newCanvas; + } + + /** + * Function called when the mouse is moved.

+ * If the mouse button is clicked, we will move the selection window. + * + * @param event The generated mouse event when the mouse moved. + */ + public void mouseMove(MouseEvent event) { + if ( isWindowMoving == true ) { + parentCanvas.setWindowCenterPosition(event.x); + } + } + + /** + * Function called when the mouse buttons are clicked.

+ * If the button is the first one (left button), turn on the "move window" mode + * + * @param event The generated mouse event when the mouse button was pressed. + */ + public void mouseDown(MouseEvent event) { + if ( event.button == 1) { + isWindowMoving = true; + parentCanvas.setWindowCenterPosition(event.x); + } + } + + /** + * Function called when the mouse buttons are released.

+ * If the button is the first one (left button), turn off the "move window" mode + * + * @param event The generated mouse event when the mouse button was released. + */ + public void mouseUp(MouseEvent event) { + if ( event.button == 1) { + isWindowMoving = false; + parentCanvas.notifyParentSelectionWindowChangedAsynchronously(); + } + } + + /** + * Function called when the mouse perform a double-click.

+ * Don't do anything yet... + * + * @param event The generated mouse event when the mouse double-click was issued. + */ + public void mouseDoubleClick(MouseEvent event) { + System.out.println("mouseDoubleClick"); + } + + /** + * Function called when the mouse scroll button is used.

+ * Start a "ScrollListener" that will wait for more scroll clicks as they are asynchonous. + * After a certain delay, the parent canvas will get notified. + * + * @param event The generated mouse event when the mouse scroll was spinned. + */ + public void mouseScrolled(MouseEvent event) { + + // Start a scrollListener if none exist yet and start its thread + // Otherwise, we will just notify the one that is currenly alive... + // Badly timed event could happen while the thread is dying but we can live with loss scroll events, I believe. + if ( mouseScrollListener == null ) { + mouseScrollListener = new DelayedMouseScroll(this, HistogramConstant.FULL_WAIT_MS_TIME_BETWEEN_MOUSE_SCROLL, HistogramConstant.INTERVAL_WAIT_MS_TIME_BETWEEN_POLL ); + mouseScrollListener.start(); + } + + // *** NOTE *** + // We need to refer to the "count" to know if the scroll is done backward or forward. + // Positive count mean it is done backward (from the wall in the direction of the hand) + // Negative count mean it is done backward (from the hand in the direction of the wall) + if ( event.count > 0) { + mouseScrollListener.incrementMouseScroll(); + } + else { + mouseScrollListener.decrementMouseScroll(); + } + } + + /** + * Function that will be called at the end of the "wait time" for scroll events.

+ * This will calculate the correct zoom time and call the canvas to resize its selection window. + * + * @param nbMouseScroll + */ + public void receiveMouseScrollCount(int nbMouseScroll) { + mouseScrollListener = null; + + long ajustedTime = 0; + + // If we received Negative scroll event, ZoomOut by ZOOM_OUT_FACTOR * the number of scroll events received. + if ( nbMouseScroll < 0 ) { + ajustedTime = (long)((double)parentCanvas.getSelectedWindowSize() * HistogramConstant.ZOOM_OUT_FACTOR); + ajustedTime = ajustedTime * Math.abs(nbMouseScroll); + ajustedTime = parentCanvas.getSelectedWindowSize() + ajustedTime; + } + // If we received Positive scroll event, ZoomIn by ZOOM_IN_FACTOR * the number of scroll events received. + else { + ajustedTime = (long)((double)parentCanvas.getSelectedWindowSize() * HistogramConstant.ZOOM_IN_FACTOR); + ajustedTime = ajustedTime * Math.abs(nbMouseScroll); + ajustedTime = parentCanvas.getSelectedWindowSize() - ajustedTime; + } + + // Resize the canvas selection window + parentCanvas.resizeWindowByAbsoluteTime(ajustedTime); + } + +} + +/** + * DelayedMouseScroll Inner Class + *

+ * Asynchronous "Mouse Scroll Listener" + *

+ * This class role is to wait for mouse scroll and count them during a certain delay.

+ * Once the time is up, it will notify the mouse listener of the number of scroll events received.

+ * + * Note that a new scroll event received will reset the wait timer. + */ +class DelayedMouseScroll extends Thread { + + private HistogramCanvasMouseListener mouseListener = null; + + private long waitTimeBetweenScroll = 0; + private long waitTimeBetweenCheck = 0; + + private long lastScrollTime = 0L; + private int nbScrollClick = 0; + + /** + * Constructor of the DelayedMouseScroll listener.

+ * Object will be initialized but start() need to be called for it start listening for scroll. + * + * @param newListener The parent mouse listener + * @param newWaitFullTime The time to wait for scroll events + * @param newWaitBeforeCheck The delay between polling for scroll events + */ + public DelayedMouseScroll(HistogramCanvasMouseListener newListener, long newWaitFullTime, long newWaitBeforePoll) { + + mouseListener = newListener; + + // Get the current system time. + // This will be used to determine since how long we wait for click + lastScrollTime = System.currentTimeMillis(); + + waitTimeBetweenScroll = newWaitFullTime; + waitTimeBetweenCheck = newWaitBeforePoll; + } + + /** + * Increment the counter for the number of scroll events received.

+ * This is intended to be called by the MouseListener. + * + * Note : A new scroll event receive will reset the wait timer. + */ + public void incrementMouseScroll() { + // Reset the wait timer + lastScrollTime = System.currentTimeMillis(); + nbScrollClick++; + } + + /** + * Decrement the counter for the number of scroll events received.

+ * This is intended to be called by the MouseListener. + * + * Note : A new scroll event receive will reset the wait timer. + */ + public void decrementMouseScroll() { + // Reset the wait timer + lastScrollTime = System.currentTimeMillis(); + nbScrollClick--; + } + + /** + * Threaded execution method.

+ * This is the real "wait" method that will wait for mouse scroll events.

+ * + * The function will wake every "waitTimeBetweenCheck" to check if we exhausted the timer.

+ * So, the "longest" we could wait after the last event is "waitTimeBetweenScroll" + "waitTimeBetweenCheck" + * + */ + @Override + public void run() { + // Check if we waited more than "waitTimeBetweenScroll" + while ( (System.currentTimeMillis() - lastScrollTime) < waitTimeBetweenScroll ) { + try { + Thread.sleep(waitTimeBetweenCheck); + } + catch (Exception e) { } + } + + // Tell the mouse listener the number of click received + mouseListener.receiveMouseScrollCount(nbScrollClick); + } +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramCanvasPaintListener.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramCanvasPaintListener.java new file mode 100644 index 0000000000..5b5cc86b00 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramCanvasPaintListener.java @@ -0,0 +1,167 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * William Bourque - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.histogram; + +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.graphics.Rectangle; + +/** + * HistogramCanvasPaintListener + *

+ * Implementation of a PaintListener for the need of the HistogramCanvas + *

+ */ +public class HistogramCanvasPaintListener implements PaintListener +{ + protected HistogramCanvas parentCanvas = null; + + /** + * HistogramCanvasPaintListener constructor + * + * @param parentCanvas Related canvas + */ + public HistogramCanvasPaintListener(HistogramCanvas newParentCanvas) { + parentCanvas = newParentCanvas; + } + + /** + * Function called when the canvas need to redraw.

+ * + * @param event The generated paint event when redraw is called. + */ + public void paintControl(PaintEvent event) { + + // First clear the whole canvas to have a clean section where to draw + clearDrawingSection(event); + + // If the content is null or has rady to draw we quit the function here + if ( (parentCanvas.getHistogramContent() == null) || (parentCanvas.getHistogramContent().getReadyUpToPosition() == 0) ) { + return; + } + + // Call the function that draw the bars + drawHistogram(event); + + // Pinpoint a position if set + if (parentCanvas.getHistogramContent().getSelectedEventTimeInWindow() > 0 ) { + drawSelectedEventInWindow(event); + } + + // If we have a selected window set to visible, call the function to draw it + if ( (parentCanvas.getCurrentWindow() != null) && (parentCanvas.getCurrentWindow().getSelectedWindowVisible() == true) ) { + drawSelectedWindow(event); + } + } + + /** + * Clear the drawing section of the canvas

+ * This paint the whole background in EMPTY_BACKGROUND_COLOR, so we have something clean to draw on. + * + * @param event The generated paint event when redraw is called. + */ + public void clearDrawingSection(PaintEvent event) { + event.gc.setForeground(event.display.getSystemColor(HistogramConstant.EMPTY_BACKGROUND_COLOR)); + event.gc.setBackground(event.display.getSystemColor(HistogramConstant.EMPTY_BACKGROUND_COLOR)); + Rectangle allSection = new Rectangle(0, 0, event.width, event.height); + event.gc.fillRectangle(allSection); + event.gc.drawRectangle(allSection); + } + + // *** VERIFY *** + // Is it good to put this synchronized? + // + /** + * Draw the histogram bars in the canvas.

+ * Use existing elements in HistogramContent to draw bars on the cancas; + * the element table in content need to be populated and have consistent value. + * + * @param event The generated paint event when redraw is called. + */ + public synchronized void drawHistogram(PaintEvent event) { + HistogramContent tmpContent = parentCanvas.getHistogramContent(); + int tmpBarWidth = tmpContent.getBarsWidth(); + + // This will be the color for all the bars that wil be draw below. + event.gc.setBackground(event.display.getSystemColor(HistogramConstant.HISTOGRAM_BARS_COLOR)); + + // *** NOTE *** + // Y Position in a canvas is REVERSED, so "0" is on top of the screen and "MAX" is on bottom. + // Not very instinctive, isn't it? + + // Draw a bar from the left (pos X=0) until the pos=(NbBars*barWidth). If space is left, it will be blanked after. + for ( int x=0; x + * + * @param event The generated paint event when redraw is called. + */ + public synchronized void drawSelectedEventInWindow(PaintEvent event) { + HistogramContent tmpContent = parentCanvas.getHistogramContent(); + int tmpBarWidth = tmpContent.getBarsWidth(); + + // This will be the color for all the bars that wil be draw below. + event.gc.setBackground(event.display.getSystemColor(HistogramConstant.SELECTED_EVENT_COLOR)); + + int position = tmpContent.getClosestXPositionFromTimestamp(tmpContent.getSelectedEventTimeInWindow()); + + Rectangle rect = new Rectangle(tmpBarWidth*position, 0, tmpBarWidth, event.height); + event.gc.fillRectangle(rect); + } + + /** + * Draw the selection window in the canvas.

+ * This draw a square around the selected section with a crosshair in the middle. + * The square cannot be smaller than "MINIMUM_WINDOW_WIDTH" + * + * @param event The generated paint event when redraw is called. + */ + public void drawSelectedWindow(PaintEvent event) { + HistogramSelectedWindow tmpWindow = parentCanvas.getCurrentWindow(); + + // Attributes (color and width) of the lines + event.gc.setForeground(event.display.getSystemColor(HistogramConstant.SELECTION_WINDOW_COLOR)); + event.gc.setLineWidth(HistogramConstant.SELECTION_LINE_WIDTH); + + // Get the window position... this would fail if the window is not initialized yet + int positionCenter = tmpWindow.getWindowXPositionCenter(); + int positionLeft = tmpWindow.getWindowXPositionLeft(); + int positionRight = tmpWindow.getWindowXPositionRight(); + + // Minimal size verification. + if ( (positionRight - positionLeft) < HistogramConstant.MINIMUM_WINDOW_WIDTH ) { + positionLeft = positionCenter - (HistogramConstant.MINIMUM_WINDOW_WIDTH/2); + positionRight = positionCenter + (HistogramConstant.MINIMUM_WINDOW_WIDTH/2); + } + + // Draw the selection window square + event.gc.drawLine(positionLeft , 0 , positionLeft , event.height); + event.gc.drawLine(positionLeft , event.height, positionRight, event.height); + event.gc.drawLine(positionRight, event.height, positionRight, 0); + event.gc.drawLine(positionLeft , 0 , positionRight, 0); + + // Draw the crosshair section + event.gc.drawLine(positionCenter + HistogramConstant.SELECTION_CROSSHAIR_LENGTH, event.height/2, positionCenter - HistogramConstant.SELECTION_CROSSHAIR_LENGTH, event.height/2); + event.gc.drawLine(positionCenter, (event.height/2) + HistogramConstant.SELECTION_CROSSHAIR_LENGTH, positionCenter, (event.height/2) - HistogramConstant.SELECTION_CROSSHAIR_LENGTH); + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramConstant.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramConstant.java new file mode 100644 index 0000000000..092a10d8a7 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramConstant.java @@ -0,0 +1,172 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * William Bourque - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.histogram; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.widgets.Composite; + +/** + * HistogramConstant + *

+ * Empty interface class to hold the different constants needed by the histogram. + *

+ */ +public abstract class HistogramConstant { + // Constants relative to requests + public final static int MAX_EVENTS_PER_READ = 1; + public final static int REDRAW_EVERY_NB_EVENTS = 10000; + public final static Boolean SKIP_EMPTY_INTERVALS_WHEN_CALCULATING_AVERAGE = true; + + + // Constant relative to the content + public final static double DEFAULT_DIFFERENCE_TO_AVERAGE = 1000.0; + + + + // Constants relative to zoom. Factors need to be a percentage ( 0 < factors < 1 ) + public final static double ZOOM_IN_FACTOR = 0.1; + public final static double ZOOM_OUT_FACTOR = 0.1; + + + // Constants relative to wait time while listening for scroll events + // "FULL" is time to wait to stop "to count" mouse scroll click events + // "INTERVAL" is time to wait between polling for scroll click events + public final static long FULL_WAIT_MS_TIME_BETWEEN_MOUSE_SCROLL = 500L; + public final static long INTERVAL_WAIT_MS_TIME_BETWEEN_POLL = 100L; + + + // Constants relative to the displacement in the trace + // Factor represent a number of HistogramContent interval + // Multiple is the factor to multiply to basic during "fast" displacement + public final static int BASIC_DISPLACEMENT_FACTOR = 1; + public final static double FAST_DISPLACEMENT_MULTIPLE = 10.0; + + + // Constants relative to the drawing of the Histogram + // Colors for the histogram. Background should be the same as the background in use + public final static int EMPTY_BACKGROUND_COLOR = SWT.COLOR_WHITE; + public final static int HISTOGRAM_BARS_COLOR = SWT.COLOR_DARK_CYAN; + public final static int SELECTED_EVENT_COLOR = SWT.COLOR_RED; + public final static int SELECTION_WINDOW_COLOR = SWT.COLOR_RED; + + // Dimension for the line of the "Selection Window" + public final static int MINIMUM_WINDOW_WIDTH = 3; + public final static int SELECTION_LINE_WIDTH = 2; + public final static int SELECTION_CROSSHAIR_LENGTH = 3; + + + /** + * Method to format a long representing nanosecond into a proper String.

+ * The returned String will always be like "0.000000000", missing decimal will be added. + * + * @param nanosecTime This time to format + * + * @return The formatted string + */ + public static String formatNanoSecondsTime(long nanosecTime) { + String returnedTime = Long.toString(nanosecTime); + + // If our number has over 9 digits, just add a dot after the ninth digits + if ( returnedTime.length() > 9 ) { + returnedTime = returnedTime.substring(0, returnedTime.length() - 9 ) + "." + returnedTime.substring( returnedTime.length() - 9 ); + } + // Otherwise, patch missing decimal with 0 + else { + int curSize = returnedTime.length(); + for (int l=0; (curSize+l)< 9; l++) { + returnedTime = "0" + returnedTime; + } + returnedTime = "0." + returnedTime; + } + + return returnedTime; + } + + /** + * Convert a String representing nanoseconds into a valid long.

+ * This can handle number like "0.5", "0.123456789" as well as plain number like "12".

+ * + * Note : This function ALWAYS return a number, if conversion failed, 0 will be returned.

+ * + * @param timeString The string to convert + * + * @return The converted nanoseconds time as long + */ + public static long convertStringToNanoseconds( String timeString ) { + long returnedNumber = 0L; + + try { + // Avoid simple commat/dot mistake + timeString = timeString.replace(",", "."); + + // If we have a dot, we have a decimal number to convert + int dotPosition = timeString.indexOf("."); + + // If the user begun the line with a dot, we add a zero + if ( dotPosition == 0 ) { + timeString = "0" + timeString; + dotPosition = 1; + } + + // If we found a dot, verify that we have 9 digits + if ( dotPosition != -1 ) { + int decimalNumber = (timeString.length() - dotPosition -1); + + // If we have less than 9 digits, we fill with 0 + if ( decimalNumber <= 9 ) { + StringBuffer strBuffer = new StringBuffer(timeString); + for ( int nbDec=decimalNumber; nbDec<9; nbDec++) { + strBuffer.append("0"); + } + timeString = strBuffer.toString(); + } + // We have OVER 9 digits, skip the useless part + else { + timeString = timeString.substring(dotPosition, 9); + } + } + + // Conversion into decimal seconds + double dblMaxTimerange = Double.parseDouble(timeString); + // Conversion into nanoseconds + returnedNumber = (long)(dblMaxTimerange * 1000000000.0); + } + catch (NumberFormatException e) { + System.out.println("Warning : Could not convert string into nanoseconds (convertStringToLong)"); + } + + return returnedNumber; + } + + /** + * Calculate the correcte width of a String.

+ * Useful to set a control to its maximum size; since the size depends on characters, + * this will calculate the correct sum... should be platform independant (we hope). + * + * @param parent Parent control we will use as a reference. Could be any composite. + * @param text The Text to measure the size from + * + * @return The size calculated. + */ + public static int getTextSizeInControl(Composite parent, String text) { + GC graphicContext = new GC(parent); + int textSize = 0; + for ( int pos=0; posHistogramContent + *

+ * This class hold the content that will be used to draw the Histograms. + *

+ */ +public class HistogramContent { + + // Start and end time of the content + protected long startTime = 0L; + protected long endTime = 0L; + + // Some information about the content + // Most of them are required to calculate position and/or draw + // Make sure they stay consistent! + protected long elementsTimeInterval = 1L; + protected double heightFactor = 100.0; + protected long heighestEventCount = 0L; + protected int maxHeight = 0; + protected int canvasWindowSize = 0; + protected int barsWidth = 0; + + // This value is used to calculate at which point we should "cut" bar that are too tall. + // Default value is large enought so that no bar should be cut + protected double maxDifferenceToAverage = HistogramConstant.DEFAULT_DIFFERENCE_TO_AVERAGE; + // This is a factor we might apply on the max difference to average, as example if we concatenate interval together + protected double maxDifferenceFactor = 1.0; + + // By default we will only consider element up to this position + protected int readyUpToPosition = 0; + + // The average number of events in the content + // Note : this IS needed to draw + protected int averageNumberOfEvents = 0; + + // This is to draw the selected event of the TMF framework in another color + // Set the 0 to ignore + protected long selectedEventTimeInWindow = -1L; + + // The table that hold the elements + protected HistogramElement[] elementTable; + + + /** + * Default constructor for the HistogramContent. + * + * @param tableSize The size ofthe element table that will be created. + * @param newCanvasSize The full size of the canvas. Used for positionning; need to be consistent with canvas. + * @param newMaxHeight The maximum height of a bar, usually same as the height of the canvas. + */ + public HistogramContent(int tableSize, int newCanvasSize, int newBarWidth, int newMaxHeight) { + this(tableSize, newCanvasSize, newBarWidth, newMaxHeight, HistogramConstant.DEFAULT_DIFFERENCE_TO_AVERAGE); + } + + /** + * Default constructor for the HistogramContent. + * + * @param tableSize The size ofthe element table that will be created. + * @param newCanvasSize The full size of the canvas. Used for positionning; need to be consistent with canvas. + * @param newMaxHeight The maximum height of a bar, usually same as the height of the canvas. + * @param newDiffToAverage This value at which point we "cut" bar that are too tall. + */ + public HistogramContent(int tableSize, int newCanvasSize, int newBarWidth, int newMaxHeight, double newDiffToAverage) { + canvasWindowSize = newCanvasSize; + barsWidth = newBarWidth; + maxHeight = newMaxHeight; + maxDifferenceToAverage = newDiffToAverage; + + // Create a new element table from the above value + // The table will not get initialized until resetTable() is called. + createNewTable(tableSize); + } + + /** + * Create a new table to hold the content element.

+ * Note that the table is not initialized (and so unusable) until resetTable() is called. + * + * @param newTableSize The size (number of element) of the table. + */ + public void createNewTable(int newTableSize) { + elementTable = new HistogramElement[newTableSize]; + + for ( int x=0; x + */ + public void clearContentData() { + startTime = 0L; + endTime = 0L; + + elementsTimeInterval = 1L; + heightFactor = 100.0; + heighestEventCount = 0L; + + readyUpToPosition = 0; + } + + /** + * Reset the data in the elements table.

+ * NOTE : For this to be consistent and usuable, "startTime", "endTime" and "intervalTime" need to be set already. + */ + public void resetTable() { + for ( int x=0; x + * Start and EndTime will be used to calculate elementsTimeInterval.

+ * + * @param newStartTime The new start time to use + * @param newEndTime The new stop time to use + */ + public void resetTable(long newStartTime, long newEndTime) { + recalculateElementsTimeInterval(newStartTime, newEndTime); + resetTable(newStartTime, newEndTime, elementsTimeInterval); + } + + /** + * Reset the data in the elements table.

+ * elementsTimeInterval will be set to the one give, use this for fixed interval.

+ * + * @param newStartTime The new start time to use + * @param newEndTime The new stop time to use + * @param newTimeInterval The new time interval to use + */ + public void resetTable(long newStartTime, long newEndTime, long newTimeInterval) { + + startTime = newStartTime; + endTime = newEndTime; + recalculateElementsTimeInterval(newStartTime, newEndTime); + + for ( int x=0; x + * NOTE : Unlike reset, this does not recalculate the content, + * so it should be done either by hand or by calling reset table after. + */ + public void clearTable() { + for ( int x=0; x + */ + public void printTable() { + for ( int x=0; x " + elementTable[x].intervalNbEvents + ":" + elementTable[x].intervalHeight + " (" + elementTable[x].firstIntervalTimestamp + ")"); + } + } + + /** + * Getter for the timestamp of the selected event in the window.

+ * + * @return The time of the event. + */ + public long getSelectedEventTimeInWindow() { + return selectedEventTimeInWindow; + } + + /** + * Setter for the timestamp of the selected event in the window.

+ * + * This allow to pinpoint a certain event or position in the window. + * Set to 0 or lower to ignore. + * + * @param newPosition The new event time. + */ + public void setSelectedEventTimeInWindow(long newTime) { + this.selectedEventTimeInWindow = newTime; + } + + /** + * Get an element in the table by its index.

+ * Null is returned if the index is out of range.

+ * Note that you can get an element past "readyUpToPosition", the index is NOT tested against it. + * + * @param index The index of the element (0 < index < nbElement) + * + * @return The element found or null if the index is wrong. + */ + public HistogramElement getElementByIndex(int index) { + HistogramElement returnedElement = null; + + if ( (index >= 0) && (index < elementTable.length) ) { + returnedElement = elementTable[index]; + } + + return returnedElement; + } + + /** + * Return the closest element to a X position on the canvas.

+ * Note : canvasWindowSize need to be set correctly here, otherwise unexpected element might be returned.

+ *

+ * NOTE : This ALWAYS return an element; + * If calculation lead outside the table, the first or the last element will be returned. + * + * @param position The X position we are looking at (0 < pos < canvasWidth) + * + * @return The closest element found. + */ + public HistogramElement getClosestElementFromXPosition(int position) { + + int index = (int)Math.round((double)elementTable.length * ((double)position / (double)canvasWindowSize) ); + + // If we are out of bound, return the closest border (first or last element) + if ( index < 0) { + index = 0; + } + else if ( index >= elementTable.length ) { + index = (elementTable.length -1); + } + + return elementTable[index]; + } + + /** + * Return the closest element's timestamp to a X position on the canvas.

+ * Note : canvasWindowSize need to be set correctly here, otherwise unexpected timestamp might be returned.

+ *

+ * NOTE : This ALWAYS return a timestamp; + * If calculation lead outside the table, the first or the last timestamp will be returned. + * + * @param position The X position we are looking at (0 < pos < canvasWidth) + * + * @return The closest timestamp found. + */ + public long getClosestTimestampFromXPosition(int position) { + return getClosestElementFromXPosition(position).firstIntervalTimestamp; + } + + /** + * Return the X position (relative to the canvas) of a certain element.

+ * Note : canvasWindowSize need to be set correctly here, otherwise unexpected element might be returned.

+ * + * NOTE : This ALWAYS return an element; + * If calculation lead outside the table, the first or the last element will be returned. + * + * @param targetElement The element we are looking to find the position + * + * @return The closest found element. + */ + public int getXPositionFromElement(HistogramElement targetElement) { + return (int)Math.round( ((double)targetElement.index / (double)elementTable.length)*(double)canvasWindowSize ); + } + + /** + * Return the closest element to a timestamp (long) given.

+ * Note : startTime and intervalTime need to be set correctly here, otherwise unexpected element might be returned.

+ *

+ * NOTE : This ALWAYS return an element; + * If calculation lead outside the table, the first or the last element will be returned. + * + * @param timestamp The timestamp (in nanosecond, as long) of the element we are looking for (startTime < timestamp < endTime) + * + * @return The closest element found. + */ + public HistogramElement getClosestElementFromTimestamp(long timestamp) { + int index = (int)Math.round( (double)(timestamp - startTime)/(double)elementsTimeInterval ); + + // If we are out of bound, return the closest border (first or last element) + if ( index < 0) { + index = 0; + } + else if ( index >= elementTable.length ) { + index = (elementTable.length -1); + } + + return elementTable[index]; + } + + /** + * Return the closest X position to a timestamp (long) given.

+ * Note : startTime and intervalTime need to be set correctly here, otherwise unexpected position might be returned.

+ *

+ * NOTE : This ALWAYS return a position; + * If calculation lead outside the table, the first or the last position will be returned. + * + * @param timestamp The timestamp (in nanosecond, as long) of the element we are looking for (startTime < timestamp < endTime) + * + * @return The closest position found. + */ + public int getClosestXPositionFromTimestamp(long timestamp) { + return getXPositionFromElement(getClosestElementFromTimestamp(timestamp)); + } + + /** + * Return the closest element to an element and a time interval to this element.

+ * The time interval can be negative or positive (before or after the element). + * + * Note : IntervalTime and StartTime need to be set correctly here, otherwise unexpected result might be returned.

+ * + * @param targetElement The element we compare the interval with. + * @param intervalToElement Time negative or positive time interval (in nanosecond) to this element. + * + * @return The closest found element, or null if given data are wrong. + */ + public HistogramElement getClosestElementByElementAndTimeInterval(HistogramElement targetElement, long intervalToElement) { + + // Get the timestamp of the target element + // This should always be valid as long the table is initialized + long elementTime = targetElement.firstIntervalTimestamp; + elementTime = elementTime + intervalToElement; + + return getClosestElementFromTimestamp(elementTime); + } + + /** + * Return the closest element to an element's timestamp (as long) and a time interval to this element.

+ * The time interval can be negative or positive (before or after the element). + * + * Note : IntervalTime and StartTime need to be set correctly here, otherwise unexpected result might be returned.

+ * + * @param timestamp The timestamp (in nanoseconds, as long) of the element we want to compare from. + * @param intervalToElement Time negative or positive time interval (in nanosecond) to this element. + * + * @return The closest found element, or null if given data are wrong. + */ + public int getClosestElementByTimestampAndTimeInterval(long timestamp, long intervalToElement) { + HistogramElement targetElement = getClosestElementFromTimestamp(timestamp); + HistogramElement newElement = getClosestElementByElementAndTimeInterval(targetElement, intervalToElement); + + return getXPositionFromElement(newElement); + } + + /** + * Return the closest element to an element's position and a time interval to this element.

+ * The time interval can be negative or positive (before or after the element). + * + * Note : IntervalTime and StartTime need to be set correctly here, otherwise unexpected result might be returned.

+ * + * @param targetPosition The position (relative to the canvas) of the element we want to compare from. + * @param intervalToElement Time negative or positive time interval (in nanosecond) to this element. + * + * @return The closest found element, or null if given data are wrong. + */ + public int getXPositionByPositionAndTimeInterval(int targetPosition, long intervalToElement) { + HistogramElement targetElement = getClosestElementFromXPosition(targetPosition); + HistogramElement newElement = getClosestElementByElementAndTimeInterval(targetElement, intervalToElement); + + return getXPositionFromElement(newElement); + } + + /** + * Getter for the number of element.

+ * The same as the value of tableSize given at construction. + * + * @return The number of element in the elements table. + */ + public int getNbElement() { + return elementTable.length; + } + + /** + * Getter for the average number of events by interval in the content.

+ * + * Note : Might be set externally (instead of calculated internally), so consistency with the content is not guarantee. + * + * @return Average number of events we currently use in + */ + public int getAverageNumberOfEvents() { + return averageNumberOfEvents; + } + + /** + * Setter for averageNumberOfEvents.

+ * + * Note : this is used in some drawing calculation so make sure this number make sense. + * Note : you might want to call recalculateEventHeight() if you change this. + * + * @param newAverageNumberOfEvents The new average number of events to use. + */ + public void setAverageNumberOfEvents(int newAverageNumberOfEvents) { + this.averageNumberOfEvents = newAverageNumberOfEvents; + } + + /** + * Recalculate the average number of events by time interval.

+ * + * Note : This run over all the element so this is quite cpu intensive, use with care. + */ + public void recalculateAverageNumberOfEvents() { + + int nbInterval = 0; + int totalNbEvents = 0; + + // Go over the element up to readyUpToPosition (further position might not be ready) + for ( int x=0; x 0 ) { + nbInterval++; + } + } + else { + nbInterval++; + } + + totalNbEvents += elementTable[x].intervalNbEvents; + } + // Calculate the average here + averageNumberOfEvents = (int)Math.round((double)totalNbEvents / (double)nbInterval); + } + + /** + * Getter for the start time of the content.

+ * + * @return The start time we currently use. + */ + public long getStartTime() { + return startTime; + } + + /** + * Setter for the start time of the content.

+ * Note : You probably want to call "resetTable()" if you change this, otherwise data might be inconsistent. + * + * @param newStartTime the new start time + */ + public void setStartTime(long newStartTime) { + this.startTime = newStartTime; + } + + + /** + * Getter for the end time of the content.

+ * + * @return The end time we currently use. + */ + public long getEndTime() { + return endTime; + } + + /** + * Setter for the end time of the content.

+ * Note : You probably want to call "resetTable()" if you change this, otherwise data might be inconsistent. + * + * @param newStartTime the new end time + */ + public void setEndTime(long newEndTime) { + this.endTime = newEndTime; + } + + /** + * Getter for the complete time interval of the content.

+ * Note : This return "endTime" minus "startTime", unlike getReadyTimeInterval() it won't check the actual time of elements. + * + * @return The complete time interval + */ + public long getCompleteTimeInterval() { + return ( endTime - startTime ); + } + + /** + * Getter for the time interval for the element between first and readyUpToPosition

+ * Note : This return element[readyPosition].time - element[first].time , not the full interval like getCompleteTimeInterval() + * + * @return The time interval of the position that are ready. + */ + public long getReadyTimeInterval() { + return ( elementTable[readyUpToPosition].firstIntervalTimestamp - elementTable[0].firstIntervalTimestamp ); + } + + /** + * Getter for the height factor of the bar.

+ * Note : height = "nb events in interval" * heightFactor + * + * @return Height factor currently used. + */ + public double getHeightFactor() { + return heightFactor; + } + + /** + * Recalculate the height factor of the element table.

+ * Assume values of "maxHeight", "heighestEventCount" or "averageNumberOfEvents" are set correctly. + */ + public void recalculateHeightFactor() { + // Recalculate the new HeightFactor for the element; + // the highest bar will get "maxHeight" and other bar a fraction of it. + double diffToConsider = (maxDifferenceToAverage * maxDifferenceFactor * (double)barsWidth); + + if ( heighestEventCount > (long)(diffToConsider * (double)averageNumberOfEvents) ) { + heightFactor = (double)maxHeight/( diffToConsider * (double)averageNumberOfEvents); + } + else { + heightFactor = (double)maxHeight/(double)heighestEventCount; + } + } + + /** + * Recalculate the height of each bar in the elements table.

+ * This assume "heightFactor" is already set correctly.

+ * + * NOTE : if "maxHeight", "heighestEventCount" or "averageNumberOfEvents" changes, + * recalculateHeightFactor() should be recalled. + */ + public void recalculateEventHeight() { + // Recalculate the height of the bars up to "readyUpToPosition" + for ( int x=0; x + * Unlike recalculateEventHeight(), this only recalculate for the given range, not the whole table. + * + */ + public void recalculateEventHeightInInterval(int startPosition, int stopPosition) { + // Basic error checking on start : should be bigger than 0 + if ( startPosition < 0 ) { + startPosition = 0; + } + + // Basic error checking on start : should be smaller than length - 1 + if ( stopPosition >= elementTable.length) { + stopPosition = (elementTable.length-1); + } + + // Recalculate the height of the bars from startPosition to stopPosition + for ( int x=startPosition; x + * This is used for the positionnal calculation so should be consistent with the real canvas size. + * + * @return Size of the canvas we currently use. + */ + public int getCanvasWindowSize() { + return canvasWindowSize; + } + + /** + * Set a new full size of the canvas.

+ * This is used for the positionnal calculation so should be consistent with the real canvas size. + * + * @param newSize New canvas size; + */ + public void setCanvasWindowSize(int newSize) { + canvasWindowSize = newSize; + } + + /** + * Getter for the heighest event count recorded so far for an interval.

+ * + * Note : Might be set externally (instead of calculated internally), so consistency with the content is not guarantee. + * + * @return Current heighestEventCount + */ + public long getHeighestEventCount() { + return heighestEventCount; + } + + /** + * Setter for setHeighestEventCount.

+ * + * Note : this is used in some drawing calculation so make sure this number make sense. + * Note : you might want to call recalculateEventHeight() if you change this. + * + * @param newHeighestEventCount Heighest event count for a single interval. + */ + public void setHeighestEventCount(long newHeighestEventCount) { + this.heighestEventCount = newHeighestEventCount; + } + + /** + * Recalculate the heightest event count for a single time interval.

+ * + * Note : This run over all the element so this is quite cpu intensive, use with care. + */ + public void recalculateHeighestEventCount() { + // Go over the element up to readyUpToPosition (further position might not be ready) + for ( int x=0; x heighestEventCount ) { + this.heighestEventCount = elementTable[x].intervalNbEvents; + } + } + } + + /** + * Getter for the max height of a bar in the content.

+ * + * @return maximum height for a bar we currently use. + */ + public int getMaxHeight() { + return maxHeight; + } + + /** + * Setter for maxHeight.

+ * + * Note : this is used in some drawing calculation so make sure this number make sense. + * Note : you might want to call recalculateEventHeight() if you change this. + * + * @param maxHeight The new maximum height for a bar to use. + */ + public void setMaxHeight(int maxHeight) { + this.maxHeight = maxHeight; + } + + /** + * Getter for the max difference to the average height a bar can have.

+ * This determine at which point a bar too tall is "cut". Set a very large value (like 1000.0) to ignore. + * + * @return maximum difference to the average we currently use. + */ + public double getMaxDifferenceToAverage() { + return maxDifferenceToAverage; + } + + /** + * Setter for the max difference to the average height a bar can have.

+ * This determine at which point a bar too tall is "cut". Set a very large value (like 1000.0) to ignore. + * + * Note : this is used in some drawing calculation so make sure this number make sense. + * Note : you might want to call recalculateEventHeight() if you change this. + * + * @param newDiffToAverage The new maximum difference to the average to use. + */ + public void setMaxDifferenceToAverage(double newDiffToAverage) { + maxDifferenceToAverage = newDiffToAverage; + } + + + /** + * Getter for a factor applied to the max difference to the average height a bar can have.

+ * This is muliplied to maxDifferenceToAverage. Set to value 1.0 to ignore. + * + * Note : this is useful if you concatenate some intervals to gether but want the average to be consistent + * + * @return maximum difference to the average we currently use. + */ + public double getMaxDifferenceToAverageFactor() { + return maxDifferenceFactor; + } + + /** + * Setter for a factor applied to the max difference to the average height a bar can have.

+ * + * Note : this is used in some drawing calculation so make sure this number make sense. + * Note : you might want to call recalculateEventHeight() if you change this. + * Note : setting to 0 will cause bar to have a zero size... use 1.0 to desactivate + * + * @param newFactor The new factor to use. + */ + public void setMaxDifferenceToAverageFactor(double newFactor) { + maxDifferenceFactor = newFactor; + } + + + /** + * Getter for the interval time of each interval.

+ * This is usually "(EndTime - StartTime) / NbElement" + * + * @return Currently used interval time. + */ + public long getElementsTimeInterval() { + return elementsTimeInterval; + } + + + /** + * Setter for the interval time of each interval.

+ * + * Note : this is used in some drawing calculation so make sure this number make sense. + * Note : you migth want to call resetTable() to to fill the element's table again if you change this. + * + * @return New interval time. + */ + public void setElementsTimeInterval(long newInterval) { + this.elementsTimeInterval = newInterval; + } + + + /** + * Calculate the correct time interval of each element from the given time.

+ * + * @return The complete time interval + */ + public void recalculateElementsTimeInterval(long startTime, long endTime) { + long tmpInterval = (long)Math.ceil((double)(endTime - startTime)/ (double)getNbElement()); + + if ( tmpInterval <= 0 ) { + tmpInterval = 1L; + } + + this.elementsTimeInterval = tmpInterval; + } + + + /** + * Getter for readyUpToPosition.

+ * This should tell to which point the content is filled, calculated and ready to use. + * + * @return Last position processed so far. + */ + public int getReadyUpToPosition() { + return readyUpToPosition; + } + + /** + * Setter for readyUpToPosition.

+ * Set a new point (position) up to where the content is filled, calculated and ready to use. + * + * @param newReadyUpToPosition The new position to use. + */ + public void setReadyUpToPosition(int newReadyUpToPosition) { + this.readyUpToPosition = newReadyUpToPosition; + } + + /** + * Getter for the bar width.

+ * This is needed by the paint listener usually. + * + * @return current bars width; + */ + public int getBarsWidth() { + return barsWidth; + } + + /** + * Setter for the bar width.

+ * Setting this to 0 will hide all the bar in the histogram. + * + * @param newBarsWidth new bars width; + */ + public void setBarsWidth(int newBarsWidth) { + this.barsWidth = newBarsWidth; + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramElement.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramElement.java new file mode 100644 index 0000000000..eb907d4a9c --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramElement.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * William Bourque - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.histogram; + +/** + * HistogramElement + *

+ * This is used by the content to keep its data. + * It would be a struct if such a thing would exist in java. + *

+ * Each "element" should represent a certain time interval + */ +public class HistogramElement { + public int index = 0; // Position of the element in the table (table index, obviously) + public long firstIntervalTimestamp = 0L; // The first timestamp recorded for this interval + public long intervalNbEvents = 0L; // Number of events recorded in this interval + public int intervalHeight = 0; // Height (in the canvas) of this element. Should be smaller than the canvas height. +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramRequest.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramRequest.java new file mode 100644 index 0000000000..34d00572fb --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramRequest.java @@ -0,0 +1,237 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * William Bourque - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.histogram; + +import org.eclipse.linuxtools.lttng.event.LttngEvent; +import org.eclipse.linuxtools.tmf.event.TmfEvent; +import org.eclipse.linuxtools.tmf.event.TmfTimeRange; +import org.eclipse.linuxtools.tmf.request.TmfEventRequest; + +/** + * HistogramRequest + *

+ * Request class, to perform a request to TMF for the histograms. + *

+ */ +public class HistogramRequest extends TmfEventRequest { + protected HistogramContent histogramContent = null; + + protected int lastInterval = 0; + protected long lastRangeTime = 0L; + protected long nbEventsInInterval = 0L; + + protected int nbIntervalNotEmpty = 1; + protected int nbEventRead = 0; + + protected int lastDrawPosition = 0; + + protected HistogramCanvas parentCanvas = null; + + /** + * Constructor for HistogramRequest.

+ * Prepare the request in TMF and reset the histogram content. + * + * @param range Range of the request. + * @param nbRequested Nb events requested. Can be "Infinity" for all. + * @param newParentCanvas HistogramCanvas related to the request. + * @param timeInterval Time interval to consider (i.e. : 1 interval is 1 bar in the histogram) + * + * @see org.eclipse.linuxtools.tmf.request.TmfEventRequest + */ + public HistogramRequest(TmfTimeRange range, int nbRequested, HistogramCanvas newParentCanvas, long timeInterval) { + super((Class)LttngEvent.class, range, nbRequested, HistogramConstant.MAX_EVENTS_PER_READ); + + // *** FIXME *** + // This does not work! The request won't be processed or the number of events returned is wrong! + // We cannot use this ! + //super((Class)dataType, range); + + parentCanvas = newParentCanvas; + histogramContent = parentCanvas.getHistogramContent(); + + // Reset the content of the HistogramContent... the given data better be valid or this will fail. + histogramContent.clearContentData(); + histogramContent.resetTable(range.getStartTime().getValue(), range.getEndTime().getValue(), timeInterval); + + lastRangeTime = range.getStartTime().getValue(); + + // Notify the UI even before the request started, so we set the timestamp already. + parentCanvas.notifyParentUpdatedInformationAsynchronously(); + } + + /** + * HandleData function : will be called by TMF each time a new event is receive for the request.

+ * Calculation for the content is done here. + */ + @Override + public void handleData() { + TmfEvent[] result = getData(); + TmfEvent[] evt = new TmfEvent[1]; + + evt[0] = (result.length > 0) ? result[0] : null; + + // *** FIXME *** + // *** EVIL BUG *** + // The request by timerange only does not work! (see constructor above) + // However, the request with number of events will loop until it reach its number or EOF + // We have to filter out ourself the extra useless events! + // + if (evt[0] != null) { + + LttngEvent tmpEvent = (LttngEvent)evt[0]; + + // This check is linked to the evil fix mentionned above + if ( ( tmpEvent.getTimestamp().getValue() >= histogramContent.getStartTime() ) && + ( tmpEvent.getTimestamp().getValue() <= histogramContent.getEndTime() ) ) + { + + // Distance (in time) between this event and the last one we read + long distance = ( tmpEvent.getTimestamp().getValue() - lastRangeTime ); + + // Check if we changed of interval (the distance is higher than the interval time) + if ( distance > histogramContent.getElementsTimeInterval() ) { + + histogramContent.getElementByIndex(lastInterval).intervalNbEvents = nbEventsInInterval; + lastRangeTime = tmpEvent.getTimestamp().getValue(); + + // * NOTE * + // We can skip several interval at once, so we need to find what was our interval now + lastInterval = (int)((lastRangeTime - histogramContent.getStartTime()) / histogramContent.getElementsTimeInterval() ); + + // *** HACK *** + // Because of the threads, weird phenomenons seem to happen here, like a position after the + // element range because another request was issued. + // This enforce the position but may result in slightly inconsistent result (i.e. a weird misplaced bar sometime). + if ( lastInterval < 0 ) { + lastInterval = 0; + } + else if ( lastInterval >= histogramContent.getNbElement() ) { + lastInterval = (histogramContent.getNbElement()-1); + } + + // * NOTE * + // We save the time we have here. This mean only the FIRST time read in an interval will be saved. + histogramContent.getElementByIndex(lastInterval).firstIntervalTimestamp = lastRangeTime; + histogramContent.setReadyUpToPosition(lastInterval); + + nbIntervalNotEmpty++; + nbEventsInInterval = 1L; + } + // We are still in the same interval, just keep counting + else { + nbEventsInInterval++; + } + + if ( nbEventsInInterval > histogramContent.getHeighestEventCount() ) { + histogramContent.setHeighestEventCount(nbEventsInInterval); + } + nbEventRead++; + + // Call an asynchronous redraw every REDRAW_EVERY_NB_EVENTS events + // That way we don't need to wait until to end to have something on the screen + if ( nbEventRead % HistogramConstant.REDRAW_EVERY_NB_EVENTS == 0 ) { + redrawAsyncronously(); + } + } + } + // We got a null event! This mean we reach the end of the request. + // Save the last interval we had, so we won't miss the very last events at the end. + else { + // Save the last events + histogramContent.getElementByIndex(lastInterval).intervalNbEvents = nbEventsInInterval; + // We reached the end of the request, so assume we fill up the content as well + histogramContent.setReadyUpToPosition(histogramContent.getNbElement()); + + // If the interval wasn't null, count this as a "non empty" interval + if (nbEventsInInterval > 0) { + nbIntervalNotEmpty++; + } + } + } + + /** + * Function that is called when the request completed (successful or not).

+ * Update information and redraw the screen. + */ + @Override + public void handleCompleted() { + parentCanvas.notifyParentUpdatedInformationAsynchronously(); + redrawAsyncronously(); + } + + /** + * Function that is called when the request completed successfully.

+ */ + @Override + public void handleSuccess() { + // Nothing different from completed. + } + + /** + * Function that is called when the request completed in failure.

+ */ + @Override + public void handleFailure() { + // Nothing different from cancel. + } + + /** + * Function that is called when the request was cancelled.

+ * Redraw and set the requestCompleted flag to true; + */ + @Override + public void handleCancel() { + redrawAsyncronously(); + } + + /** + * Update the HistogramContent with the latest information.

+ * This will perform some calculation that might be a bit harsh so it should'nt be called too often. + */ + public void updateEventsInfo() { + // *** Note *** + // The average number of event is calculated while skipping empty interval if asked + int averageNumberOfEvents = 0; + if ( HistogramConstant.SKIP_EMPTY_INTERVALS_WHEN_CALCULATING_AVERAGE ) { + averageNumberOfEvents = (int)Math.ceil((double)nbEventRead / (double)nbIntervalNotEmpty); + } + else { + averageNumberOfEvents = (int)Math.ceil((double)nbEventRead / (double)histogramContent.getNbElement()); + } + + histogramContent.setAverageNumberOfEvents(averageNumberOfEvents); + + // It is possible that the height factor didn't change; + // If not, we only need to redraw the updated section, no the whole content + // Save the actual height, recalculate the height and check if there was any changes + double previousHeightFactor = histogramContent.getHeightFactor(); + histogramContent.recalculateHeightFactor(); + if ( histogramContent.getHeightFactor() != previousHeightFactor ) { + histogramContent.recalculateEventHeight(); + } + else { + histogramContent.recalculateEventHeightInInterval(lastDrawPosition, histogramContent.getReadyUpToPosition()); + } + + lastDrawPosition = histogramContent.getReadyUpToPosition(); + } + + /** + * Perform an asynchonous redraw of the screen. + */ + public void redrawAsyncronously() { + updateEventsInfo(); + // Canvas redraw is already asynchronous + parentCanvas.redrawAsynchronously(); + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramSelectedWindow.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramSelectedWindow.java new file mode 100644 index 0000000000..562da82b90 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramSelectedWindow.java @@ -0,0 +1,212 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * William Bourque - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.histogram; + +/** + * HistogramSelectedWindow + *

+ * Selection window represent the selected section of the trace in the HistogramCanvas. + *

+ * The selected window have 3 important attributes : + *

    + *
  • Its central position + *
  • Its time width + *
  • Its visibility (to determine if we should draw it or not) + *
+ * The dimension are then deduced from the first 2 values. + * This mean the window is always a perfectly symetrical rectangle. + */ +public class HistogramSelectedWindow { + + protected int windowCenterPosition = 0; + protected long windowTimeWidth = 0L; + + protected Boolean isSelectedWindowVisible = false; + + protected HistogramContent histogramContent = null; + + /** + * Default constructor for HistogramSelectedWindow.

+ * Position and TimeWidth are both set to 0 + * + * @param newTraceContent HistogramContent to read window's data from + */ + public HistogramSelectedWindow(HistogramContent newTraceContent) { + histogramContent = newTraceContent; + } + + /** + * Default constructor for HistogramSelectedWindow.

+ * Position and TimeWidth are set to given value. + * + * @param newTraceContent HistogramContent to read window's data from + * @param centralPosition Central X Position of the selection window in the canvas (0 to canvasWidth) + * @param newWindowWidth Time width (size) of the window. (0 or greater) + */ + public HistogramSelectedWindow(HistogramContent newTraceContent, int centralPosition, long newWindowWidth) { + histogramContent = newTraceContent; + windowCenterPosition = centralPosition; + windowTimeWidth = newWindowWidth; + } + + /** + * Getter for the HistogramContent used by the window.

+ * + * @return HistogramContent tied to this selection window. + */ + public HistogramContent getTraceContent() { + return histogramContent; + } + + /** + * Setter for the HistogramContent used by the window.

+ * This need to be a valid, initialized HistogramContent; + * the data in the content are needed for positionning the window. + * + * @param newTraceContent A new HistogramContent + */ + public void setTraceContent(HistogramContent newTraceContent) { + this.histogramContent = newTraceContent; + } + + + /** + * Getter for the window visibility.

+ * + * @return true if the window is visible (will be draw), false otherwise + */ + public boolean getSelectedWindowVisible() { + return isSelectedWindowVisible; + } + + /** + * Setter for the window visibility.

+ * True means the window will be draw, false that it will be hidden. + * + * @param newIsSelectedWindowVisible The visibility value + */ + public void setSelectedWindowVisible(Boolean newIsSelectedWindowVisible) { + this.isSelectedWindowVisible = newIsSelectedWindowVisible; + } + + + /** + * Getter for the window time width (size) + * + * @return Window time width (size) + */ + public long getWindowTimeWidth() { + return windowTimeWidth; + } + + /** + * Setter for the window time width (size).

+ * Width need to be a time (in nanoseconds) that's coherent to the data we are looking at. + * + * @param newWindowTimeWidth The new time width + */ + public void setWindowTimeWidth(long newWindowTimeWidth) { + this.windowTimeWidth = newWindowTimeWidth; + } + + + /** + * Getter for the central position of the window.

+ * + * @return Center X position of this window on the canvas. + */ + public int getWindowXPositionCenter() { + return windowCenterPosition; + } + + /** + * Setter for the central position of the window.

+ * The new position need to be valid on the canvas (0 to canvasWidth). + * + * @param newPosCenter The new central position. + */ + public void setWindowXPositionCenter(int newPosCenter) { + this.windowCenterPosition = newPosCenter; + } + + /** + * Getter for the left border of the window.

+ * Compute the position from the HistogramContent data; may return 0 if the content data are wrong. + * + * @return The left position of the window, or 0 if it cannot compute it. + */ + public int getWindowXPositionLeft() { + + // If the timewidth is too small, we would pick the same position as the center one. + // To avoid this, we take a "full interval" when the window size is too small + if ( windowTimeWidth < histogramContent.getElementsTimeInterval() ) { + // Use intervalTime and not intervalTime/2 to make sure we step into the next interval + // Otherwise, if we are in the beginning of an interval, adding IntervalTime/2 could lead us into the same one + // The rounding operation will then return a correct position + return histogramContent.getXPositionByPositionAndTimeInterval(windowCenterPosition, -(histogramContent.getElementsTimeInterval() ) ); + } + else { + return histogramContent.getXPositionByPositionAndTimeInterval(windowCenterPosition, -(windowTimeWidth / 2) ); + } + } + + /** + * Getter for the right border of the window.

+ * Compute the position from the HistogramContent data; may return 0 if the content data are wrong. + * + * @return The right position of the window, or 0 if it cannot compute it. + */ + public int getWindowXPositionRight() { + // If the timewidth is too small, we would pick the same position as the center one. + // To avoid this, we take a "full interval" when the window size is too small + if ( windowTimeWidth < histogramContent.getElementsTimeInterval() ) { + // Use intervalTime and not intervalTime/2 to make sure we step into the next interval + // Otherwise, if we are in the beginning of an interval, adding IntervalTime/2 could lead us into the same one + // The rounding operation will then return a correct position + return histogramContent.getXPositionByPositionAndTimeInterval(windowCenterPosition, +(histogramContent.getElementsTimeInterval() ) ); + } + else { + return histogramContent.getXPositionByPositionAndTimeInterval(windowCenterPosition, +(windowTimeWidth / 2) ); + } + + } + + /** + * Getter for the timestamp of left border of the window.

+ * Compute the timestamp from the HistogramContent data; may return 0 if the content data are wrong. + * + * @return The left timestamp of the window, or 0 if it cannot compute it. + */ + public long getTimestampOfLeftPosition() { + return histogramContent.getClosestElementFromXPosition( getWindowXPositionLeft() ).firstIntervalTimestamp; + } + + /** + * Getter for the timestamp of the center of the window.

+ * Compute the timestamp from the HistogramContent data; may return 0 if the content data are wrong. + * + * @return The center timestamp of the window, or 0 if it cannot compute it. + */ + public long getTimestampOfCenterPosition() { + return histogramContent.getClosestElementFromXPosition( getWindowXPositionCenter() ).firstIntervalTimestamp; + } + + /** + * Getter for the timestamp of right border of the window.

+ * Compute the timestamp from the HistogramContent data; may return 0 if the content data are wrong. + * + * @return The right timestamp of the window, or 0 if it cannot compute it. + */ + public long getTimestampOfRightPosition() { + return histogramContent.getClosestElementFromXPosition( getWindowXPositionRight() ).firstIntervalTimestamp; + } +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramView.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramView.java new file mode 100644 index 0000000000..25df24c23a --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/HistogramView.java @@ -0,0 +1,936 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * William Bourque - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.histogram; + +import org.eclipse.linuxtools.lttng.event.LttngEvent; +import org.eclipse.linuxtools.lttng.event.LttngTimestamp; +import org.eclipse.linuxtools.tmf.event.TmfTimeRange; +import org.eclipse.linuxtools.tmf.event.TmfTimestamp; +import org.eclipse.linuxtools.tmf.experiment.TmfExperiment; +import org.eclipse.linuxtools.tmf.signal.TmfExperimentSelectedSignal; +import org.eclipse.linuxtools.tmf.signal.TmfExperimentUpdatedSignal; +import org.eclipse.linuxtools.tmf.signal.TmfRangeSynchSignal; +import org.eclipse.linuxtools.tmf.signal.TmfSignalHandler; +import org.eclipse.linuxtools.tmf.signal.TmfTimeSynchSignal; +import org.eclipse.linuxtools.tmf.ui.views.TmfView; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ControlEvent; +import org.eclipse.swt.events.ControlListener; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.FontData; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Text; + +/** + * HistogramView + *

+ * View that contain an visual approach to the window that control the request. + * This is intended to replace the TimeFrameView + *

+ * This view is composed of 2 canvas, one for the whole experiment and one for the selectionned window in the experiment. + * It also contain a certain number of controls to print or change informations about the experiment. + */ +public class HistogramView extends TmfView implements ControlListener { + + // *** TODO *** + // Here is what's left to do in this view + // + // 1- Make sure the interval time is small enought on very big trace (bug 311930) + // The interval time of the content is dynamically assigned from the screen width and trace duration. + // However, on very big trace (more than 1 hour), we could end up with time interval that are > 1 seconds, + // which is not very precise. + // An algorithm need to be implemented to make sure we "increase" the number of interval in the content if + // their precision is getting too bad. + // + // 2- Make sure all control are thread safe (bug 309348) + // Right now, all the basic controls (i.e. Text and Label) are sensible to "Thread Access Exception" if + // updated from different threads; we need to carefully decide when/where to redraw them. + // This is a real problem since there is a lot of thread going on in this view. + // All basic control should be subclassed to offer "Asynchronous" functions. + // + // 3- Implement a "preferences view" for the HistogramView (bug 311935) + // There is a lot of ajustable preferences in the view, however there is no way to ajust them right now + // at run time. There should be a view of some kind of "menu" to allow the user to change them while executing. + // Most of the pertinent values are in HistogramConstant.java or in this file. + + public static final String ID = "org.eclipse.linuxtools.lttng.ui.views.histogram"; + + // "Minimum" screen width size. On smaller screen, we will apply several space saving technique + private static final int SCREEN_SMALL_IF_SMALLER_THAN = 1600; + + // Size of the "fulll trace" canvas + private static final int FULL_TRACE_CANVAS_HEIGHT = 25; + private static final int FULL_TRACE_BAR_WIDTH = 1; + private static final double FULL_TRACE_DIFFERENCE_TO_AVERAGE = 1.5; + + // Size of the "Selected Window" canvas + private static final int SELECTED_WINDOW_CANVAS_WIDTH = 300; + private static final int SMALL_SELECTED_WINDOW_CANVAS_WIDTH = 200; + private static final int SELECTED_WINDOW_CANVAS_HEIGHT = 60; + private static final int SELECTED_WINDOW_BAR_WIDTH = 1; + private static final double SELECTED_WINDOW_DIFFERENCE_TO_AVERAGE = 10.0; + + // For the two "events" label (Max and min number of events in the selection), we force a width + // This will prevent the control from moving horizontally if the number of events in the selection varies + private static final int NB_EVENTS_FIXED_WIDTH = 50; + + + // The "small font" height used to display time will be "default font" minus this constant + private static final int SMALL_FONT_MODIFIER = 2; + private static final int VERY_SMALL_FONT_MODIFIER = 4; + + // *** TODO *** + // This need to be changed as soon the framework implement a "window" + private static long DEFAULT_WINDOW_SIZE = (1L * 100 * 1000 * 1000); // 0.1sec + + // The last experiment received/used by the view + private TmfExperiment lastUsedExperiment = null; + + // Parent of the view + private Composite parent = null; + + // Request and canvas for the "full trace" part + private HistogramRequest dataBackgroundFullRequest = null; + private ParentHistogramCanvas fullExperimentCanvas = null; + + // Request and canvas for the "selected window" + private HistogramRequest selectedWindowRequest = null; + private ChildrenHistogramCanvas selectedWindowCanvas = null; + + // Content of the timeTextGroup + // Since the user can modify them with erroneous value, + // we will keep track of the value internally + private long selectedWindowTime = 0L; + private long selectedWindowTimerange = 0L; + private long currentEventTime = 0L; + + // *** All the UI control below + // + // NOTE : All textboxes will be READ_ONLY. + // So the user will be able to select/copy the value in them but not to change it + private Text txtExperimentStartTime = null; + private Text txtExperimentStopTime = null; + + private Text txtWindowStartTime = null; + private Text txtWindowStopTime = null; + private Text txtWindowMaxNbEvents = null; + private Text txtWindowMinNbEvents = null; + + private static final String WINDOW_TIMERANGE_LABEL_TEXT = "Window Timerange "; + private static final String WINDOW_CURRENT_TIME_LABEL_TEXT = "Cursor Centered on "; + private static final String EVENT_CURRENT_TIME_LABEL_TEXT = "Current Event Time "; + private TimeTextGroup ntgTimeRangeWindow = null; + private TimeTextGroup ntgCurrentWindowTime = null; + private TimeTextGroup ntgCurrentEventTime = null; + + /** + * Default contructor of the view + */ + public HistogramView() { + super(ID); + } + + /** + * Create the UI controls of this view + * + * @param parent The composite parent of this view + */ + @Override + public void createPartControl(Composite newParent) { + // Save the parent + parent = newParent; + + // Default font + Font font = parent.getFont(); + FontData tmpFontData = font.getFontData()[0]; + + + Font smallFont = null; + int nbEventWidth = -1; + int selectedCanvasWidth = -1; + boolean doesTimeTextGroupNeedAdjustment = false; + + // Calculate if we need "small screen" fixes + if ( parent.getDisplay().getBounds().width < SCREEN_SMALL_IF_SMALLER_THAN ) { + // A lot smaller font for timstampe + smallFont = new Font(font.getDevice(), tmpFontData.getName(), tmpFontData.getHeight() - VERY_SMALL_FONT_MODIFIER, tmpFontData.getStyle()); + + // Smaller selection window canvas + selectedCanvasWidth = SMALL_SELECTED_WINDOW_CANVAS_WIDTH; + // Smaller event number text field + nbEventWidth = NB_EVENTS_FIXED_WIDTH/2; + + // Tell the text group to ajust + doesTimeTextGroupNeedAdjustment = true; + } + else { + // Slightly smaller font for timestamp + smallFont = new Font(font.getDevice(), tmpFontData.getName(), tmpFontData.getHeight() - SMALL_FONT_MODIFIER, tmpFontData.getStyle()); + // Usual size for selected window and event number text field + nbEventWidth = NB_EVENTS_FIXED_WIDTH; + selectedCanvasWidth = SELECTED_WINDOW_CANVAS_WIDTH; + // No ajustement needed by the text group + doesTimeTextGroupNeedAdjustment = false; + } + + // Layout for the whole view, other elements will be in a child composite of this one + // Contains : + // Composite layoutSelectionWindow + // Composite layoutTimesSpinner + // Composite layoutExperimentHistogram + Composite layoutFullView = new Composite(parent, SWT.NONE); + GridLayout gridFullView = new GridLayout(); + gridFullView.numColumns = 2; + gridFullView.horizontalSpacing = 0; + gridFullView.verticalSpacing = 0; + gridFullView.marginHeight = 0; + gridFullView.marginWidth = 0; + layoutFullView.setLayout(gridFullView); + + + // Layout that contain the SelectionWindow + // Contains : + // Label lblWindowStartTime + // Label lblWindowStopTime + // Label lblWindowMaxNbEvents + // Label lblWindowMinNbEvents + // ChildrenHistogramCanvas selectedWindowCanvas + Composite layoutSelectionWindow = new Composite(layoutFullView, SWT.NONE); + GridLayout gridSelectionWindow = new GridLayout(); + gridSelectionWindow.numColumns = 3; + gridSelectionWindow.marginHeight = 0; + gridSelectionWindow.marginWidth = 0; + gridSelectionWindow.horizontalSpacing = 0; + gridSelectionWindow.verticalSpacing = 0; + layoutSelectionWindow.setLayout(gridSelectionWindow); + GridData gridDataSelectionWindow = new GridData(SWT.FILL, SWT.TOP, false, false, 1, 1); + layoutSelectionWindow.setLayoutData(gridDataSelectionWindow); + + + // Layout that contain the time spinner + // Contains : + // NanosecTextGroup spTimeRangeWindow + // NanosecTextGroup spCurrentWindowTime + // NanosecTextGroup spCurrentEventTime + Composite layoutTimesSpinner = new Composite(layoutFullView, SWT.NONE); + GridLayout gridTimesSpinner = new GridLayout(); + gridTimesSpinner.numColumns = 3; + gridTimesSpinner.marginHeight = 0; + gridTimesSpinner.marginWidth = 0; + gridTimesSpinner.horizontalSpacing = 0; + gridTimesSpinner.verticalSpacing = 0; + layoutTimesSpinner.setLayout(gridTimesSpinner); + GridData gridDataTimesSpinner = new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1); + layoutTimesSpinner.setLayoutData(gridDataTimesSpinner); + + + // Layout that contain the complete experiment histogram and related controls. + // Contains : + // Label lblExperimentStartTime + // Label lblExperimentStopTime + // ParentHistogramCanvas fullTraceCanvas + Composite layoutExperimentHistogram = new Composite(layoutFullView, SWT.NONE); + GridLayout gridExperimentHistogram = new GridLayout(); + gridExperimentHistogram.numColumns = 2; + gridExperimentHistogram.marginHeight = 0; + gridExperimentHistogram.marginWidth = 0; + gridExperimentHistogram.horizontalSpacing = 0; + gridExperimentHistogram.verticalSpacing = 0; + layoutExperimentHistogram.setLayout(gridExperimentHistogram); + GridData gridDataExperimentHistogram = new GridData(SWT.FILL, SWT.TOP, true, false, 2, 1); + layoutExperimentHistogram.setLayoutData(gridDataExperimentHistogram); + + + + // *** Everything related to the selection window is below + GridData gridDataSelectionWindowCanvas = new GridData(SWT.LEFT, SWT.TOP, true, false, 2, 2); + gridDataSelectionWindowCanvas.heightHint = SELECTED_WINDOW_CANVAS_HEIGHT; + gridDataSelectionWindowCanvas.minimumHeight = SELECTED_WINDOW_CANVAS_HEIGHT; + gridDataSelectionWindowCanvas.widthHint = selectedCanvasWidth; + gridDataSelectionWindowCanvas.minimumWidth = selectedCanvasWidth; + selectedWindowCanvas = new ChildrenHistogramCanvas(this, layoutSelectionWindow, SWT.BORDER); + selectedWindowCanvas.setLayoutData(gridDataSelectionWindowCanvas); + + GridData gridDataWindowMaxEvents = new GridData(SWT.FILL, SWT.TOP, true, false, 1, 1); + // Force a width, to avoid the control to enlarge if the number of events change + gridDataWindowMaxEvents.minimumWidth = nbEventWidth; + txtWindowMaxNbEvents = new Text(layoutSelectionWindow, SWT.READ_ONLY); + txtWindowMaxNbEvents.setFont(smallFont); + txtWindowMaxNbEvents.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_TITLE_INACTIVE_BACKGROUND)); + txtWindowMaxNbEvents.setEditable(false); + txtWindowMaxNbEvents.setText(""); + txtWindowMaxNbEvents.setLayoutData(gridDataWindowMaxEvents); + + GridData gridDataWindowMinEvents = new GridData(SWT.LEFT, SWT.BOTTOM, true, false, 1, 1); + // Force a width, to avoid the control to enlarge if the number of events change + gridDataWindowMinEvents.minimumWidth = nbEventWidth; + txtWindowMinNbEvents = new Text(layoutSelectionWindow, SWT.READ_ONLY); + txtWindowMinNbEvents.setFont(smallFont); + txtWindowMinNbEvents.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_TITLE_INACTIVE_BACKGROUND)); + txtWindowMinNbEvents.setEditable(false); + txtWindowMinNbEvents.setText(""); + txtWindowMinNbEvents.setLayoutData(gridDataWindowMinEvents); + + GridData gridDataWindowStart = new GridData(SWT.LEFT, SWT.TOP, false, false, 1, 1); + txtWindowStartTime = new Text(layoutSelectionWindow, SWT.READ_ONLY); + txtWindowStartTime.setFont(smallFont); + txtWindowStartTime.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_TITLE_INACTIVE_BACKGROUND)); + txtWindowStartTime.setEditable(false); + txtWindowStartTime.setText(""); + txtWindowStartTime.setLayoutData(gridDataWindowStart); + + GridData gridDataWindowStop = new GridData(SWT.RIGHT, SWT.TOP, false, false, 1, 1); + txtWindowStopTime = new Text(layoutSelectionWindow, SWT.READ_ONLY); + txtWindowStopTime.setFont(smallFont); + txtWindowStopTime.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_TITLE_INACTIVE_BACKGROUND)); + txtWindowStopTime.setEditable(false); + txtWindowStopTime.setText(""); + txtWindowStopTime.setLayoutData(gridDataWindowStop); + + GridData gridDataSpacer = new GridData(SWT.FILL, SWT.TOP, true, true, 1, 1); + gridDataSpacer.minimumWidth = nbEventWidth; + // *** HACK *** + // To align properly AND to make sure the canvas size is fixed, we NEED to make sure all "section" of the + // gridlayout are taken (and if possible of a fixed size). + // However, SWT is VERY VERY DUMB and won't consider griddata that contain no control. + // Since there will be missing a section, the SelectedWindowCanvas + NbEventsText will take 3 spaces, but + // startTimeText + stopTimeText will take only 2 (as if empty the other griddata of 1 will get ignored). + // StopTime will then take over the missing space; I want to align "stopTime" right on the end of canvas, so + // the added space to stop time would make it being aligned improperly + // So I NEED the empty griddata to be considered! + // Visually : + // |---------------|---------------|-----------| + // |SelectionCanvas SelectionCanvas|NbEventText| + // |SelectionCanvas SelectionCanvas|NbEventText| + // |---------------|---------------|-----------| + // |StartTime | StopTime| ??? | + // |---------------|---------------|-----------| + // + // So since SWT will only consider griddata with control, + // I need to create a totally useless control in the ??? section. + // That's ugly, useless and it is generally a bad practice. + // + // *** SUB-HACK *** + // Other interesting fact about SWT : the way it draws (Fill/Expand control in grid) will change if + // the control is a Text or a Label. + // A Label here will be "pushed" by startTime/stopTime Text and won't fill the full space as NbEventText. + // A Text here will NOT be "pushed" and would give a nice visual output. + // (NB : No, I am NOT kidding, try it for yourself!) + // + // Soooooo I guess I will use a Text here. Way to go SWT! + // Downside is that disabled textbox has a slightly different color (even if you force it yourself) so if I want + // to make the text "invisible", I have to keep it enabled (but read only), so it can be clicked on. + // + // Label uselessControlToByPassSWTStupidBug = new Label(layoutSelectionWindow, SWT.BORDER); // WON'T align correctly!!! + Text uselessControlToByPassSWTStupidBug = new Text(layoutSelectionWindow, SWT.READ_ONLY); // WILL align correctly!!! + uselessControlToByPassSWTStupidBug.setEditable(false); + uselessControlToByPassSWTStupidBug.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_TITLE_INACTIVE_BACKGROUND)); + uselessControlToByPassSWTStupidBug.setLayoutData(gridDataSpacer); + + + + // *** Everything related to the time text group is below + GridData gridDataCurrentEvent = new GridData(SWT.CENTER, SWT.CENTER, true, true, 1, 2); + ntgCurrentEventTime = new TimeTextGroup(this, layoutTimesSpinner, SWT.BORDER, SWT.BORDER, EVENT_CURRENT_TIME_LABEL_TEXT, HistogramConstant.formatNanoSecondsTime( 0L ), doesTimeTextGroupNeedAdjustment); + ntgCurrentEventTime.setLayoutData(gridDataCurrentEvent); + + GridData gridDataTimeRange = new GridData(SWT.CENTER, SWT.CENTER, true, true, 1, 2); + ntgTimeRangeWindow = new TimeTextGroup(this, layoutTimesSpinner, SWT.BORDER, SWT.BORDER, WINDOW_TIMERANGE_LABEL_TEXT, HistogramConstant.formatNanoSecondsTime( 0L ), doesTimeTextGroupNeedAdjustment); + ntgTimeRangeWindow.setLayoutData(gridDataTimeRange); + + GridData gridDataCurrentWindow = new GridData(SWT.CENTER, SWT.CENTER, true, true, 1, 2); + ntgCurrentWindowTime = new TimeTextGroup(this, layoutTimesSpinner, SWT.BORDER, SWT.BORDER, WINDOW_CURRENT_TIME_LABEL_TEXT, HistogramConstant.formatNanoSecondsTime( 0L ), doesTimeTextGroupNeedAdjustment); + ntgCurrentWindowTime.setLayoutData(gridDataCurrentWindow); + + + + // *** Everything related to the experiment canvas is below + GridData gridDataExperimentCanvas = new GridData(SWT.FILL, SWT.TOP, true, false, 2, 1); + gridDataExperimentCanvas.heightHint = FULL_TRACE_CANVAS_HEIGHT; + gridDataExperimentCanvas.minimumHeight = FULL_TRACE_CANVAS_HEIGHT; + fullExperimentCanvas = new ParentHistogramCanvas(this, layoutExperimentHistogram, SWT.BORDER); + fullExperimentCanvas.setLayoutData(gridDataExperimentCanvas); + + GridData gridDataExperimentStart = new GridData(SWT.LEFT, SWT.TOP, false, false, 1, 1); + txtExperimentStartTime = new Text(layoutExperimentHistogram, SWT.READ_ONLY); + txtExperimentStartTime.setFont(smallFont); + txtExperimentStartTime.setText(""); + txtExperimentStartTime.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_TITLE_INACTIVE_BACKGROUND)); + txtExperimentStartTime.setEditable(false); + txtExperimentStartTime.setLayoutData(gridDataExperimentStart); + + GridData gridDataExperimentStop = new GridData(SWT.RIGHT, SWT.TOP, false, false, 1, 1); + txtExperimentStopTime = new Text(layoutExperimentHistogram, SWT.READ_ONLY); + txtExperimentStopTime.setFont(smallFont); + txtExperimentStopTime.setText(""); + txtExperimentStopTime.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_TITLE_INACTIVE_BACKGROUND)); + txtExperimentStopTime.setEditable(false); + txtExperimentStopTime.setLayoutData(gridDataExperimentStop); + } + + // *** FIXME *** + // This is mainly used because of a because in the "experimentSelected()" notification, we shouldn't need this + /** + * Method called when the view receive the focus.

+ * If ExperimentSelected didn't send us a request yet, get the current Experiment and fire requests + */ + @SuppressWarnings("unchecked") + @Override + public void setFocus() { + // WARNING : This does not seem to be thread safe + TmfExperiment tmpExperiment = (TmfExperiment)TmfExperiment.getCurrentExperiment(); + + if ( (dataBackgroundFullRequest == null) && (tmpExperiment != null) ) { + createCanvasAndRequests(tmpExperiment); + } + + // Call a redraw for everything + parent.redraw(); + } + + /** + * Method called when the user select (double-click on) an experiment.

+ * We will create the needed canvas and fire the requests. + * + * @param signal Signal received from the framework. Contain the experiment. + */ + @SuppressWarnings("unchecked") + @TmfSignalHandler + public void experimentSelected(TmfExperimentSelectedSignal signal) { + TmfExperiment tmpExperiment = (TmfExperiment)signal.getExperiment(); + createCanvasAndRequests(tmpExperiment); + } + + // *** VERIFY *** + // Not sure what this should do since I don't know when it will be called + // Let's do the same thing as experimentSelected for now + // + /** + * Method called when an experiment is updated (??).

+ * ...for now, do nothing, as udating an experiment running in the background might cause crash + * + * @param signal Signal received from the framework. Contain the experiment. + */ +// @SuppressWarnings("unchecked") + @TmfSignalHandler + public void experimentUpdated(TmfExperimentUpdatedSignal signal) { +// +// TmfExperiment tmpExperiment = (TmfExperiment)signal.getExperiment(); +// +// // Make sure the UI object are sane +// resetControlsContent(); +// +// // Redraw the canvas right away to have something "clean" as soon as we can +// fullExperimentCanvas.redraw(); +// selectedWindowCanvas.redraw(); +// +// // Recreate the request +// createCanvasAndRequests(tmpExperiment); + } + + /** + * Method called when synchonization is active and that the user select an event.

+ * We update the current event timeTextGroup and move the selected window if needed. + * + * @param signal Signal received from the framework. Contain the event. + */ + @TmfSignalHandler + public void currentTimeUpdated(TmfTimeSynchSignal signal) { + // In case we received our own signal + if (signal.getSource() != this) { + TmfTimestamp currentTime = signal.getCurrentTime(); + + // Update the current event controls + currentEventTime = currentTime.getValue(); + updateSelectedEventTime(); + + // If the given event is outside the selection window, recenter the window + if ( isGivenTimestampInSelectedWindow( currentEventTime ) == false) { + fullExperimentCanvas.setWindowCenterPosition( fullExperimentCanvas.getHistogramContent().getClosestXPositionFromTimestamp(currentEventTime) ); + // Notify control that the window changed + windowChangedNotification(); + // Send a broadcast to the framework about the window change + sendTmfRangeSynchSignalBroadcast(); + } + } + } + + @TmfSignalHandler + public void synchToTimeRange(TmfRangeSynchSignal signal) { + if ( (signal != null) && (signal.getSource() != this) ) { + if ( lastUsedExperiment != null ) { + long currentTime = signal.getCurrentTime().getValue(); + long windowStart = signal.getCurrentRange().getStartTime().getValue(); + long windowEnd = signal.getCurrentRange().getEndTime().getValue(); + long windowTimeWidth = (windowEnd - windowStart); + + // Recenter the window + fullExperimentCanvas.setWindowCenterPosition( fullExperimentCanvas.getHistogramContent().getClosestXPositionFromTimestamp(windowStart + (windowTimeWidth/2)) ); + fullExperimentCanvas.setSelectedWindowSize(windowTimeWidth); + + // *** HACK *** + // Views could send us incorrect current event value (event outside the current window) + // Here we make sure the value is sane, otherwise, we force it as the left border of the window + if ( isGivenTimestampInSelectedWindow( currentTime ) == false ) { + currentTime = windowStart; + } + currentEventTime = currentTime; + + // Notify control that the window changed + windowChangedNotification(); + + // Make sure we redraw the change + fullExperimentCanvas.redraw(); + } + } + } + + + /* + * Create the canvas needed and issue the requests + * + * @param newExperiment Experiment we will use for the request + */ + private void createCanvasAndRequests(TmfExperiment newExperiment) { + // Save the experiment we are about to use + lastUsedExperiment = newExperiment; + + // Create a copy of the trace that will be use only by the full experiment request + TmfExperiment experimentCopy = newExperiment.createTraceCopy(); + + // Create the content for the full experiment. + // This NEED to be created first, as we use it in the selectedWindowCanvas + fullExperimentCanvas.createNewHistogramContent(fullExperimentCanvas.getSize().x, FULL_TRACE_BAR_WIDTH, FULL_TRACE_CANVAS_HEIGHT, FULL_TRACE_DIFFERENCE_TO_AVERAGE); + fullExperimentCanvas.createNewSelectedWindow(DEFAULT_WINDOW_SIZE); + currentEventTime = newExperiment.getStartTime().getValue(); + // Set the window of the fullTrace canvas visible. + fullExperimentCanvas.getCurrentWindow().setSelectedWindowVisible(true); + fullExperimentCanvas.getHistogramContent().resetTable(newExperiment.getStartTime().getValue(), newExperiment.getEndTime().getValue()); + + // Create the content for the selected window. + selectedWindowCanvas.createNewHistogramContent(selectedWindowCanvas.getSize().x ,SELECTED_WINDOW_BAR_WIDTH, SELECTED_WINDOW_CANVAS_HEIGHT, SELECTED_WINDOW_DIFFERENCE_TO_AVERAGE); + selectedWindowCanvas.getHistogramContent().resetTable(fullExperimentCanvas.getCurrentWindow().getTimestampOfLeftPosition(), fullExperimentCanvas.getCurrentWindow().getTimestampOfRightPosition()); + + // Make sure the UI object are sane + resetControlsContent(); + + // Redraw the canvas right away to have something "clean" as soon as we can + if ( dataBackgroundFullRequest != null ) { + fullExperimentCanvas.redraw(); + selectedWindowCanvas.redraw(); + } + // Nullify the (possible) old request to be sure we start we something clean + // Note : this is very important for the order of the request below, + // see "TODO" in performSelectedWindowEventsRequest + dataBackgroundFullRequest = null; + selectedWindowRequest = null; + + // Perform both request. + // Order is important here, the small/synchronous request for the selection window should go first + performSelectedWindowEventsRequest(newExperiment); + performAllTraceEventsRequest(experimentCopy); + } + + /** + * Perform a new request for the Selection window.

+ * This assume the full experiment canvas has correct information about the selected window; + * we need the fullExperimentCanvas' HistogramContent to be created and a selection window to be set. + * + * @param experiment The experiment we will select from + */ + public void performSelectedWindowEventsRequest(TmfExperiment experiment) { + + HistogramSelectedWindow curSelectedWindow = fullExperimentCanvas.getCurrentWindow(); + + // If no selection window exists, we will try to cerate one; + // however this will most likely fail as the content is probably not created either + if ( curSelectedWindow == null ) { + fullExperimentCanvas.createNewSelectedWindow( DEFAULT_WINDOW_SIZE ); + curSelectedWindow = fullExperimentCanvas.getCurrentWindow(); + } + + // The request will go from the Left timestamp of the window to the Right timestamp + // This assume that out-of-bound value are handled by the SelectionWindow itself + LttngTimestamp ts1 = new LttngTimestamp( curSelectedWindow.getTimestampOfLeftPosition() ); + LttngTimestamp ts2 = new LttngTimestamp( curSelectedWindow.getTimestampOfRightPosition() ); + TmfTimeRange tmpRange = new TmfTimeRange(ts1, ts2); + + // Set a (dynamic) time interval + long intervalTime = ( (ts2.getValue() - ts1.getValue()) / selectedWindowCanvas.getHistogramContent().getNbElement() ); + + selectedWindowRequest = performRequest(experiment, selectedWindowCanvas, tmpRange, intervalTime); + selectedWindowCanvas.redrawAsynchronously(); + } + + /** + * Perform a new request for the full experiment.

+ * NOTE : this is very long, we need to implement a way to run this in parallel (see TODO) + * + * @param experiment The experiment we will select from + */ + public void performAllTraceEventsRequest(TmfExperiment experiment) { + // Create a new time range from "start" to "end" + // That way, we will get "everything" in the trace + LttngTimestamp ts1 = new LttngTimestamp( experiment.getStartTime() ); + LttngTimestamp ts2 = new LttngTimestamp( experiment.getEndTime() ); + TmfTimeRange tmpRange = new TmfTimeRange(ts1, ts2); + + // Set a (dynamic) time interval + long intervalTime = ( (ts2.getValue() - ts1.getValue()) / fullExperimentCanvas.getHistogramContent().getNbElement() ); + + // *** VERIFY *** + // This would enable "fixed interval" instead of dynamic one. + // ... we don't need it, do we? + // + // long intervalTime = ((long)(0.001 * (double)1000000000)); + + // *** TODO *** + // It would be interesting if there was a way to tell the framework to run the request "in parallel" here. + // Mean a completetly independant copy of the Expereiment would be done and we would proceed on that. + // + dataBackgroundFullRequest = performRequest(experiment, fullExperimentCanvas, tmpRange, intervalTime); + fullExperimentCanvas.redrawAsynchronously(); + } + + // *** VERIFY *** + // This function is synchronized, is it a good idea? + // Tis is done to make sure requests arrive somewhat in order, + // this is especially important when request are issued from different thread. + /** + * Create a new request from the given data and send it to the framework.

+ * The request will be queued and processed later. + * + * @param experiment The experiment we will process the request on + * @param targetCanvas The canvas that will received the result + * @param newRange The range of the request + * @param newInterval The interval of time we use to store the result into the HistogramContent + */ + public synchronized HistogramRequest performRequest(TmfExperiment experiment, HistogramCanvas targetCanvas, TmfTimeRange newRange, long newInterval) { + HistogramRequest returnedRequest = null; + + // *** FIXME *** + // EVIL BUG! + // We use int.MAX_VALUE because we want every events BUT we don't know the number inside the range. + // HOWEVER, this would cause the request to run forever (or until it reach the end of trace). + // Seeting an EndTime does not seems to stop the request + returnedRequest = new HistogramRequest(newRange, Integer.MAX_VALUE, targetCanvas, newInterval ); + + // Send the request to the framework : it will be queued and processed later + experiment.sendRequest(returnedRequest); + + return returnedRequest; + } + + /** + * Function used to warn that the selection window changed.

+ * This might be called because the window moved or because its size changed.

+ * + * We will update the different control related to the selection window. + */ + public void windowChangedNotification() { + + if ( lastUsedExperiment != null ) { + // If a request is ongoing, try to stop it + if ( selectedWindowRequest.isCompleted() == false ) { + selectedWindowRequest.cancel(); + } + + // Get the latest window information + selectedWindowTime = fullExperimentCanvas.getCurrentWindow().getTimestampOfCenterPosition(); + selectedWindowTimerange = fullExperimentCanvas.getCurrentWindow().getWindowTimeWidth(); + + // If the current event time is outside the new window, change the current event + // The new current event will be the one closest to the LEFT side of the new window + if ( isGivenTimestampInSelectedWindow(currentEventTime) == false ) { + currentEventChangeNotification( fullExperimentCanvas.getCurrentWindow().getTimestampOfLeftPosition() ); + } + + // Perform a new request to read data about the new window + performSelectedWindowEventsRequest(lastUsedExperiment); + } + } + + /** + * Function used to tell that the current event changed.

+ * This might be called because the user changed the current event or + * because the last current event is now outside the selection window.

+ * + * We update the related control and send a signal to notify other views of the new current event. + * + * @param newCurrentEventTime + */ + public void currentEventChangeNotification(long newCurrentEventTime) { + + // Notify other views in the framework + if (currentEventTime != newCurrentEventTime) { + currentEventTime = newCurrentEventTime; + + // Update the UI control + updateSelectedEventTime(); + } + } + + public void sendTmfTimeSynchSignalBroadcast() { + +// System.out.println("sendTmfTimeSynchSignalBroadcast " + System.currentTimeMillis()); + + // Send a signal to the framework + LttngTimestamp tmpTimestamp = new LttngTimestamp(currentEventTime); + broadcast(new TmfTimeSynchSignal(this, tmpTimestamp)); + } + + /** + * Function used to tell that the timerange (window) changed.

+ * This will most likely be called if the time window is resized. + * + * We send a signal to notify other views of the new timerange. + */ + public void sendTmfRangeSynchSignalBroadcast() { + +// System.out.println("sendTmfRangeSynchSignalBroadcast " + System.currentTimeMillis()); + + // *** TODO *** + // Not very elegant... we need to chance this below. + // + long centerTime = fullExperimentCanvas.getCurrentWindow().getTimestampOfCenterPosition(); + long windowWidth = fullExperimentCanvas.getCurrentWindow().getWindowTimeWidth(); + + long startTime = centerTime-windowWidth; + if ( startTime < fullExperimentCanvas.getHistogramContent().getStartTime() ) { + startTime = fullExperimentCanvas.getHistogramContent().getStartTime(); + } + LttngTimestamp tmpStartTime = new LttngTimestamp(startTime); + + long endTime = centerTime+windowWidth; + if ( endTime > fullExperimentCanvas.getHistogramContent().getEndTime() ) { + endTime = fullExperimentCanvas.getHistogramContent().getEndTime(); + } + LttngTimestamp tmpEndTime = new LttngTimestamp(endTime); + + TmfTimeRange tmpTimeRange = new TmfTimeRange(tmpStartTime, tmpEndTime); + LttngTimestamp tmpEventTime = new LttngTimestamp(currentEventTime); + + // Send a signal to the framework + broadcast(new TmfRangeSynchSignal(this, tmpTimeRange, tmpEventTime)); + } + + /** + * Function that will be called when one of the time text group value is changed.

+ * Since we don't (and can't unless we subclass them) know which one, we check them all. + */ + public void timeTextGroupChangeNotification() { + + // Get all the time text group value + long newCurrentTime = ntgCurrentEventTime.getValue(); + long newSelectedWindowTime = ntgCurrentWindowTime.getValue(); + long newSelectedWindowTimeRange = ntgTimeRangeWindow.getValue(); + + // If the user changed the current event time, call the notification + if ( newCurrentTime != currentEventTime ) { + currentEventChangeNotification( newCurrentTime ); + // Send a broadcast to the framework about the window change + sendTmfTimeSynchSignalBroadcast(); + } + + // If the user changed the selected window time, recenter the window and call the notification + if ( newSelectedWindowTime != selectedWindowTime ) { + selectedWindowTime = newSelectedWindowTime; + fullExperimentCanvas.setWindowCenterPosition( fullExperimentCanvas.getHistogramContent().getClosestXPositionFromTimestamp(selectedWindowTime) ); + windowChangedNotification(); + // Send a broadcast to the framework about the window change + sendTmfRangeSynchSignalBroadcast(); + } + + // If the user changed the selected window size, resize the window and call the notification + if ( newSelectedWindowTimeRange != selectedWindowTimerange ) { + selectedWindowTimerange = newSelectedWindowTimeRange; + fullExperimentCanvas.resizeWindowByAbsoluteTime(selectedWindowTimerange); + windowChangedNotification(); + // Send a broadcast to the framework about the window change + sendTmfRangeSynchSignalBroadcast(); + } + + } + + /** + * Getter for the last used experiment.

+ * This might be different than the current experiment or even null. + * + * @return the last experiment we used in this view + */ + public TmfExperiment getLastUsedExperiment() { + return lastUsedExperiment; + } + + /** + * Check if a given timestamp is inside the selection window.

+ * This assume fullExperimentCanvas contain a valid HistogramContent + * + * @param timestamp the timestamp to check + * + * @return if the time is inside the selection window or not + */ + public boolean isGivenTimestampInSelectedWindow(long timestamp) { + boolean returnedValue = true; + + // If the content is not set correctly, this will return weird (or even null) result + if ( (timestamp < fullExperimentCanvas.getCurrentWindow().getTimestampOfLeftPosition() ) || + (timestamp > fullExperimentCanvas.getCurrentWindow().getTimestampOfRightPosition() ) ) + { + returnedValue = false; + } + + return returnedValue; + } + + /** + * Reset the content of all Controls.

+ * WARNING : Calls in there are not thread safe and can't be called from different thread than "main" + */ + public void resetControlsContent() { + + TmfExperiment tmpExperiment = getLastUsedExperiment(); + + // Use the previous Start and End time, or default if they are not available + String startTime = null; + String stopTime = null; + if ( tmpExperiment != null ) { + startTime = HistogramConstant.formatNanoSecondsTime( tmpExperiment.getStartTime().getValue() ); + stopTime = HistogramConstant.formatNanoSecondsTime( tmpExperiment.getEndTime().getValue() ); + } + else { + startTime = HistogramConstant.formatNanoSecondsTime( 0L ); + stopTime = HistogramConstant.formatNanoSecondsTime( 0L ); + } + + txtExperimentStartTime.setText( startTime ); + txtExperimentStopTime.setText( stopTime ); + txtExperimentStartTime.getParent().layout(); + + txtWindowMaxNbEvents.setText("" + 0); + txtWindowMinNbEvents.setText("" + 0); + txtWindowStartTime.setText( HistogramConstant.formatNanoSecondsTime( 0L ) ); + txtWindowStopTime.setText( HistogramConstant.formatNanoSecondsTime( 0L ) ); + txtWindowStartTime.getParent().layout(); + + ntgCurrentWindowTime.setValue( HistogramConstant.formatNanoSecondsTime( 0L ) ); + ntgTimeRangeWindow.setValue( HistogramConstant.formatNanoSecondsTime( 0L ) ); + + // Using "startTime" here can avoid an useless TmfTimeSynchSignal here + // However it look ugly to have only this time + ntgCurrentEventTime.setValue( HistogramConstant.formatNanoSecondsTime( 0L ) ); + } + + /** + * Update the content of the controls related to the full experiment canvas

+ * WARNING : Calls in there are not thread safe and can't be called from different thread than "main" + */ + public void updateFullExperimentInformation() { + + String startTime = HistogramConstant.formatNanoSecondsTime( fullExperimentCanvas.getHistogramContent().getStartTime() ); + String stopTime = HistogramConstant.formatNanoSecondsTime( fullExperimentCanvas.getHistogramContent().getEndTime() ); + + txtExperimentStartTime.setText( startTime ); + txtExperimentStopTime.setText( stopTime ); + + // Take one of the parent and call its layout to update control size + // Since both control have the same parent, only one call is needed + txtExperimentStartTime.getParent().layout(); + + // Update the selected window, just in case + // This should give a better user experience and it is low cost + updateSelectedWindowInformation(); + } + + /** + * Update the content of the controls related to the selection window canvas

+ * WARNING : Calls in there are not thread safe and can't be called from different thread than "main" + */ + public void updateSelectedWindowInformation() { + // Update the timestamp as well + updateSelectedWindowTimestamp(); + + txtWindowMaxNbEvents.setText( Long.toString(selectedWindowCanvas.getHistogramContent().getHeighestEventCount()) ); + txtWindowMinNbEvents.setText(Long.toString(0)); + + // Refresh the layout + txtWindowMaxNbEvents.getParent().layout(); + } + + /** + * Update the content of the controls related to the timestamp of the selection window

+ * WARNING : Calls in there are not thread safe and can't be called from different thread than "main" + */ + public void updateSelectedWindowTimestamp() { + String startTime = HistogramConstant.formatNanoSecondsTime( selectedWindowCanvas.getHistogramContent().getStartTime() ); + String stopTime = HistogramConstant.formatNanoSecondsTime( selectedWindowCanvas.getHistogramContent().getEndTime() ); + txtWindowStartTime.setText( startTime ); + txtWindowStopTime.setText( stopTime ); + + ntgCurrentWindowTime.setValue( fullExperimentCanvas.getCurrentWindow().getTimestampOfCenterPosition() ); + ntgTimeRangeWindow.setValue( fullExperimentCanvas.getCurrentWindow().getWindowTimeWidth() ); + + // If the current event time is outside the selection window, recenter our window + if ( isGivenTimestampInSelectedWindow(ntgCurrentEventTime.getValue()) == false ) { + currentEventChangeNotification( fullExperimentCanvas.getCurrentWindow().getTimestampOfCenterPosition() ); + } + + // Take one control in each group to call to refresh the layout + // Since both control have the same parent, only one call is needed + txtWindowStartTime.getParent().layout(); + ntgCurrentWindowTime.getParent().layout(); + } + + /** + * Update the controls related current event.

+ * The call here SHOULD be thread safe and can be call from any threads. + */ + public void updateSelectedEventTime() { + ntgCurrentEventTime.setValueAsynchronously(currentEventTime); + // Tell the selection canvas which event is currently selected + // This give a nice graphic output + selectedWindowCanvas.getHistogramContent().setSelectedEventTimeInWindow(currentEventTime); + selectedWindowCanvas.redrawAsynchronously(); + } + + /** + * Method called when the view is moved.

+ * + * Just redraw everything... + * + * @param event The controle event generated by the move. + */ + public void controlMoved(ControlEvent event) { + parent.redraw(); + } + + /** + * Method called when the view is resized.

+ * + * We will make sure that the size didn't change more than the content size.

+ * Otherwise we need to perform a new request for the full experiment because we are missing data). + * + * @param event The control event generated by the resize. + */ + public void controlResized(ControlEvent event) { + + // Ouch! The screen enlarged (screen resolution changed?) so far that we miss content to fill the space. + if ( parent.getDisplay().getBounds().width > fullExperimentCanvas.getHistogramContent().getNbElement() ) { + if ( lastUsedExperiment != null ) { + createCanvasAndRequests(lastUsedExperiment); + } + } + + } +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/ParentHistogramCanvas.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/ParentHistogramCanvas.java new file mode 100644 index 0000000000..cb2ce61ddc --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/ParentHistogramCanvas.java @@ -0,0 +1,173 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * William Bourque - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.histogram; + +import org.eclipse.swt.widgets.Composite; + +/** + * ParentHistogramCanvas + *

+ * Extended implementation of the HistogramCanvas. + *

+ * This canvas goal is to display the "Full experiment" histogram. + */ +public class ParentHistogramCanvas extends HistogramCanvas { + + protected HistogramView parentHistogramWindow = null; + + /** + * ParentHistogramCanvas constructor.

+ * Same as HistogramCanvas, but receive a parent HistogramView that we can call from here. + * + * @param parent Composite control which will be the parent of the new instance (cannot be null) + * @param Style the style of control to construct + */ + public ParentHistogramCanvas(HistogramView newParentWindow, Composite parent, int style) { + super(parent, style); + + parentHistogramWindow = newParentWindow; + } + + /** + * Create a new HistogramContent for this HistogramCanvas

+ * A new empty canvas will then be created. + * + * IMPORTANT NOTE : This implementaton use the next power of 2 to the full screen resolution as the content size. + * This allow us to resize the canvas at low cost (i.e. : no need to reissue a full request) + * We need a "particular" paint listener that know about this. + * + * @param canvasSize Size of the parent canvas. + * @param widthPerBar Width of the histogram "bars" + * @param barsHeight Height of the histogram "bars" + * @param maxBarsDifferenceToAverage Factor used to "chop" bars that are too tall. Set to something big (100.0?) if not needed. + */ + @Override + public void createNewHistogramContent(int canvasSize, int widthPerBar, int barsHeight, double maxBarsDifferenceToAverage) { + + // *** FIXME *** + // Note there MIGHT be some unhandled case, like if the resolution of the screen change + // or if a new screen is plugged. + // Let's ignore them for now. + // + // The maximum size the canvas could ever had + int canvasMaxSize = getParent().getDisplay().getBounds().width; + + // Calculate the power of two superior to the max size + int exp = (int)Math.ceil( Math.log( (double)canvasMaxSize ) / Math.log(2.0) ); + int contentSize = (int)Math.pow(2, exp); + + // Create the content + histogramContent = new HistogramContent( contentSize, canvasSize, widthPerBar, barsHeight, maxBarsDifferenceToAverage); + + // We need to ajust the "maxDifferenceToAverageFactor" as the bars we draw might be slitghly larger than the value asked + // Each "interval" are concatenated when draw so the worst case should be : + // contentSize / (closest power of 2 to canvasMaxSize) + // Ex : if canvasSize is 1500 -> (2048 / 1024) == 2 so maxDiff should be twice larger + // + // Note : this is not perfect, if the screen is resized after we calculate this, the resulting output can be quite ugly + // For this reason, this will be recalculated in the paintListener as well. + double maxBarsDiffFactor = ((double)contentSize / Math.pow(2, exp-1)); + histogramContent.setMaxDifferenceToAverageFactor(maxBarsDiffFactor); + } + + /* + * Create a histogram paint listener and bind it to this canvas.

+ * + * Note : This one is a bit particular, as it is made to draw content that is of a power of 2. + * The default one draw content that is relative to the real pixels size. + */ + @Override + protected void createAndAddPaintListener() { + paintListener = new ParentHistogramCanvasPaintListener(this);; + this.addPaintListener( paintListener ); + } + + /** + * Function that is called when the selection window is moved.

+ * Note: Given position should be relative to the previous (centered) absolute position.

+ * + * Calculate the new position then re-center the window.

+ * It will also notify the HistogramView that the window changed. + * + * @param newRelativeXPosition New position relative to the last known absolute position. + */ + @Override + public void moveWindow(int newRelativeXPosition) { + int absolutePosition = currentWindow.getWindowXPositionCenter() + newRelativeXPosition; + + setWindowCenterPosition(absolutePosition); + notifyParentSelectionWindowChangedAsynchronously(); + } + + /** + * Function that is called when the selection window is re-centered.

+ * Note: Given position should be absolute to the window and need to be the selection window center.

+ * + * Recenter the window and notify the HistogramView that the window changed. + * + * @param newRelativeXPosition New absolute position. + */ + @Override + public void setWindowCenterPosition(int newAbsoluteXPosition) { + + if ( newAbsoluteXPosition < 0 ) { + newAbsoluteXPosition = 0; + } + else if ( newAbsoluteXPosition > getParent().getSize().x ) { + newAbsoluteXPosition = getParent().getSize().x; + } + + if ( newAbsoluteXPosition != currentWindow.getWindowXPositionCenter() ) { + currentWindow.setWindowXPositionCenter(newAbsoluteXPosition); + redrawAsynchronously(); + } + } + + /** + * Function that is called when the selection window size (time width) changed by an absolute time.

+ * Note: Given time should be in nanoseconds, positive. + * + * Set the new window size and notify the HistogramView that the window changed. + * + * @param newTime New absoulte time (in nanoseconds) to apply to the window. + */ + @Override + public void resizeWindowByAbsoluteTime(long newTime) { + if ( newTime != getSelectedWindowSize() ) { + setSelectedWindowSize(newTime); + + notifyParentSelectionWindowChangedAsynchronously(); + redrawAsynchronously(); + } + } + + /** + * Notify the parent HistogramView that we have updated information.

+ * This is intended to be called at the end of the request when we know we have up-to-date information. + */ + @Override + public void notifyParentUpdatedInformation() { + parentHistogramWindow.updateFullExperimentInformation(); + } + + /** + * Notify the parent HistogramView that the SelectionWindow changed.

+ * This is intended to be called when the window move or is resized. + */ + @Override + public void notifyParentSelectionWindowChanged() { + // Notify the parent view that something changed + parentHistogramWindow.windowChangedNotification(); + // Send a broadcast to the framework about the window change + parentHistogramWindow.sendTmfRangeSynchSignalBroadcast(); + } +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/ParentHistogramCanvasPaintListener.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/ParentHistogramCanvasPaintListener.java new file mode 100644 index 0000000000..932aaecb37 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/ParentHistogramCanvasPaintListener.java @@ -0,0 +1,144 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * William Bourque - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.histogram; + +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.graphics.Rectangle; + +/** + * HistogramCanvasPaintListener + *

+ * Implementation of a PaintListener for the specific need of the ParentHistogramCanvas. + *

+ * The difference with the default one is that this one take a content that is the power of 2 higher + * than the display size.

+ * + * When it is time to draw, it takes the closest power of 2 smaller than the canvas size; it is then easy to + * concatenate the interval as they are both power of 2.

+ * The difference between the power of 2 and the not-power-of-2 canvas size is then filled by drawing bar that are + * slightly larger every (power/canvasSize) interval.

+ */ +public class ParentHistogramCanvasPaintListener extends HistogramCanvasPaintListener +{ + public ParentHistogramCanvasPaintListener(HistogramCanvas newParentCanvas) { + super(newParentCanvas); + } + + + // *** VERIFY *** + // Is it good to put this synchronized? + // + /** + * Draw the histogram bars in the canvas.

+ * This drawing function expect the content to be the power of 2 higher than the canvas size. + * The bars size will be slightly dynamic to fill the gap between the power and the canvas size.

+ * + * Note : This draw function is somewhat heavier than the default one. + * + * @param event The generated paint event when redraw is called. + */ + @Override + public synchronized void drawHistogram(PaintEvent event) { + HistogramContent tmpContent = parentCanvas.getHistogramContent(); + int tmpBarWidth = tmpContent.getBarsWidth(); + int canvasSize = event.width; + + event.gc.setBackground(event.display.getSystemColor(HistogramConstant.HISTOGRAM_BARS_COLOR)); + + // Calculate the closest power of 2 just smaller than the canvas size + int closestPowerToCanvas = (int)Math.pow(2, Math.floor( Math.log( canvasSize ) / Math.log(2.0) )); + + // Make sure the canvas didn't change size, it which case we need to recalculate our heights + recalculateHeightIfCanvasSizeChanged(); + + // Calculate the factor of difference between canvas and the power + double factor = (double)canvasSize / (double)closestPowerToCanvas; + // Calculate how many interval will need to be concatenated into one pixel + int intervalDifference = (tmpContent.getNbElement() / closestPowerToCanvas)*tmpBarWidth; + + // This keep a link between the position in "power" and the pixel we draw + // I.e. correlation between position in the power ("fake" pixels) and the position in the canvas ("real" pixels) + // So if pos == 30 and factor == 1.5, we know that the pixel that draw this pos is (30 * 1.5) == 45 + int posInPower = 0; + int widthFilled = 0; + + // Read from 0 up to the currently ready position + // We advance by "intervalDifference" as the bars migth not represent 1 interval only + for( int contentPos=0; contentPos < tmpContent.getReadyUpToPosition(); contentPos += intervalDifference ) { + // Width of the current item. + // Vary because of the difference between the power of 2 and the canvas size + // Ex: if power == 1024 and canvas == 1500, a bars every (1024/1500) will have a size of 2 instead of 1. + int itemWidth = (int)( Math.ceil((double)(posInPower+1)*factor) - Math.ceil((double)posInPower*factor) ); + itemWidth = itemWidth*tmpBarWidth; + + // Concatenate all the element in the interval + // Ex : if power == 1024 and content == 2048, every (2048/1024)*bars_width will be concatenated + int thisElementHeight = 0; + for ( int concatPos=0; concatPos real_pixel, + // this is used to calculate the width of each element + posInPower++; + } + + // Clear the remaining space in the canvas (there should not be any) so it appears clean. + event.gc.setBackground(event.display.getSystemColor(HistogramConstant.EMPTY_BACKGROUND_COLOR)); + Rectangle rect = new Rectangle(widthFilled, 0, event.width, event.height); + event.gc.fillRectangle(rect); + } + + /* + * The function will make sure that the "max difference average" factor is still the same as before; + * if not, the heigth of the events will be recalculated.

+ * + * The factor might change if the canvas is resized by a big factor.

+ */ + protected void recalculateHeightIfCanvasSizeChanged() { + HistogramContent tmpContent = parentCanvas.getHistogramContent(); + // We need to ajust the "maxDifferenceToAverageFactor" as the bars we draw might be slitghly larger than the value asked + // Each "interval" are concatenated when draw so the worst case should be : + // contentSize / (closest power of 2 to canvasMaxSize) + // Ex : if canvasSize is 1500 -> (2048 / 1024) == 2 so maxDiff should be twice larger + // + // His is set in the create content of the canvas, but we need to recalculate it + // here because the window might have been resized! + int exp = (int)Math.floor( Math.log( (double)tmpContent.getCanvasWindowSize() ) / Math.log(2.0) ); + int contentSize = (int)Math.pow(2, exp); + double maxBarsDiffFactor = ((double)tmpContent.getNbElement() / (double)contentSize ); + + // Floating point comparaison : + // We consider it is different if the difference is greater than 10^-3 + if ( Math.abs(maxBarsDiffFactor - tmpContent.getMaxDifferenceToAverageFactor()) > 0.001 ) { + // The factor changed! That's unfortunate because it will take a while to recalculate. + tmpContent.setMaxDifferenceToAverageFactor(maxBarsDiffFactor); + tmpContent.recalculateHeightFactor(); + tmpContent.recalculateEventHeight(); + } + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/TimeTextGroup.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/TimeTextGroup.java new file mode 100644 index 0000000000..1c887aa662 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/histogram/TimeTextGroup.java @@ -0,0 +1,476 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.histogram; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.FontData; +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.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +/** + * TimeTextGroup + *

+ * Special control for HistogramView + *

+ * This control will give you a group, a text box and a label at once. + */ +public class TimeTextGroup implements FocusListener, KeyListener { + + protected static final String NANOSEC_LABEL = "sec"; + protected static final String LONGEST_STRING_VALUE = "." + Long.MAX_VALUE; + protected static final int MAX_CHAR_IN_TEXTBOX = LONGEST_STRING_VALUE.length(); + + // The "small font" height used to display time will be "default font" minus this constant + protected static final int VERY_SMALL_FONT_MODIFIER = 2; + protected static final int SMALL_FONT_MODIFIER = 1; + + // Indentation size + protected static final int DEFAULT_INDENT_SIZE = 10; + + protected HistogramView parentView = null; + protected AsyncTimeTextGroupRedrawer asyncRedrawer = null; + + protected Group grpName = null; + protected Text txtNanosec = null; + protected Label lblNanosec = null; + + protected long timeValue = 0L; + + /** + * Default Constructor.

+ * + * @param newParentView Parent HistogramView + * @param parent Parent Composite, used to position the inner controls. + * @param textStyle Style of the textbox. Usually SWT.BORDER or SWT.NONE (or anything that suit a Text) + * @param groupStyle Style of the group. Anything that suite a Text + */ + public TimeTextGroup(HistogramView newParentView, Composite parent, int textStyle, int groupStyle) { + this(newParentView, parent, textStyle, groupStyle, "", HistogramConstant.formatNanoSecondsTime(0L), false); + } + + /** + * Default Constructor with adjustement for small screen.

+ * + * @param newParentView Parent HistogramView + * @param parent Parent Composite, used to position the inner controls. + * @param textStyle Style of the textbox. Usually SWT.BORDER or SWT.NONE (or anything that suit a Text) + * @param groupStyle Style of the group. Anything that suite a Text + * @param isSpaceSaverNeeded Value that tell if we try to save some space in the control. + */ + public TimeTextGroup(HistogramView newParentView, Composite parent, int textStyle, int groupStyle, boolean isSpaceSaverNeeded) { + this(newParentView, parent, textStyle, groupStyle, "", HistogramConstant.formatNanoSecondsTime(0L), isSpaceSaverNeeded); + } + + /** + * Default Constructor, allow you to give the groupname and the textbox value.

+ * + * @param newParentView Parent HistogramView + * @param parent Parent Composite, used to position the inner controls. + * @param textStyle Style of the textbox. Usually SWT.BORDER or SWT.NONE (or anything that suit a Text) + * @param groupStyle Style of the group. Anything that suite a Text + * @param groupValue Value (label) of the group. + * @param textValue Value of the textbox. + */ + public TimeTextGroup(HistogramView newParentView, Composite parent, int textStyle, int groupStyle, String groupValue, String textValue) { + this(newParentView, parent, textStyle, groupStyle, groupValue, textValue, false); + } + + /** + * Default Constructor with adjustement for small screen, allow you to give the groupname and the textbox value.

+ * + * @param newParentView Parent HistogramView + * @param parent Parent Composite, used to position the inner controls. + * @param textStyle Style of the textbox. Usually SWT.BORDER or SWT.NONE (or anything that suit a Text) + * @param groupStyle Style of the group. Anything that suite a Text + * @param groupValue Value (label) of the group. + * @param textValue Value of the textbox. + * @param isSpaceSaverNeeded Value that tell if we try to save some space in the control. + */ + public TimeTextGroup(HistogramView newParentView, Composite parent, int textStyle, int groupStyle, String groupValue, String textValue, boolean isSpaceSaverNeeded) { + Font font = parent.getFont(); + FontData tmpFontData = font.getFontData()[0]; + + Font smallFont = null; + int textBoxSize = -1; + int indentSize = -1; + + // If we were asked to save size, calculate the correct value here + if ( isSpaceSaverNeeded == true ) { + smallFont = new Font(font.getDevice(), tmpFontData.getName(), tmpFontData.getHeight()-VERY_SMALL_FONT_MODIFIER, tmpFontData.getStyle()); + + // No minimum textBoxSize and no indent size + textBoxSize = 0; + indentSize = 0; + } + else { + // We use only a slightly smaller font + smallFont = new Font(font.getDevice(), tmpFontData.getName(), tmpFontData.getHeight()-SMALL_FONT_MODIFIER, tmpFontData.getStyle()); + + // ** Creation of the textbox + // Calculate the optimal size of the textbox already + // This will avoid the control to move around and resize when bigger value are given + textBoxSize = HistogramConstant.getTextSizeInControl(parent, LONGEST_STRING_VALUE); + + // Default indent + indentSize = DEFAULT_INDENT_SIZE; + } + + parentView = newParentView; + + // ** Creation of the group + GridLayout gridLayoutgroup = new GridLayout(2, false); + gridLayoutgroup.horizontalSpacing = 0; + gridLayoutgroup.verticalSpacing = 0; + grpName = new Group(parent, groupStyle); + grpName.setText(groupValue); + grpName.setFont(smallFont); + grpName.setLayout(gridLayoutgroup); + + txtNanosec = new Text(grpName, textStyle); + txtNanosec.setTextLimit( MAX_CHAR_IN_TEXTBOX ); + txtNanosec.setText( textValue ); + txtNanosec.setFont(smallFont); + GridData gridDataTextBox = new GridData(SWT.LEFT, SWT.CENTER, true, false); + gridDataTextBox.horizontalIndent = indentSize; + gridDataTextBox.verticalIndent = 0; + gridDataTextBox.minimumWidth = textBoxSize; + txtNanosec.setLayoutData(gridDataTextBox); + + // ** Creation of the label + lblNanosec = new Label(grpName, SWT.LEFT); + lblNanosec.setText(NANOSEC_LABEL); + lblNanosec.setFont(smallFont); + GridData gridDataLabel = new GridData(SWT.LEFT, SWT.CENTER, false, false); + gridDataLabel.horizontalIndent = indentSize; + gridDataLabel.verticalIndent = 0; + lblNanosec.setLayoutData(gridDataLabel); + + // Add all listener + addNeededListeners(); + } + + /* + * Create and add all listeners needed by our control.

+ */ + protected void addNeededListeners() { + + // AsyncCanvasRedrawer is an internal class + // This is used to redraw the canvas without danger from a different thread + asyncRedrawer = new AsyncTimeTextGroupRedrawer(this); + + txtNanosec.addFocusListener(this); + txtNanosec.addKeyListener(this); + } + + /** + * Getter for the layout data currently in use.

+ * + * @return the layout + */ + public Object getLayoutData() { + return grpName.getLayoutData(); + } + + /** + * Set a new layoutData for our control.

+ * + * @param layoutData the new layout data + */ + public void setLayoutData(Object layoutData) { + grpName.setLayoutData(layoutData); + } + + /** + * Get the control's parent.

+ * + * @return Currently used parent + */ + public Composite getParent() { + return grpName.getParent(); + } + + /** + * Set a new parent for the control.

+ * + * @return Currently used parent + */ + public void setParent(Composite newParent) { + grpName.setParent(newParent); + txtNanosec.setParent(newParent); + lblNanosec.setParent(newParent); + } + + /** + * Getter for the time value of the control.

+ * + * @return The nanoseconds time value + */ + public long getValue() { + return timeValue; + } + + /** + * Set a new String value to the control.

+ * Note : The String value will be converted in long before being applied; + * if any conversion error occur, 0 will be used.

+ * + * @param newTimeAsString The value to convert and set. + */ + public void setValue(String newTimeAsString) { + long timeAsLong = HistogramConstant.convertStringToNanoseconds(newTimeAsString); + setValue( timeAsLong ); + } + + /** + * Set a new value to the control.

+ * Note : The value will be formatted as nanosecond value, + * missing zero will be added if needed.

+ * + * @param newTime The value to set. + */ + public void setValue(long newTime) { + timeValue = newTime; + txtNanosec.setText( HistogramConstant.formatNanoSecondsTime(newTime) ); + } + + /** + * Set a new String value, asynchronously.

+ * This will call setValue(String) in async.Exec to avoid Thread Access problem to UI.

+ * + * @param newTimeAsString The value to convert and set. + */ + public void setValueAsynchronously(String newTimeAsString) { + long timeAsLong = HistogramConstant.convertStringToNanoseconds(newTimeAsString); + setValueAsynchronously( timeAsLong ); + } + + /** + * Set a new String value, asynchronously.

+ * This will call setValue(long) in async.Exec to avoid Thread Access problem to UI.

+ * + * @param newTimeAsString The value to set. + */ + public void setValueAsynchronously(long newTime) { + // Set the correct value ASAP + timeValue = newTime; + + // Create a new redrawer in case it doesn't exist yet (we never know with thread!) + if ( asyncRedrawer == null ) { + asyncRedrawer = new AsyncTimeTextGroupRedrawer(this); + } + + asyncRedrawer.asynchronousSetValue(newTime); + } + + /** + * Set a new group name (label) for this control.

+ * + * @param newName The new name to set. + */ + public void setGroupName(String newName) { + grpName.setText(newName); + } + + /** + * Set a new group name (label) for this control, asynchronously.

+ * This will call setValue(long) in async.Exec to avoid Thread Access problem to UI.

+ * + * @param newName The new name to set. + */ + public void setGroupNameAsynchronously(String newGroupName) { + // Create a new redrawer in case it doesn't exist yet (we never know with thread!) + if ( asyncRedrawer == null ) { + asyncRedrawer = new AsyncTimeTextGroupRedrawer(this); + } + + asyncRedrawer.asynchronousSetGroupName(newGroupName); + } + + + /** + * Method to call the "Asynchronous redrawer" for this time text group

+ * This allow safe redraw from different threads. + */ + public void redrawAsynchronously() { + // Create a new redrawer in case it doesn't exist yet (we never know with thread!) + if ( asyncRedrawer == null ) { + asyncRedrawer = new AsyncTimeTextGroupRedrawer(this); + } + + asyncRedrawer.asynchronousRedraw(); + } + + /** + * Redraw the control + */ + public void redraw () { + grpName.redraw(); + txtNanosec.redraw(); + lblNanosec.redraw(); + } + + /* + * This function is called when an user enter a new string in the control by hand.

+ * It will ensure the format of the String is valid. + */ + protected void handleNewStringValue() { + String valueInText = txtNanosec.getText(); + long valueAsLong = HistogramConstant.convertStringToNanoseconds(valueInText); + + if ( getValue() != valueAsLong ) { + setValue(valueAsLong); + // Notify our parent that the control was updated + notifyParentUpdatedTextGroupValue(); + } + } + + /** + * This function notify our parent HistogramView that our value changed. + */ + public void notifyParentUpdatedTextGroupValue() { + parentView.timeTextGroupChangeNotification(); + } + + /** + * Function that is called when the canvas get focus.

+ * + * Doesn't do anything yet... + * + * @param event The focus event generated. + */ + public void focusGained(FocusEvent event) { + // Nothing to do yet + } + + /** + * Function that is called when the canvas loose focus.

+ * It will validate that the String entered by the user (if any) is valid.

+ * + * @param event The focus event generated. + */ + public void focusLost(FocusEvent event) { + handleNewStringValue(); + } + + /** + * Function that is called when a key is pressed.

+ * Possible actions : + * - Enter (CR) : Validate the entered String.

+ * + * @param event The KeyEvent generated when the key was pressed. + */ + public void keyPressed(KeyEvent event) { + switch (event.keyCode) { + // SWT.CR is "ENTER" Key + case SWT.CR: + handleNewStringValue(); + break; + default: + break; + } + } + + /** + * Function that is called when a key is released.

+ * Possible actions : + * Nothing yet + * + * @param event The KeyEvent generated when the key was pressed. + */ + public void keyReleased(KeyEvent e) { + + } +} + +/** + * AsyncTimeTextGroupRedrawer Inner Class + *

+ * Asynchronous redrawer for the TimeTextGroup + *

+ * This class role is to call method that update the UI on asynchronously. + * This should prevent any "invalid thread access" exception when trying to update UI from a different thread. + */ +class AsyncTimeTextGroupRedrawer { + + private TimeTextGroup parentTimeTextGroup = null; + + /** + * AsyncTimeTextGroupRedrawer constructor. + * + * @param newParent Related time text group. + */ + public AsyncTimeTextGroupRedrawer(TimeTextGroup newParent) { + parentTimeTextGroup = newParent; + } + + /** + * Asynchronous SetValue for time text group. + * + * Basically, it just run "getParent().setValue(time)" in asyncExec. + * + * @param newTime The new time to set + */ + public void asynchronousSetValue(long newTime) { + final long tmpTime = newTime; + + Display display = parentTimeTextGroup.getParent().getDisplay(); + display.asyncExec(new Runnable() { + public void run() { + parentTimeTextGroup.setValue(tmpTime); + } + }); + } + + /** + * Asynchronous SetGroupName for time text group. + * + * Basically, it just run "getParent().setGroupName(name)" in asyncExec. + * + * @param newGroupName The new group name to set + */ + public void asynchronousSetGroupName(String newGroupName) { + final String tmpName = newGroupName; + + Display display = parentTimeTextGroup.getParent().getDisplay(); + display.asyncExec(new Runnable() { + public void run() { + parentTimeTextGroup.setGroupName(tmpName); + } + }); + } + + /** + * Function to redraw the related time text group asynchonously.

+ * + * Basically, it just run "getParent().redraw()" in asyncExec. + * + */ + public void asynchronousRedraw() { + Display display = parentTimeTextGroup.getParent().getDisplay(); + display.asyncExec(new Runnable() { + public void run() { + parentTimeTextGroup.getParent().redraw(); + } + }); + } +} \ No newline at end of file diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/LTTngProjectNature.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/LTTngProjectNature.java new file mode 100644 index 0000000000..2e14ccd1bc --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/LTTngProjectNature.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectNature; +import org.eclipse.core.runtime.CoreException; + +/** + * LTTngProjectNature + *

+ * This is really a marker for the LTTng projects. + */ +public class LTTngProjectNature implements IProjectNature { + + public static final String ID = "org.eclipse.linuxtools.lttng.ui.views.project.LTTngProjectNature"; + + private IProject fProject; + + /* (non-Javadoc) + * @see org.eclipse.core.resources.IProjectNature#configure() + */ + public void configure() throws CoreException { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see org.eclipse.core.resources.IProjectNature#deconfigure() + */ + public void deconfigure() throws CoreException { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see org.eclipse.core.resources.IProjectNature#getProject() + */ + public IProject getProject() { + return fProject; + } + + /* (non-Javadoc) + * @see org.eclipse.core.resources.IProjectNature#setProject(org.eclipse.core.resources.IProject) + */ + public void setProject(IProject project) { + fProject = project; + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/ProjectView.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/ProjectView.java new file mode 100644 index 0000000000..c76654f77e --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/ProjectView.java @@ -0,0 +1,211 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project; + +import java.io.FileNotFoundException; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceChangeEvent; +import org.eclipse.core.resources.IResourceChangeListener; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.ViewerSorter; +import org.eclipse.linuxtools.lttng.event.LttngEvent; +import org.eclipse.linuxtools.lttng.state.experiment.StateManagerFactory; +import org.eclipse.linuxtools.lttng.trace.LTTngTrace; +import org.eclipse.linuxtools.lttng.ui.views.project.model.ILTTngProjectTreeNode; +import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngExperimentNode; +import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngProjectContentProvider; +import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngProjectLabelProvider; +import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngProjectRoot; +import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngTraceNode; +import org.eclipse.linuxtools.tmf.experiment.TmfExperiment; +import org.eclipse.linuxtools.tmf.signal.TmfExperimentSelectedSignal; +import org.eclipse.linuxtools.tmf.trace.ITmfTrace; +import org.eclipse.linuxtools.tmf.ui.views.TmfView; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.MouseAdapter; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.Tree; + +/** + * ProjectView + *

+ * The ProjectView keeps track of the LTTng projects in the workspace. + */ +public class ProjectView extends TmfView { + + public static final String ID = "org.eclipse.linuxtools.lttng.ui.views.project"; + + // ------------------------------------------------------------------------ + // Main data structures + // ------------------------------------------------------------------------ + + private TreeViewer fViewer; + private LTTngProjectRoot fProjectRoot; + private TmfExperiment fSelectedExperiment = null; + + private IWorkspace fWorkspace; + private IResourceChangeListener fResourceChangeListener; + + // ------------------------------------------------------------------------ + // View refresher + // ------------------------------------------------------------------------ + + // Perform updates on the UI thread + private Runnable fViewRefresher = new Runnable() { + public void run() { + if (fViewer != null) { + Object[] elements = fViewer.getExpandedElements(); + fViewer.refresh(); + fViewer.setExpandedElements(elements); + } + } + }; + + public LTTngProjectRoot getRoot() { + return fProjectRoot; + } + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + + public ProjectView() { + + super("ProjectView"); + fProjectRoot = new LTTngProjectRoot(this); + + fWorkspace = ResourcesPlugin.getWorkspace(); + fResourceChangeListener = new IResourceChangeListener() { + public void resourceChanged(IResourceChangeEvent event) { + if (event.getType() == IResourceChangeEvent.POST_CHANGE) { + fProjectRoot.refreshChildren(); + refresh(); + } + } + }; + fWorkspace.addResourceChangeListener(fResourceChangeListener); + } + + public void refresh() { + Tree tree = fViewer.getTree(); + if (tree != null && !tree.isDisposed()) + tree.getDisplay().asyncExec(fViewRefresher); + } + + public void setSelection(ILTTngProjectTreeNode node) { + fViewer.setSelection(new StructuredSelection(node), true); + } + + @Override + public void dispose() { + fWorkspace.removeResourceChangeListener(fResourceChangeListener); + } + + @Override + public void createPartControl(Composite parent) { + + fViewer = new TreeViewer(parent, SWT.SINGLE); + fViewer.setContentProvider(new LTTngProjectContentProvider()); + fViewer.setSorter(new ViewerSorter()); + fViewer.setLabelProvider(new LTTngProjectLabelProvider()); + fViewer.setInput(fProjectRoot); + + getSite().setSelectionProvider(fViewer); + hookMouse(); + + createContextMenu(); + } + + // ------------------------------------------------------------------------ + // ViewPart + // ------------------------------------------------------------------------ + + @Override + public String toString() { + return "[ProjectView]"; + } + + // ------------------------------------------------------------------------ + // hookMouse + // ------------------------------------------------------------------------ + + private void hookMouse() { + fViewer.getTree().addMouseListener(new MouseAdapter() { + @Override + public void mouseDoubleClick(MouseEvent event) { + TreeSelection selection = (TreeSelection) fViewer.getSelection(); + Object element = selection.getFirstElement(); + if (element instanceof LTTngExperimentNode) { + LTTngExperimentNode experiment = (LTTngExperimentNode) element; + selectExperiment(experiment); + } + } + }); + } + + private boolean waitForCompletion = true; + + /** + * @param experiment + */ + public void selectExperiment(LTTngExperimentNode experiment) { + String expId = experiment.getName(); + if (fSelectedExperiment != null) + fSelectedExperiment.dispose(); + try { + LTTngTraceNode[] traceEntries = experiment.getTraces(); + int nbTraces = traceEntries.length; + ITmfTrace[] traces = new ITmfTrace[nbTraces]; + for (int i = 0; i < nbTraces; i++) { + IResource res = traceEntries[i].getFolder(); + String location = res.getLocation().toOSString(); + ITmfTrace trace = new LTTngTrace(location, waitForCompletion); + traces[i] = trace; + } + fSelectedExperiment = new TmfExperiment(LttngEvent.class, expId, traces); + fSelectedExperiment.indexExperiment(waitForCompletion); + // Make sure the lttng-core, experiment selection context is ready + // for an event request from any view + StateManagerFactory.getExperimentManager().experimentSelected_prep( + (TmfExperiment) fSelectedExperiment); + + broadcast(new TmfExperimentSelectedSignal(this, fSelectedExperiment)); + } catch (FileNotFoundException e) { + return; + } catch (Exception e) { + e.printStackTrace(); + } + } + + // ------------------------------------------------------------------------ + // createContextMenu + // ------------------------------------------------------------------------ + + // Populated from the plug-in + private void createContextMenu() { + MenuManager menuManager = new MenuManager("#PopupMenu"); + menuManager.setRemoveAllWhenShown(true); + Menu menu = menuManager.createContextMenu(fViewer.getControl()); + fViewer.getControl().setMenu(menu); + getSite().registerContextMenu(menuManager, fViewer); + } + +} \ No newline at end of file diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/AddTraceWizard.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/AddTraceWizard.java new file mode 100644 index 0000000000..eac20e8704 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/AddTraceWizard.java @@ -0,0 +1,94 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.dialogs; + +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngExperimentNode; +import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngProjectNode; +import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngTraceNode; +import org.eclipse.ui.IImportWizard; +import org.eclipse.ui.IWorkbench; + +/** + * AddTraceWizard + *

+ * TODO: Implement me. Please. + */ +public class AddTraceWizard extends Wizard implements IImportWizard { + + private LTTngProjectNode fProject; + private LTTngExperimentNode fExperiment; + private AddTraceWizardPage fMainPage; + + /** + * @param project + */ + public AddTraceWizard(LTTngProjectNode project, LTTngExperimentNode experiment) { + fProject = project; + fExperiment = experiment; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IWorkbenchWizard#init(org.eclipse.ui.IWorkbench, org.eclipse.jface.viewers.IStructuredSelection) + */ + public void init(IWorkbench workbench, IStructuredSelection selection) { + setWindowTitle("Adding traces to experiment"); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.wizard.Wizard#addPages() + */ + @Override + public void addPages() { + super.addPages(); + fMainPage = new AddTraceWizardPage(fProject, "Some string"); + addPage(fMainPage); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.wizard.Wizard#performFinish() + */ + @Override + public boolean performFinish() { + + IWorkspace workspace = ResourcesPlugin.getWorkspace(); + IFolder experimentFolder = fExperiment.getFolder(); + + LTTngTraceNode[] traces = fMainPage.getSelection(); + for (LTTngTraceNode trace : traces) { + try { + IFolder folder = experimentFolder.getFolder(trace.getName()); + IPath location = trace.getFolder().getLocation(); + if (workspace.validateLinkLocation(folder, location).isOK()) { + folder.createLink(location, IResource.REPLACE, null); + fExperiment.addTrace(folder); + } + else { + System.out.println("Problem"); + } + } catch (CoreException e) { + e.printStackTrace(); + } + } + + return true; + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/AddTraceWizardPage.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/AddTraceWizardPage.java new file mode 100644 index 0000000000..ded48a0279 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/AddTraceWizardPage.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.dialogs; + +import java.util.Vector; + +import org.eclipse.jface.viewers.CheckboxTableViewer; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngProjectNode; +import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngTraceNode; +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.Table; +import org.eclipse.swt.widgets.TableColumn; + +/** + * AddTraceWizardPage + *

+ * TODO: Implement me. Please. + */ +public class AddTraceWizardPage extends WizardPage { + + private LTTngProjectNode fProject; + private CheckboxTableViewer fCheckboxTableViewer; + + protected AddTraceWizardPage(LTTngProjectNode project, String pageName) { + super(pageName); + setTitle("Select traces"); + setDescription("Select the traces to add to the experiment"); + fProject = project; + } + + public void createControl(Composite parent) { + Composite container = new Composite(parent, SWT.NULL); + container.setLayout(new FormLayout()); + setControl(container); + + fCheckboxTableViewer = CheckboxTableViewer.newCheckList(container, SWT.BORDER); + fCheckboxTableViewer.setContentProvider(new DialogTraceContentProvider()); + fCheckboxTableViewer.setLabelProvider(new DialogTraceLabelProvider()); + + final Table table = fCheckboxTableViewer.getTable(); + final FormData formData = new FormData(); + formData.bottom = new FormAttachment(100, 0); + formData.right = new FormAttachment(100, 0); + formData.top = new FormAttachment(0, 0); + formData.left = new FormAttachment(0, 0); + table.setLayoutData(formData); + table.setHeaderVisible(true); + + final TableColumn tableColumn = new TableColumn(table, SWT.NONE); + tableColumn.setWidth(200); + tableColumn.setText("Trace"); + + fCheckboxTableViewer.setInput(fProject.getTracesFolder()); + } + + public LTTngTraceNode[] getSelection() { + Vector traces = new Vector(); + Object[] selection = fCheckboxTableViewer.getCheckedElements(); + for (Object sel : selection) { + if (sel instanceof LTTngTraceNode) + traces.add((LTTngTraceNode) sel); + } + LTTngTraceNode[] result = new LTTngTraceNode[traces.size()]; + traces.toArray(result); + return result; + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/DialogTraceContentProvider.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/DialogTraceContentProvider.java new file mode 100644 index 0000000000..d3efae9762 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/DialogTraceContentProvider.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.dialogs; + +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngTraceFolderNode; + +/** + * LTTngTracesContentProvider + *

+ * TODO: Implement me. Please. + */ +public class DialogTraceContentProvider implements IStructuredContentProvider { + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object) + */ + public Object[] getElements(Object inputElement) { + if (inputElement instanceof LTTngTraceFolderNode) { + LTTngTraceFolderNode folder = (LTTngTraceFolderNode) inputElement; + return folder.getTraces(); + } + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.IContentProvider#dispose() + */ + public void dispose() { + // TODO Auto-generated method stub + } + + /* (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) { + // TODO Auto-generated method stub + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/DialogTraceLabelProvider.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/DialogTraceLabelProvider.java new file mode 100644 index 0000000000..d3ff08b2bd --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/DialogTraceLabelProvider.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.dialogs; + +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngTraceNode; +import org.eclipse.swt.graphics.Image; + +/** + * LTTngTracesLabelProvider + *

+ * TODO: Implement me. Please. + */ +public class DialogTraceLabelProvider extends LabelProvider implements ITableLabelProvider { + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int) + */ + public Image getColumnImage(Object element, int columnIndex) { + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int) + */ + public String getColumnText(Object element, int columnIndex) { + if (element instanceof LTTngTraceNode) { + LTTngTraceNode entry = (LTTngTraceNode) element; + switch (columnIndex) { + case 0: + return entry.getName(); + default: + return null; + } + } + return null; + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/ImportTraceWizard.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/ImportTraceWizard.java new file mode 100644 index 0000000000..77dd476c0a --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/ImportTraceWizard.java @@ -0,0 +1,117 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.dialogs; + +import java.util.List; + +import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.ui.IImportWizard; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.ide.IDE; +import org.eclipse.ui.internal.WorkbenchPlugin; +import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin; +import org.eclipse.ui.internal.wizards.datatransfer.DataTransferMessages; + +/** + * ImportTraceWizard + *

+ * + * TODO: Implement me. Please. + */ +@SuppressWarnings("restriction") +public class ImportTraceWizard extends Wizard implements IImportWizard { + + private IWorkbench fWorkbench; + private IStructuredSelection fSelection; + private ImportTraceWizardPage fMainPage; + + /** + * + */ + public ImportTraceWizard() { + IDialogSettings workbenchSettings = WorkbenchPlugin.getDefault().getDialogSettings(); + IDialogSettings section = workbenchSettings.getSection("LTTngTraceImportWizard"); + if (section == null) { + section = workbenchSettings.addNewSection("LTTngTraceImportWizard"); + } + + setDialogSettings(section); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.wizard.Wizard#addPages() + */ + @Override + public void addPages() { + super.addPages(); + fMainPage = new ImportTraceWizardPage(fWorkbench, fSelection); + addPage(fMainPage); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IWorkbenchWizard#init(org.eclipse.ui.IWorkbench, org.eclipse.jface.viewers.IStructuredSelection) + */ + @SuppressWarnings("rawtypes") + public void init(IWorkbench workbench, IStructuredSelection selection) { + fWorkbench = workbench; + fSelection = selection; + + List selectedResources = IDE.computeSelectedResources(selection); + if (!selectedResources.isEmpty()) { + fSelection = new StructuredSelection(selectedResources); + } + + setWindowTitle(DataTransferMessages.DataTransfer_importTitle); + setDefaultPageImageDescriptor(IDEWorkbenchPlugin.getIDEImageDescriptor("wizban/importdir_wiz.png")); + setNeedsProgressMonitor(true); + } + + public ImportTraceWizardPage getMainPage() { + return fMainPage; + } + + /** + * performFinish is called after the "finish" button is pressed in the import wizard + * If we return "false", the wizard will not close. + * + * We perform here version check on the imported LTTng trace + * + */ + @Override + public boolean performFinish() { + + if ( fMainPage.getDestination().equals( fMainPage.getInitialContainerString() ) ) { + + String errMessage[] = { "Error : import destination is wrong." }; + errMessage = fMainPage.extendErrorMessage(errMessage, ""); + errMessage = fMainPage.extendErrorMessage(errMessage, "You cannot import your trace directly into the \"" + fMainPage.getInitialContainerString() + "\""); + errMessage = fMainPage.extendErrorMessage(errMessage, "The trace has to be into a subdirectly, like \"" + fMainPage.getInitialContainerString() + "/MyTrace\"" ); + errMessage = fMainPage.extendErrorMessage(errMessage, ""); + errMessage = fMainPage.extendErrorMessage(errMessage, "Please change the destination folder."); + fMainPage.showVersionErrorPopup(errMessage); + + return false; + } + + return fMainPage.finish(); + } + + @Override + public boolean canFinish() { + return fMainPage.isSelectedElementsValidLttngTraces(); + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/ImportTraceWizardPage.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/ImportTraceWizardPage.java new file mode 100644 index 0000000000..5c8e041633 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/ImportTraceWizardPage.java @@ -0,0 +1,342 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.dialogs; + +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.linuxtools.lttng.LttngException; +import org.eclipse.linuxtools.lttng.trace.LTTngTraceVersion; +import org.eclipse.linuxtools.lttng.ui.views.project.handlers.TraceErrorHandler; +import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngProjectNode; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.internal.wizards.datatransfer.WizardFileSystemResourceImportPage1; + +/** + * ImportTraceWizardPage + *

+ * TODO: Implement me. Please. + */ +@SuppressWarnings("restriction") +public class ImportTraceWizardPage extends WizardFileSystemResourceImportPage1 { + + private boolean isContainerSet = false; + private String initialContainerString = ""; + private String selectedSourceDirectory = ""; + + public ImportTraceWizardPage(IWorkbench workbench, IStructuredSelection selection) { + super(workbench, selection); + + LTTngProjectNode folder = (LTTngProjectNode) selection.getFirstElement(); + String path = folder.getTracesFolder().getFolder().getFullPath().toOSString(); + + initialContainerString = path; + setContainerFieldValue(path); + } + + + public String getTraceDirectory() { + String tmpPath = ""; + if ( (getSourceDirectory() != null) && (getSourceDirectory().getName() != null) ) { + tmpPath = this.getSourceDirectory().getName().toString(); + } + + return tmpPath; + } + + public String getInitialContainerString() { + return initialContainerString; + } + + public String getTracepath() { + String tmpPath = ""; + if ( (getSourceDirectory() != null) && (getSourceDirectory().getPath() != null) ) { + tmpPath = this.getSourceDirectory().getPath().toString(); + } + + return tmpPath; + } + + public String getDestination() { + String returnPath = null; + + if ( getContainerFullPath() != null ) { + returnPath = getContainerFullPath().toString(); + } + return returnPath; + } + + public boolean isSelectedElementsValidLttngTraces() { + boolean returnedValue = true; + + // We don't want to test until something is selected + if ( selectionGroup.getCheckedElementCount() > 0 ) { + + // We don't want to revalidate each time, only want a new directory is selected + if ( ! selectedSourceDirectory.equals(getSourceDirectory().getAbsolutePath().toString()) ) + { + try { + if ( isPathLttngTrace( getSourceDirectory().getAbsolutePath() ) == false ) { + returnedValue = false; + selectedSourceDirectory = ""; + + String errMessage[] = { "Couldn't get LTTng version number for the path : " }; + errMessage = extendErrorMessage(errMessage, getSourceDirectory().getAbsolutePath() ); + errMessage = extendErrorMessage(errMessage, ""); + errMessage = extendErrorMessage(errMessage, "Verify that the directory is a valid LTTng trace directory."); + errMessage = extendErrorMessage(errMessage, "Make sure the top directory is the trace itself and not any of its parent."); + showVersionErrorPopup(errMessage); + selectionGroup.setAllSelections(false); + } + else { + selectedSourceDirectory = getSourceDirectory().getAbsolutePath(); + + if ( isContainerSet == false ) { + isContainerSet = true; + + if ( ! getDestination().toString().equals( getInitialContainerString() + "/" + getTraceDirectory() ) ) { + // *** HACK *** + // Force a sane destination to avoid imported files to end up in the root of the "Traces/" directory + setContainerFieldValue(getInitialContainerString() + "/" + getTraceDirectory()); + } + } + } + } + catch (LttngException e) { + String[] errorMessages = e.toString().split("\n"); + String exceptionMessage[] = { "Version check failed for the path : ", this.getTracepath(), "", "Returned error was :" }; + + for ( int pos=0; pos 0) { +// // Call import ressources (code is below) +// return importResources(listRealFiles); +// } +// +// MessageDialog.openInformation(getContainer().getShell(), +// DataTransferMessages.DataTransfer_information, +// DataTransferMessages.FileImport_noneSelected); +// return false; +// } +// +// @Override +// protected boolean importResources(List fileSystemObjects) { +// // *** Explanation of the hackssss +// // We want the import wizard to import everything in the form of : +// // trace1/ -> tracefiles* +// // +// // However, the wizard is too dumb to do the following and will recreate the full architecture the user selected. +// // So, depending what the user select, we could end up with something like : +// // home/user/somewhere/trace1/ -> tracefiles* +// // +// // Since there is nothing to do with that, we need to change the "source" and the "to-import files" to reflect this. +// // Basically, from the case above, the "source" should be changed to "trace1/" and "to-import files" +// // should have the correct parent so the wizard can still find them +// // +// // Let's see how fun it is to do with mr. import wizard. +// +// +// List listRealFilesShortPath = new ArrayList(); +// java.io.File newFullSource = getSourceDirectory(); +// +// // We will loop for every "to-import full path files" we have and recreate "short path" files +// // Mean, the current path of the file is currently something like : +// // Path : /home/billybob/mytraces/trace1/metadata_0 Parent : null +// // And we want something less dumb like : +// // Path : metadata_0 Parent : /home/billybob/mytraces/trace1/ +// for (int pos=0; pos /home/billybob/mytraces/trace1/ +// String newParent = oldFile.getAbsolutePath().substring(0, oldFile.getAbsolutePath().lastIndexOf("/") ); +// +// // Create a "short path file" with the good parent from it. This give : +// // (Files) Path : metadata_0 Parent : /home/billybob/mytraces/trace1/ +// newShortPathFile = new java.io.File(newParent, oldFile.getName() ); +// +// // Create a new "full source" directory -> /home/billybob/mytraces/trace1/ +// newFullSource = new java.io.File( newParent ); +// +// // Add our pretty file to the new List +// listRealFilesShortPath.add(newShortPathFile); +// } +// +// // *** +// // HACK #3 +// // Now that we have everything, we need to AJUST THE DESTINATION +// // To do so, we ajust the "ContainerValue" text field. +// // +// // Right now we have something like : +// // Path -> /where/to/import/ +// // (Files) Path : metadata_0 Parent : /home/billybob/mytraces/trace1/ +// // We want something like : +// // Path -> /where/to/import/trace1/ +// // (Files) Path : metadata_0 Parent : /home/billybob/mytraces/trace1/ +// // +// +// // We take the current text field and we add the "full source" name +// // Note : the "name" is the last directory name so "trace1" is returned for a path like "/home/billybob/mytraces/trace1/" +// setContainerFieldValue(getContainerFullPath() + "/" + newFullSource.getName()); +// +// /* +// System.out.println("\n\n" + getContainerFullPath()); +// System.out.println(newFullSource); +// System.out.println(FileSystemStructureProvider.INSTANCE); +// System.out.println(this.getContainer()); +// System.out.println(fileSystemObjects); +// */ +// +// // Finally import !! +// ImportOperation operation = new ImportOperation(getContainerFullPath(), newFullSource, FileSystemStructureProvider.INSTANCE, this, listRealFilesShortPath); +// +// operation.setContext(getShell()); +// return executeImportOperation(operation); +// } +// +// // This function test if the selected directory are LTTng traces +// // This one is made to work with the madness above. +// public boolean isSelectedElementsValidLttngTraces() { +// boolean returnedValue = true; +// +// String errMessage[] = { "Couldn't get LTTng version number for the path : " }; +// +// // We don't want to test until something is selected +// if ( selectionGroup.getCheckedElementCount() > 0 ) { +// try { +// List selectionList = selectionGroup.getAllWhiteCheckedItems(); +// MinimizedFileSystemElement tmpSelectedElement = null; +// +// for ( int x=0; xNewProjectMainWizardPage + *

+ * + * TODO: Implement me. Please. + */ +public class NewProjectMainWizardPage extends WizardNewProjectCreationPage { + + /** + * @param pageName + */ + public NewProjectMainWizardPage(String pageName) { + super(pageName); + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/NewProjectWizard.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/NewProjectWizard.java new file mode 100644 index 0000000000..e0bd8a303c --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/NewProjectWizard.java @@ -0,0 +1,147 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.dialogs; + +import java.net.URI; + +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; +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.IConfigurationElement; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.linuxtools.lttng.ui.LTTngUiPlugin; +import org.eclipse.linuxtools.lttng.ui.views.project.LTTngProjectNature; +import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngProjectNode; +import org.eclipse.ui.wizards.newresource.BasicNewResourceWizard; + +/** + * NewProjectWizard + *

+ * TODO: Implement me. Please. + */ +public class NewProjectWizard extends BasicNewResourceWizard { + + private String fTtitle; + private String fDescription; + + protected NewProjectMainWizardPage fMainPage; + protected String fProjectName; + protected URI fProjectLocation; + protected IConfigurationElement fConfigElement; + + protected IProject fProject; + + /** + * + */ + public NewProjectWizard() { + this("LTTng Project", "Create an LTTng Project"); + } + + /** + * @param title + * @param desc + */ + public NewProjectWizard(String title, String desc) { + super(); + setDialogSettings(LTTngUiPlugin.getDefault().getDialogSettings()); + setNeedsProgressMonitor(true); + setForcePreviousAndNextButtons(true); + setWindowTitle(title); + fTtitle = title; + fDescription = desc; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.wizard.Wizard#addPages() + */ + @Override + public void addPages() { + fMainPage= new NewProjectMainWizardPage("LTTng Project"); + fMainPage.setTitle(fTtitle); + fMainPage.setDescription(fDescription); + addPage(fMainPage); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.wizard.Wizard#performCancel() + */ + @Override + public boolean performCancel() { + return true; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.wizard.Wizard#performFinish() + */ + @Override + public boolean performFinish() { + fProjectName = fMainPage.getProjectName(); + fProjectLocation = fMainPage.useDefaults() ? null : fMainPage.getLocationURI(); + fProject = createProject(fProjectName, fProjectLocation, new NullProgressMonitor()); + return true; + } + + public IProject getProject() { + return fProject; + } + + /** + * @param projectName + * @param projectLocation + * @param monitor + * @return + */ + private IProject createProject(String projectName, URI projectLocation, IProgressMonitor monitor) { + + IWorkspace workspace = ResourcesPlugin.getWorkspace(); + IWorkspaceRoot root = workspace.getRoot(); + IProject project = root.getProject(projectName); + + try { + if (!project.exists()) { + IProjectDescription description = workspace.newProjectDescription(project.getName()); + if (projectLocation != null) + description.setLocationURI(projectLocation); + project.create(description, monitor); + } + + if (!project.isOpen()) + project.open(monitor); + + IProjectDescription description = project.getDescription(); + description.setNatureIds(new String[] { LTTngProjectNature.ID } ); + project.setDescription(description, null); + + IFolder folder = project.getFolder(LTTngProjectNode.TRACE_FOLDER_NAME); + if (!folder.exists()) + folder.create(true, true, null); + + folder = project.getFolder(LTTngProjectNode.EXPER_FOLDER_NAME); + if (!folder.exists()) + folder.create(true, true, null); + + return project; + } + catch (CoreException e) { + e.printStackTrace(); + } + return null; + } + +} \ No newline at end of file diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/TraceErrorDialog.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/TraceErrorDialog.java new file mode 100644 index 0000000000..06bbcc2930 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/dialogs/TraceErrorDialog.java @@ -0,0 +1,135 @@ +package org.eclipse.linuxtools.lttng.ui.views.project.dialogs; + +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * William Bourque - Initial API and implementation + *******************************************************************************/ + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.GC; +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.ui.dialogs.SelectionStatusDialog; + +public class TraceErrorDialog extends SelectionStatusDialog { + + private String[] messages = null; + + public TraceErrorDialog(Shell parentShell, String[] newMessages) { + super(parentShell); + + messages = newMessages; + setTitle("Trace Selection"); + setStatusLineAboveButtons(true); + } + + @Override + protected void computeResult() { + } + + @Override + public void create() { + super.create(); + getButton(IDialogConstants.OK_ID).setEnabled(true); + getButton(IDialogConstants.OK_ID).setAlignment(GridData.CENTER); + getButton(IDialogConstants.CANCEL_ID).setVisible(false); + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite) super.createDialogArea(parent); + composite.setLayout(new GridLayout()); + composite.setLayoutData(new GridData(GridData.FILL_BOTH)); + + createFolderNameGroup(composite); + return composite; + } + + private void createFolderNameGroup(Composite parent) { + Font font = parent.getFont(); + Composite folderGroup = new Composite(parent, SWT.NONE); + + GridLayout layout = new GridLayout(); + layout.numColumns = 1; + layout.verticalSpacing = 3; + folderGroup.setLayout(layout); + folderGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + + // Position grid for the messages + GridData positionningData = new GridData(GridData.FILL_VERTICAL); + + // New message label + Label lblMessage = new Label(folderGroup, SWT.NONE); + lblMessage.setFont(font); + lblMessage.setText("Error while opening the trace! Error message was : "); + lblMessage.setLayoutData(positionningData); + + // The actual messages + GC graphicContext = new GC(parent); + String longuestLine = ""; + int msgSize = 0; + + // *** Font and FontData are nowhere near elegant to use. + Font errorFont = new Font(graphicContext.getDevice(), font.getFontData()[0].getName(), font.getFontData()[0].getHeight(), SWT.ITALIC); + + Label[] lblErrorMessages = new Label[messages.length]; + for(int x=0; x longuestLine.length() ) { + longuestLine = messages[x]; + } + } + + for ( int pos=0; posCloseProjectHandler + *

+ * TODO: Implement me. Please. + */ +public class CloseProjectHandler implements IHandler { + + private LTTngProjectNode fProject = null; + + // ------------------------------------------------------------------------ + // Validation + // ------------------------------------------------------------------------ + + public boolean isEnabled() { + + // Check if we are closing down + IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + if (window == null) + return false; + + // Check if we are in the Project View + IWorkbenchPage page = window.getActivePage(); + if (!(page.getActivePart() instanceof ProjectView)) + return false; + + // Check if a project is selected + ISelection selection = page.getSelection(ProjectView.ID); + if (selection instanceof StructuredSelection) { + Object element = ((StructuredSelection) selection).getFirstElement(); + fProject = (element instanceof LTTngProjectNode) ? (LTTngProjectNode) element : null; + } + return (fProject != null && fProject.isOpen()); + } + + // Handled if we are in the ProjectView + public boolean isHandled() { + return true; + } + + // ------------------------------------------------------------------------ + // Execution + // ------------------------------------------------------------------------ + + public Object execute(ExecutionEvent event) throws ExecutionException { + + if (fProject != null) { + fProject.closeProject(); + fProject.refresh(); + } + return null; + } + + public void dispose() { + // TODO Auto-generated method stub + } + + // ------------------------------------------------------------------------ + // IHandlerListener + // ------------------------------------------------------------------------ + + public void addHandlerListener(IHandlerListener handlerListener) { + // TODO Auto-generated method stub + } + + public void removeHandlerListener(IHandlerListener handlerListener) { + // TODO Auto-generated method stub + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/DeleteExperimentHandler.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/DeleteExperimentHandler.java new file mode 100644 index 0000000000..ed736efa07 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/DeleteExperimentHandler.java @@ -0,0 +1,105 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.handlers; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.IHandler; +import org.eclipse.core.commands.IHandlerListener; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.linuxtools.lttng.ui.views.project.ProjectView; +import org.eclipse.linuxtools.lttng.ui.views.project.model.ILTTngProjectTreeNode; +import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngExperimentNode; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; + +/** + * DeleteExperimentHandler + *

+ * TODO: Implement me. Please. + */ +public class DeleteExperimentHandler implements IHandler { + + private LTTngExperimentNode fExperiment = null; + + // ------------------------------------------------------------------------ + // Validation + // ------------------------------------------------------------------------ + + public boolean isEnabled() { + + // Check if we are closing down + IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + if (window == null) + return false; + + // Check if a trace is selected + IWorkbenchPage page = window.getActivePage(); + if (!(page.getActivePart() instanceof ProjectView)) + return false; + + // Check if a trace is selected + ISelection selection = page.getSelection(ProjectView.ID); + if (selection instanceof StructuredSelection) { + Object element = ((StructuredSelection) selection).getFirstElement(); + fExperiment = (element instanceof LTTngExperimentNode) ? (LTTngExperimentNode) element : null; + } + + return (fExperiment != null); + } + + // Handled if we are in the ProjectView + public boolean isHandled() { + return true; + } + + // ------------------------------------------------------------------------ + // Execution + // ------------------------------------------------------------------------ + + public Object execute(ExecutionEvent event) throws ExecutionException { + + IFolder folder = fExperiment.getFolder(); + ILTTngProjectTreeNode parent = fExperiment.getParent(); + try { + parent.removeChild(fExperiment); + parent.refresh(); + folder.delete(true, true, null); + } catch (CoreException e) { + e.printStackTrace(); + } + + return null; + } + + public void dispose() { + // TODO Auto-generated method stub + } + + // ------------------------------------------------------------------------ + // IHandlerListener + // ------------------------------------------------------------------------ + + public void addHandlerListener(IHandlerListener handlerListener) { + // TODO Auto-generated method stub + } + + public void removeHandlerListener(IHandlerListener handlerListener) { + // TODO Auto-generated method stub + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/DeleteProjectHandler.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/DeleteProjectHandler.java new file mode 100644 index 0000000000..328dd97276 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/DeleteProjectHandler.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.handlers; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.IHandler; +import org.eclipse.core.commands.IHandlerListener; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.linuxtools.lttng.ui.views.project.ProjectView; +import org.eclipse.linuxtools.lttng.ui.views.project.model.ILTTngProjectTreeNode; +import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngProjectNode; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; + +/** + * DeleteProjectHandler + *

+ * TODO: Implement me. Please. + */ +public class DeleteProjectHandler implements IHandler { + + private LTTngProjectNode fProject = null; + + // ------------------------------------------------------------------------ + // Validation + // ------------------------------------------------------------------------ + + public boolean isEnabled() { + + // Check if we are closing down + IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + if (window == null) + return false; + + // Check if we are in the Project View + IWorkbenchPage page = window.getActivePage(); + if (!(page.getActivePart() instanceof ProjectView)) + return false; + + // Check if a project is selected + ISelection selection = page.getSelection(ProjectView.ID); + if (selection instanceof StructuredSelection) { + Object element = ((StructuredSelection) selection).getFirstElement(); + fProject = (element instanceof LTTngProjectNode) ? (LTTngProjectNode) element : null; + } + return (fProject != null); + } + + // Handled if we are in the ProjectView + public boolean isHandled() { + return true; + } + + // ------------------------------------------------------------------------ + // Execution + // ------------------------------------------------------------------------ + + public Object execute(ExecutionEvent event) throws ExecutionException { + + IProject project = fProject.getProject(); + ILTTngProjectTreeNode parent = fProject.getParent(); + try { + parent.removeChild(fProject); + parent.refresh(); + project.delete(true, true, null); + } catch (CoreException e) { + e.printStackTrace(); + } + + return null; + } + + public void dispose() { + // TODO Auto-generated method stub + } + + // ------------------------------------------------------------------------ + // IHandlerListener + // ------------------------------------------------------------------------ + + public void addHandlerListener(IHandlerListener handlerListener) { + // TODO Auto-generated method stub + } + + public void removeHandlerListener(IHandlerListener handlerListener) { + // TODO Auto-generated method stub + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/DeleteTraceHandler.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/DeleteTraceHandler.java new file mode 100644 index 0000000000..beb0d0595b --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/DeleteTraceHandler.java @@ -0,0 +1,105 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.handlers; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.IHandler; +import org.eclipse.core.commands.IHandlerListener; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.linuxtools.lttng.ui.views.project.ProjectView; +import org.eclipse.linuxtools.lttng.ui.views.project.model.ILTTngProjectTreeNode; +import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngTraceNode; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; + +/** + * DeleteTraceHandler + *

+ * TODO: Implement me. Please. + */ +public class DeleteTraceHandler implements IHandler { + + private LTTngTraceNode fTrace = null; + + // ------------------------------------------------------------------------ + // Validation + // ------------------------------------------------------------------------ + + public boolean isEnabled() { + + // Check if we are closing down + IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + if (window == null) + return false; + + // Check if a trace is selected + IWorkbenchPage page = window.getActivePage(); + if (!(page.getActivePart() instanceof ProjectView)) + return false; + + // Check if a trace is selected + ISelection selection = page.getSelection(ProjectView.ID); + if (selection instanceof StructuredSelection) { + Object element = ((StructuredSelection) selection).getFirstElement(); + fTrace = (element instanceof LTTngTraceNode) ? (LTTngTraceNode) element : null; + } + + return (fTrace != null); + } + + // Handled if we are in the ProjectView + public boolean isHandled() { + return true; + } + + // ------------------------------------------------------------------------ + // Execution + // ------------------------------------------------------------------------ + + public Object execute(ExecutionEvent event) throws ExecutionException { + + IFolder folder = fTrace.getFolder(); + ILTTngProjectTreeNode parent = fTrace.getParent(); + try { + parent.removeChild(fTrace); + parent.refresh(); + folder.delete(true, true, null); + } catch (CoreException e) { + e.printStackTrace(); + } + + return null; + } + + public void dispose() { + // TODO Auto-generated method stub + } + + // ------------------------------------------------------------------------ + // IHandlerListener + // ------------------------------------------------------------------------ + + public void addHandlerListener(IHandlerListener handlerListener) { + // TODO Auto-generated method stub + } + + public void removeHandlerListener(IHandlerListener handlerListener) { + // TODO Auto-generated method stub + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/ImportTraceHandler.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/ImportTraceHandler.java new file mode 100644 index 0000000000..907c428c07 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/ImportTraceHandler.java @@ -0,0 +1,123 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.handlers; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.IHandler; +import org.eclipse.core.commands.IHandlerListener; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.window.Window; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.linuxtools.lttng.ui.views.project.ProjectView; +import org.eclipse.linuxtools.lttng.ui.views.project.dialogs.ImportTraceWizard; +import org.eclipse.linuxtools.lttng.ui.views.project.model.ILTTngProjectTreeNode; +import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngProjectNode; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; + +/** + * ImportTraceHandler + *

+ * TODO: Implement me. Please. + */ +public class ImportTraceHandler implements IHandler { + + private LTTngProjectNode fProject = null; + + // ------------------------------------------------------------------------ + // Validation + // ------------------------------------------------------------------------ + + public boolean isEnabled() { + + // Check if we are closing down + IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + if (window == null) + return false; + + // Check if we are in the Project View + IWorkbenchPage page = window.getActivePage(); + if (!(page.getActivePart() instanceof ProjectView)) + return false; + + // Check if a project is selected + ISelection selection = page.getSelection(ProjectView.ID); + if (selection instanceof StructuredSelection) { + Object element = ((StructuredSelection) selection).getFirstElement(); + if (element instanceof ILTTngProjectTreeNode) { + ILTTngProjectTreeNode node = (ILTTngProjectTreeNode) element; + while (node != null && !(node instanceof LTTngProjectNode)) { + node = node.getParent(); + } + fProject = (node instanceof LTTngProjectNode) ? (LTTngProjectNode) node : null; + } + } + + return (fProject != null && fProject.isOpen() && fProject.isLTTngProject()); + } + + // Always handled + public boolean isHandled() { + return true; + } + + // ------------------------------------------------------------------------ + // Execution + // ------------------------------------------------------------------------ + + public Object execute(ExecutionEvent event) throws ExecutionException { + + // Set the selection to the project + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + ProjectView view = (ProjectView) page.getActivePart(); + view.setSelection(fProject); + + // Fire the Import Trace Wizard + IWorkbench workbench = PlatformUI.getWorkbench(); + Shell shell = workbench.getActiveWorkbenchWindow().getShell(); + + ImportTraceWizard wizard = new ImportTraceWizard(); + wizard.init(PlatformUI.getWorkbench(), new StructuredSelection(fProject)); + WizardDialog dialog = new WizardDialog(shell, wizard); + dialog.open(); + + if (dialog.getReturnCode() == Window.OK && fProject != null) { + fProject.refreshChildren(); + fProject.refresh(); + } + + return null; + } + + public void dispose() { + // TODO Auto-generated method stub + } + + // ------------------------------------------------------------------------ + // IHandlerListener + // ------------------------------------------------------------------------ + + public void addHandlerListener(IHandlerListener handlerListener) { + // TODO Auto-generated method stub + } + + public void removeHandlerListener(IHandlerListener handlerListener) { + // TODO Auto-generated method stub + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/NewExperimentHandler.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/NewExperimentHandler.java new file mode 100644 index 0000000000..b6e760e2b4 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/NewExperimentHandler.java @@ -0,0 +1,117 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.handlers; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.IHandler; +import org.eclipse.core.commands.IHandlerListener; +import org.eclipse.core.resources.IFolder; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.window.Window; +import org.eclipse.linuxtools.lttng.ui.views.project.ProjectView; +import org.eclipse.linuxtools.lttng.ui.views.project.dialogs.NewExperimentDialog; +import org.eclipse.linuxtools.lttng.ui.views.project.model.ILTTngProjectTreeNode; +import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngExperimentFolderNode; +import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngProjectNode; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; + +/** + * NewExperimentHandler + *

+ * TODO: Implement me. Please. + */ +public class NewExperimentHandler implements IHandler { + + private LTTngProjectNode fProject = null; + + // ------------------------------------------------------------------------ + // Validation + // ------------------------------------------------------------------------ + + public boolean isEnabled() { + + // Check if we are closing down + IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + if (window == null) + return false; + + // Check if we are in the Project View + IWorkbenchPage page = window.getActivePage(); + if (!(page.getActivePart() instanceof ProjectView)) + return false; + + // Check if a project is selected + ISelection selection = page.getSelection(ProjectView.ID); + if (selection instanceof StructuredSelection) { + Object element = ((StructuredSelection) selection).getFirstElement(); + if (element instanceof ILTTngProjectTreeNode) { + ILTTngProjectTreeNode node = (ILTTngProjectTreeNode) element; + while (node != null && !(node instanceof LTTngProjectNode)) { + node = node.getParent(); + } + fProject = (node instanceof LTTngProjectNode) ? (LTTngProjectNode) node : null; + } + } + + return (fProject != null && fProject.isOpen() && fProject.isLTTngProject()); + } + + // Handled if we are in the ProjectView + public boolean isHandled() { + return true; + } + + // ------------------------------------------------------------------------ + // Execution + // ------------------------------------------------------------------------ + + public Object execute(ExecutionEvent event) throws ExecutionException { + + // Open the experiment creation dialog + LTTngExperimentFolderNode experimentFolder = fProject.getExperimentsFolder(); + Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); + NewExperimentDialog dialog = new NewExperimentDialog(shell, experimentFolder); + dialog.open(); + + if (dialog.getReturnCode() == Window.OK) { + Object[] experiments = dialog.getResult(); + if (experiments[0] instanceof IFolder) { + experimentFolder.addExperiment((IFolder) experiments[0]); + } + } + + return null; + } + + public void dispose() { + // TODO Auto-generated method stub + } + + // ------------------------------------------------------------------------ + // IHandlerListener + // ------------------------------------------------------------------------ + + public void addHandlerListener(IHandlerListener handlerListener) { + // TODO Auto-generated method stub + } + + public void removeHandlerListener(IHandlerListener handlerListener) { + // TODO Auto-generated method stub + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/NewProjectHandler.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/NewProjectHandler.java new file mode 100644 index 0000000000..a4863073e0 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/NewProjectHandler.java @@ -0,0 +1,105 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.handlers; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.IHandler; +import org.eclipse.core.commands.IHandlerListener; +import org.eclipse.core.resources.IProject; +import org.eclipse.jface.window.Window; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.linuxtools.lttng.ui.views.project.ProjectView; +import org.eclipse.linuxtools.lttng.ui.views.project.dialogs.NewProjectWizard; +import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngProjectRoot; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; + +/** + * NewProjectHandler + *

+ * TODO: Implement me. Please. + */ +public class NewProjectHandler implements IHandler { + + private LTTngProjectRoot fProjectRoot = null; + + // ------------------------------------------------------------------------ + // Validation + // ------------------------------------------------------------------------ + + public boolean isEnabled() { + + // Check if we are closing down + IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + if (window == null) + return false; + + // Check if we are in the Project View + IWorkbenchPart part = window.getActivePage().getActivePart(); + if (!(part instanceof ProjectView)) + return false; + + fProjectRoot = ((ProjectView) part).getRoot(); + + return (fProjectRoot != null); + } + + // Always handled + public boolean isHandled() { + return true; + } + + // ------------------------------------------------------------------------ + // Execution + // ------------------------------------------------------------------------ + + public Object execute(ExecutionEvent event) throws ExecutionException { + + // Fire the New Project Wizard + Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); + NewProjectWizard wizard = new NewProjectWizard(); + WizardDialog dialog = new WizardDialog(shell, wizard); + dialog.open(); + + // Update the project model + if (dialog.getReturnCode() == Window.OK) { + IProject project = wizard.getProject(); + if (project != null && fProjectRoot != null) { + fProjectRoot.refreshChildren(); + fProjectRoot.refresh(); + } + } + + return null; + } + + public void dispose() { + // TODO Auto-generated method stub + } + + // ------------------------------------------------------------------------ + // IHandlerListener + // ------------------------------------------------------------------------ + + public void addHandlerListener(IHandlerListener handlerListener) { + // TODO Auto-generated method stub + } + + public void removeHandlerListener(IHandlerListener handlerListener) { + // TODO Auto-generated method stub + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/OpenExperimentHandler.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/OpenExperimentHandler.java new file mode 100644 index 0000000000..c7948b4dbb --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/OpenExperimentHandler.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.handlers; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.IHandler; +import org.eclipse.core.commands.IHandlerListener; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.linuxtools.lttng.ui.views.project.ProjectView; +import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngExperimentNode; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; + +/** + * OpenExperimentHandler + *

+ * TODO: Implement me. Please. + */ +public class OpenExperimentHandler implements IHandler { + + private LTTngExperimentNode fExperiment = null; + + // ------------------------------------------------------------------------ + // Validation + // ------------------------------------------------------------------------ + + public boolean isEnabled() { + // Check if we are closing down + IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + if (window == null) + return false; + + // Check if a trace is selected + IWorkbenchPage page = window.getActivePage(); + if (!(page.getActivePart() instanceof ProjectView)) + return false; + + // Check if a trace is selected + ISelection selection = page.getSelection(ProjectView.ID); + if (selection instanceof StructuredSelection) { + Object element = ((StructuredSelection) selection).getFirstElement(); + fExperiment = (element instanceof LTTngExperimentNode) ? (LTTngExperimentNode) element : null; + } + + return (fExperiment != null); + } + + // Handled if we are in the ProjectView + public boolean isHandled() { + return true; + } + + // ------------------------------------------------------------------------ + // Execution + // ------------------------------------------------------------------------ + + public Object execute(ExecutionEvent event) throws ExecutionException { + + // Set the selection to the project + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + ProjectView projectView = (ProjectView) page.getActivePart(); + + if (projectView != null) { + projectView.selectExperiment(fExperiment); + } + + return null; + } + + // ------------------------------------------------------------------------ + // IHandlerListener + // ------------------------------------------------------------------------ + + public void addHandlerListener(IHandlerListener handlerListener) { + // TODO Auto-generated method stub + } + + public void removeHandlerListener(IHandlerListener handlerListener) { + // TODO Auto-generated method stub + } + + public void dispose() { + // TODO Auto-generated method stub + + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/OpenProjectHandler.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/OpenProjectHandler.java new file mode 100644 index 0000000000..8aabb38720 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/OpenProjectHandler.java @@ -0,0 +1,95 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.handlers; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.IHandler; +import org.eclipse.core.commands.IHandlerListener; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.linuxtools.lttng.ui.views.project.ProjectView; +import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngProjectNode; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; + +/** + * OpenProjectHandler + *

+ * TODO: Implement me. Please. + */ +public class OpenProjectHandler implements IHandler { + + private LTTngProjectNode fProject = null; + + // ------------------------------------------------------------------------ + // Validation + // ------------------------------------------------------------------------ + + public boolean isEnabled() { + + // Check if we are closing down + IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + if (window == null) + return false; + + // Check if we are in the Project View + IWorkbenchPage page = window.getActivePage(); + if (!(page.getActivePart() instanceof ProjectView)) + return false; + + // Check if a project is selected + ISelection selection = page.getSelection(ProjectView.ID); + if (selection instanceof StructuredSelection) { + Object element = ((StructuredSelection) selection).getFirstElement(); + fProject = (element instanceof LTTngProjectNode) ? (LTTngProjectNode) element : null; + } + return (fProject != null && !fProject.isOpen()); + } + + // Handled if we are in the ProjectView + public boolean isHandled() { + return true; + } + + // ------------------------------------------------------------------------ + // Execution + // ------------------------------------------------------------------------ + + public Object execute(ExecutionEvent event) throws ExecutionException { + + if (fProject != null) { + fProject.openProject(); + fProject.refresh(); + } + return null; + } + + public void dispose() { + // TODO Auto-generated method stub + } + + // ------------------------------------------------------------------------ + // IHandlerListener + // ------------------------------------------------------------------------ + + public void addHandlerListener(IHandlerListener handlerListener) { + // TODO Auto-generated method stub + } + + public void removeHandlerListener(IHandlerListener handlerListener) { + // TODO Auto-generated method stub + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/OpenTraceHandler.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/OpenTraceHandler.java new file mode 100644 index 0000000000..8e011112b1 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/OpenTraceHandler.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.handlers; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.IHandler; +import org.eclipse.core.commands.IHandlerListener; +import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngTraceNode; +import org.eclipse.swt.widgets.MessageBox; +import org.eclipse.ui.PlatformUI; + +/** + * OpenTraceHandler + *

+ * TODO: Implement me. Please. + */ +public class OpenTraceHandler implements IHandler { + + private LTTngTraceNode fTrace = null; + + // ------------------------------------------------------------------------ + // Validation + // ------------------------------------------------------------------------ + + public boolean isEnabled() { + return (fTrace != null); + } + + // Handled if we are in the ProjectView + public boolean isHandled() { + return true; + } + + // ------------------------------------------------------------------------ + // Execution + // ------------------------------------------------------------------------ + + public Object execute(ExecutionEvent event) throws ExecutionException { + + MessageBox mb = new MessageBox(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell()); + mb.setText("Open Trace"); + mb.setMessage("Not implemented yet"); + mb.open(); + + return null; + } + + public void dispose() { + // TODO Auto-generated method stub + } + + // ------------------------------------------------------------------------ + // IHandlerListener + // ------------------------------------------------------------------------ + + public void addHandlerListener(IHandlerListener handlerListener) { + // TODO Auto-generated method stub + } + + public void removeHandlerListener(IHandlerListener handlerListener) { + // TODO Auto-generated method stub + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/RefreshHandler.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/RefreshHandler.java new file mode 100644 index 0000000000..740ed30a40 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/RefreshHandler.java @@ -0,0 +1,98 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.handlers; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.IHandler; +import org.eclipse.core.commands.IHandlerListener; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.linuxtools.lttng.ui.views.project.ProjectView; +import org.eclipse.linuxtools.lttng.ui.views.project.model.ILTTngProjectTreeNode; +import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngProjectRoot; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; + +/** + * RefreshHandler + *

+ * TODO: Implement me. Please. + */ +public class RefreshHandler implements IHandler { + + private LTTngProjectRoot fProjectRoot = null; + + // ------------------------------------------------------------------------ + // Validation + // ------------------------------------------------------------------------ + + public boolean isEnabled() { + + // Check if we are closing down + IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + if (window == null) + return false; + + // Check if we can find the project model root node + ISelection selection = window.getActivePage().getSelection(ProjectView.ID); + if (selection instanceof StructuredSelection) { + Object element = ((StructuredSelection) selection).getFirstElement(); + if (element instanceof ILTTngProjectTreeNode) { + ILTTngProjectTreeNode node = (ILTTngProjectTreeNode) element; + while (node != null && !(node instanceof LTTngProjectRoot)) { + node = node.getParent(); + } + fProjectRoot = (node instanceof LTTngProjectRoot) ? (LTTngProjectRoot) node : null; + } + } + + return (fProjectRoot != null); + } + + // Handled if we are in the ProjectView + public boolean isHandled() { + return true; + } + + // ------------------------------------------------------------------------ + // Execution + // ------------------------------------------------------------------------ + + public Object execute(ExecutionEvent event) throws ExecutionException { + + if (fProjectRoot != null) { + fProjectRoot.refreshChildren(); + fProjectRoot.refresh(); + } + + return null; + } + + public void dispose() { + // TODO Auto-generated method stub + } + + // ------------------------------------------------------------------------ + // IHandlerListener + // ------------------------------------------------------------------------ + + public void addHandlerListener(IHandlerListener handlerListener) { + // TODO Auto-generated method stub + } + + public void removeHandlerListener(IHandlerListener handlerListener) { + // TODO Auto-generated method stub + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/RenameExperimentHandler.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/RenameExperimentHandler.java new file mode 100644 index 0000000000..7651437131 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/RenameExperimentHandler.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.handlers; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.IHandler; +import org.eclipse.core.commands.IHandlerListener; +import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngExperimentNode; +import org.eclipse.swt.widgets.MessageBox; +import org.eclipse.ui.PlatformUI; + +/** + * RenameExperimentHandler + *

+ * TODO: Implement me. Please. + */ +public class RenameExperimentHandler implements IHandler { + + private LTTngExperimentNode fExperiment = null; + + // ------------------------------------------------------------------------ + // Validation + // ------------------------------------------------------------------------ + + public boolean isEnabled() { + return (fExperiment != null); + } + + // Handled if we are in the ProjectView + public boolean isHandled() { + return true; + } + + // ------------------------------------------------------------------------ + // Execution + // ------------------------------------------------------------------------ + + public Object execute(ExecutionEvent event) throws ExecutionException { + + MessageBox mb = new MessageBox(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell()); + mb.setText("Rename Experiment"); + mb.setMessage("Not implemented yet"); + mb.open(); + + return null; + } + + public void dispose() { + // TODO Auto-generated method stub + } + + // ------------------------------------------------------------------------ + // IHandlerListener + // ------------------------------------------------------------------------ + + public void addHandlerListener(IHandlerListener handlerListener) { + // TODO Auto-generated method stub + } + + public void removeHandlerListener(IHandlerListener handlerListener) { + // TODO Auto-generated method stub + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/RenameProjectHandler.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/RenameProjectHandler.java new file mode 100644 index 0000000000..43dc44b2ac --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/RenameProjectHandler.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.handlers; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.IHandler; +import org.eclipse.core.commands.IHandlerListener; +import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngProjectNode; +import org.eclipse.swt.widgets.MessageBox; +import org.eclipse.ui.PlatformUI; + +/** + * RenameProjectHandler + *

+ * TODO: Implement me. Please. + */ +public class RenameProjectHandler implements IHandler { + + private LTTngProjectNode fProject = null; + + // ------------------------------------------------------------------------ + // Validation + // ------------------------------------------------------------------------ + + public boolean isEnabled() { + +// // Check if we are closing down +// IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); +// if (window == null) +// return false; +// +// // Check if we are in the Project View +// IWorkbenchPage page = window.getActivePage(); +// if (!(page.getActivePart() instanceof ProjectView)) +// return false; +// +// // Check if a project is selected +// ISelection selection = page.getSelection(ProjectView.ID); +// if (selection instanceof StructuredSelection) { +// Object element = ((StructuredSelection) selection).getFirstElement(); +// fProjectNode = (element instanceof LTTngProjectNode) ? (LTTngProjectNode) element : null; +// } + + return (fProject != null); + } + + // Handled if we are in the ProjectView + public boolean isHandled() { + return false; + } + + // ------------------------------------------------------------------------ + // Execution + // ------------------------------------------------------------------------ + + public Object execute(ExecutionEvent event) throws ExecutionException { + + MessageBox mb = new MessageBox(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell()); + mb.setText("Rename Project"); + mb.setMessage("Not implemented yet"); + mb.open(); + + return null; + } + + public void dispose() { + // TODO Auto-generated method stub + } + + // ------------------------------------------------------------------------ + // IHandlerListener + // ------------------------------------------------------------------------ + + public void addHandlerListener(IHandlerListener handlerListener) { + // TODO Auto-generated method stub + } + + public void removeHandlerListener(IHandlerListener handlerListener) { + // TODO Auto-generated method stub + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/RenameTraceHandler.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/RenameTraceHandler.java new file mode 100644 index 0000000000..3c1457d2ff --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/RenameTraceHandler.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.handlers; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.IHandler; +import org.eclipse.core.commands.IHandlerListener; +import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngTraceNode; +import org.eclipse.swt.widgets.MessageBox; +import org.eclipse.ui.PlatformUI; + +/** + * RenameTraceHandler + *

+ * TODO: Implement me. Please. + */ +public class RenameTraceHandler implements IHandler { + + private LTTngTraceNode fTrace = null; + + // ------------------------------------------------------------------------ + // Validation + // ------------------------------------------------------------------------ + + public boolean isEnabled() { + return (fTrace != null); + } + + // Handled if we are in the ProjectView + public boolean isHandled() { + return true; + } + + // ------------------------------------------------------------------------ + // Execution + // ------------------------------------------------------------------------ + + public Object execute(ExecutionEvent event) throws ExecutionException { + + MessageBox mb = new MessageBox(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell()); + mb.setText("Rename Trace"); + mb.setMessage("Not implemented yet"); + mb.open(); + + return null; + } + + public void dispose() { + // TODO Auto-generated method stub + } + + // ------------------------------------------------------------------------ + // IHandlerListener + // ------------------------------------------------------------------------ + + public void addHandlerListener(IHandlerListener handlerListener) { + // TODO Auto-generated method stub + } + + public void removeHandlerListener(IHandlerListener handlerListener) { + // TODO Auto-generated method stub + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/SelectTracesHandler.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/SelectTracesHandler.java new file mode 100644 index 0000000000..ef3804dcaa --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/SelectTracesHandler.java @@ -0,0 +1,105 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.handlers; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.IHandler; +import org.eclipse.core.commands.IHandlerListener; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.linuxtools.lttng.ui.views.project.ProjectView; +import org.eclipse.linuxtools.lttng.ui.views.project.dialogs.AddTraceWizard; +import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngExperimentNode; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; + +/** + * SelectTracesHandler + *

+ * TODO: Implement me. Please. + */ +public class SelectTracesHandler implements IHandler { + + private LTTngExperimentNode fExperiment = null; + + // ------------------------------------------------------------------------ + // Validation + // ------------------------------------------------------------------------ + + public boolean isEnabled() { + + // Check if we are closing down + IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + if (window == null) + return false; + + // Check if we are in the Project View + IWorkbenchPage page = window.getActivePage(); + if (!(page.getActivePart() instanceof ProjectView)) + return false; + + // Check that an experiment is selected + ISelection selection = page.getSelection(ProjectView.ID); + if (selection instanceof StructuredSelection) { + Object element = ((StructuredSelection) selection).getFirstElement(); + fExperiment = (element instanceof LTTngExperimentNode) ? (LTTngExperimentNode) element : null; + } + + return (fExperiment != null); + } + + // Handled if we are in the ProjectView + public boolean isHandled() { + return true; + } + + // ------------------------------------------------------------------------ + // Execution + // ------------------------------------------------------------------------ + + public Object execute(ExecutionEvent event) throws ExecutionException { + + // Open the trace addition wizard + IWorkbench workbench = PlatformUI.getWorkbench(); + Shell shell = workbench.getActiveWorkbenchWindow().getShell(); + + AddTraceWizard wizard = new AddTraceWizard(fExperiment.getProject(), fExperiment); + wizard.init(PlatformUI.getWorkbench(), null); + WizardDialog dialog = new WizardDialog(shell, wizard); + dialog.open(); + + return null; + } + + public void dispose() { + // TODO Auto-generated method stub + } + + // ------------------------------------------------------------------------ + // IHandlerListener + // ------------------------------------------------------------------------ + + public void addHandlerListener(IHandlerListener handlerListener) { + // TODO Auto-generated method stub + } + + public void removeHandlerListener(IHandlerListener handlerListener) { + // TODO Auto-generated method stub + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/TraceErrorHandler.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/TraceErrorHandler.java new file mode 100644 index 0000000000..ebd6f4deef --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/handlers/TraceErrorHandler.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * William Bourque - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.handlers; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.IHandler; +import org.eclipse.core.commands.IHandlerListener; +import org.eclipse.linuxtools.lttng.ui.views.project.dialogs.TraceErrorDialog; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.PlatformUI; + + +public class TraceErrorHandler implements IHandler { + + private String[] messages; + + public TraceErrorHandler(String[] newMessages) { + messages = newMessages; + } + + public boolean isEnabled() { + return true; + } + + public boolean isHandled() { + return true; + } + + public Object execute(ExecutionEvent event) throws ExecutionException { + IWorkbench workbench = PlatformUI.getWorkbench(); + Shell shell = workbench.getActiveWorkbenchWindow().getShell(); + + TraceErrorDialog dialog = new TraceErrorDialog(shell, messages); + dialog.open(); + + return null; + } + + public void dispose() { + } + + public void addHandlerListener(IHandlerListener handlerListener) { + } + + public void removeHandlerListener(IHandlerListener handlerListener) { + } + +} + diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/ILTTngProjectTreeNode.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/ILTTngProjectTreeNode.java new file mode 100644 index 0000000000..dea2e32dec --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/ILTTngProjectTreeNode.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.model; + +import java.util.List; + +/** + * ILTTngProjectTreeNode + *

+ * TODO: Implement me. Please. + * TODO: Make ILTTngProjectTreeNode extends IAdaptable + */ +public interface ILTTngProjectTreeNode { + + public String getName(); + + public ILTTngProjectTreeNode getParent(); + + public boolean hasChildren(); + + public List getChildren(); + + public void removeChild(ILTTngProjectTreeNode child); + + public void removeChildren(); + + public void refreshChildren(); + + public void refresh(); + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngExperimentFolderNode.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngExperimentFolderNode.java new file mode 100644 index 0000000000..5f5416b52e --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngExperimentFolderNode.java @@ -0,0 +1,130 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.model; + +import java.lang.reflect.Array; + +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; + +/** + * LTTngExperimentFolderNode + *

+ * TODO: Implement me. Please. + */ +public class LTTngExperimentFolderNode extends LTTngProjectTreeNode { + + private final IFolder fExperimentFolder; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + public LTTngExperimentFolderNode(IFolder folder) { + this(null, folder); + } + + public LTTngExperimentFolderNode(ILTTngProjectTreeNode parent, IFolder folder) { + super(parent); + fExperimentFolder = folder; + } + + // ------------------------------------------------------------------------ + // LTTngProjectTreeNode + // ------------------------------------------------------------------------ + + public String getName() { + return fExperimentFolder.getName(); + } + + @Override + public void refreshChildren() { + try { + IResource[] resources = fExperimentFolder.members(); + for (IResource resource : resources) { + if (resource instanceof IFolder) { + LTTngExperimentNode node = find(resource.getName()); + if (node == null) { + node = new LTTngExperimentNode(this, (IFolder) resource); + fChildren.add(node); + } + } + } + for (ILTTngProjectTreeNode node : fChildren) { + if (exists(node.getName(), resources)) { + node.refreshChildren(); + } + else { + fChildren.remove(node); + } + } + } catch (CoreException e) { + } + } + + private LTTngExperimentNode find(String name) { + for (ILTTngProjectTreeNode node : fChildren) { + if (node instanceof LTTngExperimentNode && node.getName().equals(name)) { + return (LTTngExperimentNode) node; + } + } + return null; + } + + private boolean exists(String name, IResource[] resources) { + for (IResource resource : resources) { + if (resource.getName().equals(name)) + return true; + } + return false; + } + + // ------------------------------------------------------------------------ + // Accessors + // ------------------------------------------------------------------------ + + /** + * @return + */ + public LTTngProjectNode getProject() { + return (LTTngProjectNode) getParent(); + } + + /** + * @return + */ + public IFolder getFolder() { + return fExperimentFolder; + } + + /** + * @return + */ + public LTTngExperimentNode[] getExperiments() { + LTTngExperimentNode[] result = (LTTngExperimentNode[]) Array.newInstance(LTTngExperimentNode.class, fChildren.size()); + return fChildren.toArray(result); + } + + // ------------------------------------------------------------------------ + // Modifiers + // ------------------------------------------------------------------------ + +// No longer needed: handled by the IResourceChangeListener in the View + public void addExperiment(IFolder experiment) { +// LTTngExperimentNode node = new LTTngExperimentNode(this, experiment); +// fChildren.add(node); +// refresh(); + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngExperimentNode.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngExperimentNode.java new file mode 100644 index 0000000000..e494bc4234 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngExperimentNode.java @@ -0,0 +1,125 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.model; + +import java.lang.reflect.Array; + +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; + +/** + * LTTngExperimentNode + *

+ * TODO: Implement me. Please. + */ +public class LTTngExperimentNode extends LTTngProjectTreeNode { + + private final IFolder fExperiment; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + public LTTngExperimentNode(IFolder resource) { + this(null, resource); + } + + public LTTngExperimentNode(ILTTngProjectTreeNode parent, IFolder folder) { + super(parent); + fExperiment = folder; + } + + // ------------------------------------------------------------------------ + // LTTngProjectTreeNode + // ------------------------------------------------------------------------ + + public String getName() { + return fExperiment.getName(); + } + + @Override + public void refreshChildren() { + try { + IResource[] resources = fExperiment.members(0); + for (IResource resource : resources) { + LTTngTraceNode node = find(resource.getName()); + if (node == null) { + node = new LTTngTraceNode(this, (IFolder) resource); + fChildren.add(node); + } + } + for (ILTTngProjectTreeNode node : fChildren) { + if (!exists(node.getName(), resources)) { + fChildren.remove(node); + } + } + } catch (CoreException e) { + } + } + + private LTTngTraceNode find(String name) { + for (ILTTngProjectTreeNode node : fChildren) { + if (node instanceof LTTngTraceNode && node.getName().equals(name)) { + return (LTTngTraceNode) node; + } + } + return null; + } + + private boolean exists(String name, IResource[] resources) { + for (IResource resource : resources) { + if (resource.getName().equals(name)) + return true; + } + return false; + } + + // ------------------------------------------------------------------------ + // Modifiers + // ------------------------------------------------------------------------ + +// No longer needed: handled by the IResourceChangeListener in the View + public void addTrace(IFolder trace) { +// LTTngTraceNode node = new LTTngTraceNode(this, trace); +// fChildren.add(node); +// refresh(); + } + + // ------------------------------------------------------------------------ + // Accessors + // ------------------------------------------------------------------------ + + /** + * @return + */ + public IFolder getFolder() { + return fExperiment; + } + + /** + * @return + */ + public LTTngTraceNode[] getTraces() { + LTTngTraceNode[] result = (LTTngTraceNode[]) Array.newInstance(LTTngTraceNode.class, fChildren.size()); + return fChildren.toArray(result); + } + + /** + * @return + */ + public LTTngProjectNode getProject() { + return (LTTngProjectNode) getParent().getParent(); + } + +} \ No newline at end of file diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngProjectContentProvider.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngProjectContentProvider.java new file mode 100644 index 0000000000..12a8f74cc1 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngProjectContentProvider.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.model; + +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.Viewer; + +/** + * LTTngProjectContentProvider + *

+ * TODO: Implement me. Please. + */ + public class LTTngProjectContentProvider implements ITreeContentProvider { + + public Object[] getChildren(Object parentElement) { + return ((ILTTngProjectTreeNode) parentElement).getChildren().toArray(); + } + + public Object getParent(Object element) { + return ((ILTTngProjectTreeNode) element).getParent(); + } + + public boolean hasChildren(Object element) { + return ((ILTTngProjectTreeNode) element).hasChildren(); + } + + public Object[] getElements(Object inputElement) { + if (inputElement instanceof LTTngProjectRoot) { + return ((LTTngProjectRoot) inputElement).getChildren().toArray(); + } + return null; + } + + public void dispose() { + // TODO Auto-generated method stub + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + // TODO Auto-generated method stub + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngProjectLabelProvider.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngProjectLabelProvider.java new file mode 100644 index 0000000000..6dee2d47ef --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngProjectLabelProvider.java @@ -0,0 +1,140 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.model; + +import java.net.URL; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.linuxtools.lttng.ui.LTTngUiPlugin; +import org.eclipse.swt.graphics.Image; +import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.PlatformUI; + +/** + * LTTngProjectLabelProvider + *

+ * TODO: Implement me. Please. + * TODO: Find proper icons for traces and experiments + */ +public class LTTngProjectLabelProvider implements ILabelProvider { + + private final String fTraceIconFile = "icons/garland16.png"; +// private final String fExperimentIconFile = "icons/garland16.png"; + + private final Image fOpenedProjectIcon; + private final Image fClosedProjectIcon; + private final Image fFolderIcon; + private final Image fTraceIcon; + private final Image fExperimentIcon; + + /** + * + */ + public LTTngProjectLabelProvider() { + + fOpenedProjectIcon = PlatformUI.getWorkbench().getSharedImages().getImage(org.eclipse.ui.ide.IDE.SharedImages.IMG_OBJ_PROJECT); + fClosedProjectIcon = PlatformUI.getWorkbench().getSharedImages().getImage(org.eclipse.ui.ide.IDE.SharedImages.IMG_OBJ_PROJECT_CLOSED); + fFolderIcon = PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FOLDER); + + fTraceIcon = loadIcon(fTraceIconFile); + fExperimentIcon = fFolderIcon; // loadIcon(fExperimentIconFile); + } + + private Image loadIcon(String url) { + LTTngUiPlugin plugin = LTTngUiPlugin.getDefault(); + Image icon = plugin.getImageRegistry().get(url); + if (icon == null) { + URL imageURL = plugin.getBundle().getEntry(url); + ImageDescriptor descriptor = ImageDescriptor.createFromURL(imageURL); + icon = descriptor.createImage(); + plugin.getImageRegistry().put(url, icon); + } + return icon; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ILabelProvider#getImage(java.lang.Object) + */ + public Image getImage(Object element) { + + if (element instanceof LTTngProjectNode) { + LTTngProjectNode project = (LTTngProjectNode) element; + return (project.isOpen()) ? fOpenedProjectIcon : fClosedProjectIcon; + } + + if (element instanceof LTTngTraceFolderNode) { + return fFolderIcon; + } + + if (element instanceof LTTngTraceNode) { + return fTraceIcon; + } + + if (element instanceof LTTngExperimentFolderNode) { + return fFolderIcon; + } + + if (element instanceof LTTngExperimentNode) { + return fExperimentIcon; + } + + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ILabelProvider#getText(java.lang.Object) + */ + public String getText(Object element) { + ILTTngProjectTreeNode node = (ILTTngProjectTreeNode) element; + String label = node.getName(); + if (node instanceof LTTngTraceFolderNode || + node instanceof LTTngExperimentFolderNode || + node instanceof LTTngExperimentNode) + { + label += " [" + node.getChildren().size() + "]"; + } + return label; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.IBaseLabelProvider#addListener(org.eclipse.jface.viewers.ILabelProviderListener) + */ + public void addListener(ILabelProviderListener listener) { + // TODO Auto-generated method stub + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose() + */ + public void dispose() { + // TODO Auto-generated method stub + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.IBaseLabelProvider#isLabelProperty(java.lang.Object, java.lang.String) + */ + public boolean isLabelProperty(Object element, String property) { + // TODO Auto-generated method stub + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.IBaseLabelProvider#removeListener(org.eclipse.jface.viewers.ILabelProviderListener) + */ + public void removeListener(ILabelProviderListener listener) { + // TODO Auto-generated method stub + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngProjectNode.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngProjectNode.java new file mode 100644 index 0000000000..748dce726f --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngProjectNode.java @@ -0,0 +1,200 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.model; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.linuxtools.lttng.ui.views.project.LTTngProjectNature; + +/** + * LTTngProjectNode + *

+ * TODO: Implement me. Please. + */ +public class LTTngProjectNode extends LTTngProjectTreeNode { + + public static final String TRACE_FOLDER_NAME = "Traces"; + public static final String EXPER_FOLDER_NAME = "Experiments"; + + private final IProject fProject; + private boolean fIsLTTngProject; + private boolean fIsOpen; + private LTTngTraceFolderNode fTracesFolder; + private LTTngExperimentFolderNode fExperimentsFolder; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + public LTTngProjectNode(IProject project) { + this(null, project); + } + + public LTTngProjectNode(ILTTngProjectTreeNode parent, IProject project) { + super(parent); + fProject = project; + updateState(); + } + + // ------------------------------------------------------------------------ + // LTTngProjectTreeNode + // ------------------------------------------------------------------------ + + public String getName() { + return fProject.getName(); + } + + @Override + public void refreshChildren() { + + if (!(fIsOpen && fIsLTTngProject)) + return; + + try { + IResource[] resources = fProject.members(); + for (IResource resource : resources) { + if (resource.getType() == IResource.FOLDER) { + String name = resource.getName(); + if (name.equals(TRACE_FOLDER_NAME) && !isIncluded(true, name, fChildren)) { + fTracesFolder = new LTTngTraceFolderNode(this, (IFolder) resource); + fChildren.add(fTracesFolder); + } else + if (name.equals(EXPER_FOLDER_NAME) && !isIncluded(false, name, fChildren)) { + fExperimentsFolder = new LTTngExperimentFolderNode(this, (IFolder) resource); + fChildren.add(fExperimentsFolder); + } + } + } + List toRemove = new ArrayList(); + for (ILTTngProjectTreeNode node : fChildren) { + if (exists(node.getName(), resources)) { + node.refreshChildren(); + } + else { + toRemove.add(node); + } + } + for (ILTTngProjectTreeNode node : toRemove) { + fChildren.remove(node); + } + + } catch (CoreException e) { + } + } + + private boolean isIncluded(boolean isTraces, String name, List list) { + boolean found = false; + for (ILTTngProjectTreeNode node : list) { + if (node instanceof LTTngTraceFolderNode && isTraces) { + found |= node.getName().equals(name); + } else + if (node instanceof LTTngExperimentFolderNode && !isTraces) { + found |= node.getName().equals(name); + } + } + return found; + } + + private boolean exists(String name, IResource[] resources) { + for (IResource resource : resources) { + if (resource.getName().equals(name)) + return true; + } + return false; + } + + // ------------------------------------------------------------------------ + // Modifiers + // ------------------------------------------------------------------------ + + public void openProject() { + try { + fProject.open(null); + updateState(); + refreshChildren(); + } catch (CoreException e) { + e.printStackTrace(); + } + } + + public void closeProject() { + try { + fProject.close(null); + updateState(); + removeChildren(); + } catch (CoreException e) { + e.printStackTrace(); + } + } + + private boolean isLTTngProject(IProject project) { + boolean result = false; + if (project != null && project.isAccessible()) { + try { + result = project.hasNature(LTTngProjectNature.ID); + } catch (CoreException e) { + } + } + return result; + } + + public void updateState() { + fIsOpen = (fProject != null) ? fProject.isAccessible() : false; + fIsLTTngProject = isLTTngProject(fProject); + } + + // ------------------------------------------------------------------------ + // Accessors + // ------------------------------------------------------------------------ + + /** + * @return + */ + public boolean isLTTngProject() { + return fIsLTTngProject; + } + + /** + * @return + */ + public boolean isOpen() { + return fIsOpen; + } + + /** + * @return + */ + public IProject getProject() { + return fProject; + } + + /** + * @return + */ + public LTTngTraceFolderNode getTracesFolder() { + return fTracesFolder; + } + + /** + * @return + */ + public LTTngExperimentFolderNode getExperimentsFolder() { + return fExperimentsFolder; + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngProjectRoot.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngProjectRoot.java new file mode 100644 index 0000000000..b54831c765 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngProjectRoot.java @@ -0,0 +1,99 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.model; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.linuxtools.lttng.ui.views.project.ProjectView; + +/** + * LTTngProjectRoot + *

+ * TODO: Implement me. Please. + */ +public class LTTngProjectRoot extends LTTngProjectTreeNode { + + private final ProjectView fView; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + public LTTngProjectRoot(ProjectView view) { + super(null); + fView = view; + refreshChildren(); + } + + @Override + public void refresh() { + fView.refresh(); + } + + // ------------------------------------------------------------------------ + // LTTngProjectTreeNode + // ------------------------------------------------------------------------ + + public String getName() { + return null; + } + + @Override + public void refreshChildren() { + IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); + IProject[] projects = root.getProjects(); + for (IProject project : projects) { + LTTngProjectNode node = find(project.getName()); + if (node == null) { + node = new LTTngProjectNode(this, project); + fChildren.add(node); + } else { + node.updateState(); + } + } + List toRemove = new ArrayList(); + for (ILTTngProjectTreeNode node : fChildren) { + if (exists(node.getName(), projects)) { + node.refreshChildren(); + } + else { + toRemove.add(node); + } + } + for (ILTTngProjectTreeNode node : toRemove) { + fChildren.remove(node); + } + } + + private LTTngProjectNode find(String name) { + for (ILTTngProjectTreeNode node : fChildren) { + if (node instanceof LTTngProjectNode && node.getName().equals(name)) { + return (LTTngProjectNode) node; + } + } + return null; + } + + private boolean exists(String name, IProject[] projects) { + for (IProject project : projects) { + if (project.getName().equals(name)) + return true; + } + return false; + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngProjectTreeNode.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngProjectTreeNode.java new file mode 100644 index 0000000000..b35bbfd6a5 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngProjectTreeNode.java @@ -0,0 +1,82 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.model; + +import java.util.ArrayList; +import java.util.List; + +/** + * LTTngProjectTreeNode + *

+ * TODO: Implement me. Please. + */ +public abstract class LTTngProjectTreeNode implements ILTTngProjectTreeNode { + + protected ILTTngProjectTreeNode fParent = null; + protected List fChildren = null; + + // ------------------------------------------------------------------------ + // Constructor + // ------------------------------------------------------------------------ + + public LTTngProjectTreeNode(ILTTngProjectTreeNode parent) { + fParent = parent; + fChildren = new ArrayList(); + } + + @Override + public String toString() { + return getName(); + } + + // ------------------------------------------------------------------------ + // ILTTngProjectTreeNode + // ------------------------------------------------------------------------ + + public ILTTngProjectTreeNode getParent() { + return fParent; + } + + public boolean hasChildren() { + return fChildren.size() > 0; + } + + public List getChildren() { + return fChildren; + } + + public abstract void refreshChildren(); + + public void refresh() { + fParent.refresh(); + } + + public void removeChild(ILTTngProjectTreeNode child) { + for (ILTTngProjectTreeNode node : fChildren) { + if (node == child) { + node.removeChildren(); + // We can do it since we are returning right away + fChildren.remove(node); + return; + } + } + } + + public void removeChildren() { + for (ILTTngProjectTreeNode node : fChildren) { + node.removeChildren(); + } + fChildren.clear(); + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngTraceFolderNode.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngTraceFolderNode.java new file mode 100644 index 0000000000..de11690557 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngTraceFolderNode.java @@ -0,0 +1,127 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.model; + +import java.lang.reflect.Array; + +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; + +/** + * LTTngTraceFolderNode + *

+ * TODO: Implement me. Please. + */ +public class LTTngTraceFolderNode extends LTTngProjectTreeNode { + + private final IFolder fTraceFolder; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + public LTTngTraceFolderNode(IFolder folder) { + this(null, folder); + } + + public LTTngTraceFolderNode(ILTTngProjectTreeNode parent, IFolder folder) { + super(parent); + fTraceFolder = folder; + } + + // ------------------------------------------------------------------------ + // LTTngProjectTreeNode + // ------------------------------------------------------------------------ + + public String getName() { + return fTraceFolder.getName(); + } + + @Override + public void refreshChildren() { + try { + IResource[] resources = fTraceFolder.members(); + for (IResource resource : resources) { + if (resource instanceof IFolder) { + LTTngTraceNode node = find(resource.getName()); + if (node == null) { + node = new LTTngTraceNode(this, (IFolder) resource); + fChildren.add(node); + } + } + } + for (ILTTngProjectTreeNode node : fChildren) { + if (!exists(node.getName(), resources)) { + fChildren.remove(node); + } + } + } catch (CoreException e) { + } + } + + private LTTngTraceNode find(String name) { + for (ILTTngProjectTreeNode node : fChildren) { + if (node instanceof LTTngTraceNode && node.getName().equals(name)) { + return (LTTngTraceNode) node; + } + } + return null; + } + + private boolean exists(String name, IResource[] resources) { + for (IResource resource : resources) { + if (resource.getName().equals(name)) + return true; + } + return false; + } + + // ------------------------------------------------------------------------ + // Accessors + // ------------------------------------------------------------------------ + + /** + * @return + */ + public LTTngProjectNode getProject() { + return (LTTngProjectNode) getParent(); + } + + /** + * @return + */ + public IFolder getFolder() { + return fTraceFolder; + } + + /** + * @return + */ + public LTTngTraceNode[] getTraces() { + LTTngTraceNode[] result = (LTTngTraceNode[]) Array.newInstance(LTTngTraceNode.class, fChildren.size()); + return fChildren.toArray(result); + } + + // ------------------------------------------------------------------------ + // Modifiers + // ------------------------------------------------------------------------ + +// No longer needed: handled by the IResourceChangeListener in the View + public void addTrace(IFolder trace) { +// LTTngTraceNode node = new LTTngTraceNode(this, trace); +// fChildren.add(node); +// refresh(); + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngTraceNode.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngTraceNode.java new file mode 100644 index 0000000000..4312a2dbf1 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/project/model/LTTngTraceNode.java @@ -0,0 +1,69 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.project.model; + +import org.eclipse.core.resources.IFolder; + +/** + * LTTngTraceNode + *

+ * TODO: Implement me. Please. + */ +public class LTTngTraceNode extends LTTngProjectTreeNode { + + private final IFolder fTrace; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + public LTTngTraceNode(IFolder folder) { + this(null, folder); + } + + public LTTngTraceNode(ILTTngProjectTreeNode parent, IFolder trace) { + super(parent); + fTrace = trace; + } + + // ------------------------------------------------------------------------ + // LTTngProjectTreeNode + // ------------------------------------------------------------------------ + + public String getName() { + return fTrace.getName(); + } + + @Override + public void refreshChildren() { + } + + // ------------------------------------------------------------------------ + // Accessors + // ------------------------------------------------------------------------ + + /** + * @return + */ + public LTTngProjectNode getProject() { + return (LTTngProjectNode) getParent().getParent(); + } + + /** + * @return + */ + public IFolder getFolder() { + return fTrace; + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/Messages.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/Messages.java new file mode 100644 index 0000000000..e01dae1743 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/Messages.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.resources; + +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +public class Messages { + private static final String BUNDLE_NAME = "org.eclipse.linuxtools.lttng.ui.views.resources.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 + '!'; + } + } +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/ResourcesView.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/ResourcesView.java new file mode 100644 index 0000000000..c658ac2b10 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/ResourcesView.java @@ -0,0 +1,560 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are made + * available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Alvaro Sanchez-Leon - Initial implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.resources; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IMenuListener; +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.linuxtools.lttng.request.ILttngSyntEventRequest; +import org.eclipse.linuxtools.lttng.state.evProcessor.ITransEventProcessor; +import org.eclipse.linuxtools.lttng.ui.TraceDebug; +import org.eclipse.linuxtools.lttng.ui.model.trange.ItemContainer; +import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeViewerProvider; +import org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView; +import org.eclipse.linuxtools.lttng.ui.views.common.ParamsUpdater; +import org.eclipse.linuxtools.lttng.ui.views.resources.evProcessor.ResourcesEventToHandlerFactory; +import org.eclipse.linuxtools.lttng.ui.views.resources.model.ResourceModelFactory; +import org.eclipse.linuxtools.tmf.event.TmfEvent; +import org.eclipse.linuxtools.tmf.event.TmfTimeRange; +import org.eclipse.linuxtools.tmf.experiment.TmfExperiment; +import org.eclipse.linuxtools.tmf.signal.TmfExperimentSelectedSignal; +import org.eclipse.linuxtools.tmf.signal.TmfRangeSynchSignal; +import org.eclipse.linuxtools.tmf.signal.TmfSignalHandler; +import org.eclipse.linuxtools.tmf.signal.TmfTimeSynchSignal; +import org.eclipse.linuxtools.tmf.ui.viewers.TmfViewerFactory; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.ITmfTimeScaleSelectionListener; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.ITmfTimeSelectionListener; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeScaleSelectionEvent; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeSelectionEvent; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITmfTimeAnalysisEntry; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.IWorkbenchActionConstants; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.plugin.AbstractUIPlugin; + +/** + * @author alvaro + * + */ +public class ResourcesView extends AbsTimeUpdateView implements + ITmfTimeSelectionListener, ITmfTimeScaleSelectionListener { + + // ======================================================================== + // Data + // ======================================================================== + public static final String ID = "org.eclipse.linuxtools.lttng.ui.views.resources"; + + // private int totalNumItems = 0; + // Actions + private Action resetScale; + private Action nextEvent; + private Action prevEvent; + private Action nextTrace; + private Action prevTrace; + private Action showLegend; + private Action filterTraces; + private Action zoomIn; + private Action zoomOut; + private Action zoomFilter; + private Composite top; + + // private static SimpleDateFormat stimeformat = new SimpleDateFormat( + // "yy/MM/dd HH:mm:ss"); + + // private TraceModelImplFactory fact; + + // ======================================================================== + // Constructor + // ======================================================================== + + /** + * The constructor. + */ + public ResourcesView() { + super(ID); + } + + // ======================================================================== + // Methods + // ======================================================================== + + /** + * This is a callback that will allow us to create the viewer and initialize + * it. + */ + @Override + public void createPartControl(Composite parent) { + top = new Composite(parent, SWT.BORDER); + + top.setLayout(new FillLayout()); + tsfviewer = TmfViewerFactory.createViewer(top, + new TimeRangeViewerProvider()); + + tsfviewer.addWidgetSelectionListner(this); + tsfviewer.addWidgetTimeScaleSelectionListner(this); + + // Traces shall not be grouped to allow synchronisation + tsfviewer.groupTraces(true); + tsfviewer.setAcceptSelectionAPIcalls(true); + + // Viewer to notify selection to this class + // This class will synchronise selections with table. + tsfviewer.addWidgetSelectionListner(this); + tsfviewer.addWidgetTimeScaleSelectionListner(this); + + // Create the help context id for the viewer's control + // TODO: Associate with help system + PlatformUI.getWorkbench().getHelpSystem().setHelp( + tsfviewer.getControl(), + "org.eclipse.linuxtools.lttng.ui.views.resource.view"); //$NON-NLS-1$ + + makeActions(); + hookContextMenu(); + contributeToActionBars(); + + // Read relevant values + int timeSpaceWidth = tsfviewer.getTimeSpace(); + if (timeSpaceWidth < 0) { + timeSpaceWidth = -timeSpaceWidth; + } + + TmfExperiment experiment = TmfExperiment.getCurrentExperiment(); + if (experiment != null) { + TmfTimeRange experimentTRange = experiment.getTimeRange(); + if (experimentTRange != null) { + long time0 = experimentTRange.getStartTime().getValue(); + long time1 = experimentTRange.getEndTime().getValue(); + ParamsUpdater paramUpdater = getParamsUpdater(); + paramUpdater.update(time0, time1, timeSpaceWidth); + } + // send the initial request and obtained the adjusted time used + TmfTimeRange adjustedTimeRange = initialExperimentDataRequest(this, experimentTRange); + + // initialize widget time boundaries and filtering parameters + ModelUpdateInit(experimentTRange, adjustedTimeRange, this); + } else { + TraceDebug.debug("No selected experiment information available"); + } + } + + private void hookContextMenu() { + MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$ + menuMgr.setRemoveAllWhenShown(true); + menuMgr.addMenuListener(new IMenuListener() { + public void menuAboutToShow(IMenuManager manager) { + ResourcesView.this.fillContextMenu(manager); + } + }); + + Menu menu = menuMgr.createContextMenu(tsfviewer.getControl()); + tsfviewer.getControl().setMenu(menu); + getSite() + .registerContextMenu(menuMgr, tsfviewer.getSelectionProvider()); + } + + private void contributeToActionBars() { + IActionBars bars = getViewSite().getActionBars(); + fillLocalPullDown(bars.getMenuManager()); + fillLocalToolBar(bars.getToolBarManager()); + } + + private void fillLocalPullDown(IMenuManager manager) { + manager.add(new Separator()); + // manager.add(showLegend); + manager.add(new Separator()); + manager.add(resetScale); + manager.add(nextEvent); + manager.add(prevEvent); + manager.add(nextTrace); + manager.add(prevTrace); + // manager.add(filterTraces); + manager.add(zoomIn); + manager.add(zoomOut); + manager.add(zoomFilter); + manager.add(new Separator()); + } + + private void fillContextMenu(IMenuManager manager) { + // manager.add(showLegend); + manager.add(new Separator()); + manager.add(resetScale); + manager.add(nextEvent); + manager.add(prevEvent); + manager.add(nextTrace); + manager.add(prevTrace); + // manager.add(showLegend); + // manager.add(filterTraces); + manager.add(zoomIn); + manager.add(zoomOut); + manager.add(zoomFilter); + manager.add(new Separator()); + manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); + } + + private void fillLocalToolBar(IToolBarManager manager) { + // manager.add(showLegend); + manager.add(new Separator()); + manager.add(resetScale); + manager.add(nextEvent); + manager.add(prevEvent); + manager.add(nextTrace); + manager.add(prevTrace); + // manager.add(filterTraces); + manager.add(zoomIn); + manager.add(zoomOut); + manager.add(zoomFilter); + manager.add(new Separator()); + } + + private void makeActions() { + // action4 + resetScale = new Action() { + @Override + public void run() { + if (tsfviewer != null) { + tsfviewer.resetStartFinishTime(); + } + + } + }; + resetScale.setText(Messages.getString("ResourcesView.Action.Reset")); //$NON-NLS-1$ + resetScale.setToolTipText(Messages + .getString("ResourcesView.Action.Reset.ToolTip")); //$NON-NLS-1$ + resetScale.setImageDescriptor(AbstractUIPlugin + .imageDescriptorFromPlugin(Messages + .getString("ResourcesView.tmf.UI"), + "icons/home_nav.gif")); + + // action5 + nextEvent = new Action() { + @Override + public void run() { + if (tsfviewer != null) { + tsfviewer.selectNextEvent(); + } + } + }; + nextEvent.setText(Messages.getString("ResourcesView.Action.NextEvent")); //$NON-NLS-1$ + nextEvent.setToolTipText(Messages + .getString("ResourcesView.Action.NextEvent.Tooltip")); //$NON-NLS-1$ + nextEvent.setImageDescriptor(AbstractUIPlugin + .imageDescriptorFromPlugin(Messages + .getString("ResourcesView.tmf.UI"), + "icons/next_event.gif")); + + // action6 + prevEvent = new Action() { + @Override + public void run() { + if (tsfviewer != null) { + tsfviewer.selectPrevEvent(); + } + } + }; + prevEvent.setText(Messages.getString("ResourcesView.Action.PrevEvent")); //$NON-NLS-1$ + prevEvent.setToolTipText(Messages + .getString("ResourcesView.Action.PrevEvent.Tooltip")); //$NON-NLS-1$ + prevEvent.setImageDescriptor(AbstractUIPlugin + .imageDescriptorFromPlugin(Messages + .getString("ResourcesView.tmf.UI"), + "icons/prev_event.gif")); + + // action7 + nextTrace = new Action() { + @Override + public void run() { + if (tsfviewer != null) { + tsfviewer.selectNextTrace(); + } + } + }; + nextTrace.setText(Messages + .getString("ResourcesView.Action.NextResource")); //$NON-NLS-1$ + nextTrace.setToolTipText(Messages + .getString("ResourcesView.Action.NextResource.ToolTip")); //$NON-NLS-1$ + nextTrace.setImageDescriptor(AbstractUIPlugin + .imageDescriptorFromPlugin(Messages + .getString("ResourcesView.tmf.UI"), + "icons/next_item.gif")); + + // action8 + prevTrace = new Action() { + @Override + public void run() { + if (tsfviewer != null) { + tsfviewer.selectPrevTrace(); + } + } + }; + prevTrace.setText(Messages + .getString("ResourcesView.Action.PreviousResource")); //$NON-NLS-1$ + prevTrace.setToolTipText(Messages + .getString("ResourcesView.Action.PreviousResource.Tooltip")); //$NON-NLS-1$ + prevTrace.setImageDescriptor(AbstractUIPlugin + .imageDescriptorFromPlugin(Messages + .getString("ResourcesView.tmf.UI"), + "icons/prev_item.gif")); + + // action9 + showLegend = new Action() { + @Override + public void run() { + if (tsfviewer != null) { + tsfviewer.showLegend(); + } + } + }; + showLegend.setText(Messages.getString("ResourcesView.Action.Legend")); //$NON-NLS-1$ + showLegend.setToolTipText(Messages + .getString("ResourcesView.Action.Legend.ToolTip")); //$NON-NLS-1$ + + // action10 + filterTraces = new Action() { + @Override + public void run() { + if (tsfviewer != null) { + tsfviewer.filterTraces(); + } + } + }; + filterTraces.setText(Messages.getString("ResourcesView.Action.Filter")); //$NON-NLS-1$ + filterTraces.setToolTipText(Messages + .getString("ResourcesView.Action.Filter.ToolTip")); //$NON-NLS-1$ + filterTraces.setImageDescriptor(AbstractUIPlugin + .imageDescriptorFromPlugin(Messages + .getString("ResourcesView.tmf.UI"), + "icons/filter_items.gif")); + + // action10 + zoomIn = new Action() { + @Override + public void run() { + if (tsfviewer != null) { + tsfviewer.zoomIn(); + } + } + }; + zoomIn.setText(Messages.getString("ResourcesView.Action.ZoomIn")); //$NON-NLS-1$ + zoomIn.setToolTipText(Messages + .getString("ResourcesView.Action.ZoomIn.Tooltip")); //$NON-NLS-1$ + zoomIn.setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin( + Messages.getString("ResourcesView.tmf.UI"), + "icons/zoomin_nav.gif")); + + // action10 + zoomOut = new Action() { + @Override + public void run() { + if (tsfviewer != null) { + tsfviewer.zoomOut(); + } + } + }; + zoomOut.setText(Messages.getString("ResourcesView.Action.ZoomOut")); //$NON-NLS-1$ + zoomOut.setToolTipText(Messages + .getString("ResourcesView.Action.ZoomOut.tooltip")); //$NON-NLS-1$ + zoomOut.setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin( + Messages.getString("ResourcesView.tmf.UI"), + "icons/zoomout_nav.gif")); + + // zoomFilter + zoomFilter = new Action() { + @Override + public void run() { + // Nothing to do, however the selection status is needed by the + // application + } + }; + + zoomFilter.setText(Messages.getString("ResourcesView.Action.ZoomFilter")); //$NON-NLS-1$ + zoomFilter.setToolTipText(Messages.getString("ResourcesView.Action.ZoomFilter.tooltip")); //$NON-NLS-1$ + zoomFilter.setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(Messages + .getString("ResourcesView.tmf.UI"), "icons/filter_items.gif")); + zoomFilter.setChecked(false); + + // PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_ELCL_SYNCED); + } + + /** + * Passing the focus request to the viewer's control. + */ + @Override + public void setFocus() { + tsfviewer.getControl().setFocus(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView# + * tsfTmProcessSelEvent + * (org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeSelectionEvent + * ) + */ + public void tsfTmProcessSelEvent(TmfTimeSelectionEvent event) { + // common implementation + super.tsfTmProcessSelEvent(event); + } + + /* + * (non-Javadoc) + * + * @seeorg.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis. + * ITmfTimeScaleSelectionListener + * #tsfTmProcessTimeScaleEvent(org.eclipse.linuxtools + * .tmf.ui.viewers.timeAnalysis.TmfTimeScaleSelectionEvent) + */ + public void tsfTmProcessTimeScaleEvent(TmfTimeScaleSelectionEvent event) { + super.tsfTmProcessTimeScaleEvent(event); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView#displayModel + * (org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model. + * ITmfTimeAnalysisEntry[], long, long, boolean, long, long, + * java.lang.Object) + */ + public void displayModel(final ITmfTimeAnalysisEntry[] items, final long startBoundTime, + final long endBoundTime, final boolean updateTimeBounds, final long startVisibleWindow, + final long endVisibleWindow, final Object source) { + + Display display = tsfviewer.getControl().getDisplay(); + display.asyncExec(new Runnable() { + + public void run() { + tsfviewer.display(items, startBoundTime, endBoundTime, updateTimeBounds); + // validate visible boundaries + if (startVisibleWindow > -1 && endVisibleWindow > -1) { + tsfviewer.setSelectVisTimeWindow(startVisibleWindow, endVisibleWindow, source); + } + tsfviewer.resizeControls(); + } + }); + } + + @Override + public void dispose() { + // dispose parent resources + super.dispose(); + + tsfviewer.removeWidgetSelectionListner(this); + tsfviewer.removeWidgetTimeScaleSelectionListner(this); + tsfviewer = null; + } + + /** + * Registers as listener of time selection from other tmf views + * + * @param signal + */ + @TmfSignalHandler + public void synchToTime(TmfTimeSynchSignal signal) { + super.synchToTime(signal); + } + + /** + * Annotation Registers as listener of time range selection from other views + * The implementation handles the entry of the signal. + * + * @param signal + */ + @TmfSignalHandler + public void synchToTimeRange(TmfRangeSynchSignal signal) { + if (zoomFilter != null) { + synchToTimeRange(signal, zoomFilter.isChecked()); + } + } + + @Override + public void modelIncomplete(ILttngSyntEventRequest request) { + // Nothing to do + // The data will be refreshed on the next request + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView# + * getEventProcessor() + */ + @Override + public ITransEventProcessor getEventProcessor() { + return ResourcesEventToHandlerFactory.getInstance(); + } + + /** + * @param signal + */ + @TmfSignalHandler + public void experimentSelected(TmfExperimentSelectedSignal signal) { + if (signal != null) { + TmfTimeRange experimentTRange = signal.getExperiment().getTimeRange(); + + // prepare time intervals in widget + ModelUpdateInit(experimentTRange, experimentTRange, signal.getSource()); + + // request initial data + initialExperimentDataRequest(signal.getSource(), experimentTRange); + } + } + + /** + * @param source + * @param experimentTRange + * @return Adjusted time window used for the request (smaller window to + * initialize view) + */ + private TmfTimeRange initialExperimentDataRequest(Object source, TmfTimeRange experimentTRange) { + // Adjust the initial time window to a shorter interval to allow + // user to select the interesting area based on the perspective + TmfTimeRange initTimeWindow = getInitTRange(experimentTRange); + + dataRequest(initTimeWindow, experimentTRange, true); + if (TraceDebug.isDEBUG()) { + TraceDebug.debug("Initialization request time range is: " + initTimeWindow.getStartTime().toString() + "-" + + initTimeWindow.getEndTime().toString()); + } + + return initTimeWindow; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView# + * getParamsUpdater() + */ + protected ParamsUpdater getParamsUpdater() { + return ResourceModelFactory.getParamsUpdater(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView# + * getItemContainer() + */ + @Override + protected ItemContainer getItemContainer() { + return ResourceModelFactory.getResourceContainer(); + } +} \ No newline at end of file diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/evProcessor/AbsResourcesTRangeUpdate.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/evProcessor/AbsResourcesTRangeUpdate.java new file mode 100644 index 0000000000..fa92ab1dbb --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/evProcessor/AbsResourcesTRangeUpdate.java @@ -0,0 +1,305 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.resources.evProcessor; + +import java.util.Vector; + +import org.eclipse.linuxtools.lttng.event.LttngEvent; +import org.eclipse.linuxtools.lttng.state.evProcessor.ILttngEventProcessor; +import org.eclipse.linuxtools.lttng.state.model.LttngTraceState; +import org.eclipse.linuxtools.lttng.ui.TraceDebug; +import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeComponent; +import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEvent; +import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEvent.Type; +import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEventResource; +import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEventResource.ResourceTypes; +import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeResourceFactory; +import org.eclipse.linuxtools.lttng.ui.views.common.AbsTRangeUpdate; +import org.eclipse.linuxtools.lttng.ui.views.common.ParamsUpdater; +import org.eclipse.linuxtools.lttng.ui.views.resources.model.ResourceContainer; +import org.eclipse.linuxtools.lttng.ui.views.resources.model.ResourceModelFactory; +import org.eclipse.linuxtools.tmf.event.TmfTimeRange; + +public abstract class AbsResourcesTRangeUpdate extends AbsTRangeUpdate + implements ILttngEventProcessor { + + // ======================================================================== + // Data + // ======================================================================= + protected ResourceContainer resContainer = ResourceModelFactory + .getResourceContainer(); + protected ParamsUpdater params = ResourceModelFactory.getParamsUpdater(); + protected static final Long ANY_CPU = 0L; + + // ======================================================================== + // Methods + // ======================================================================= + protected TimeRangeEventResource addLocalResource(long traceStartTime, + long traceEndTime, String traceId, ResourceTypes type, Long resId, + long insertionTime) { + + String resourceName = type.toString() + " " + resId.toString(); + // Note : the "traceid" here is assigned to the "groupname" as we group + // by trace in the UI + TimeRangeEventResource localRessource = TimeRangeResourceFactory + .getInstance().createResource(resContainer.getUniqueId(), + traceStartTime, traceEndTime, resourceName, traceId, + "", type, resId, insertionTime); + resContainer.addItem(localRessource); + return localRessource; + } + + /** + * Used to check if the event is visible within the current visible time + * window + * + * @return + */ + protected boolean withinViewRange(long stime, long etime) { + long windowStartTime = params.getStartTime(); + long windowEndTime = params.getEndTime(); + + if (stime == 13589765052286L) { + TraceDebug.debug("Debug event catched"); + } + + // Start of event is already out of range + if (stime > windowEndTime) { + return false; + } + + // End time within or beyond start of window as long as the start time + // is before the end of the window (condition above) + if (etime >= windowStartTime) { + return true; + } + + // // start time is within window + // if (stime >= windowStartTime && stime <= windowEndTime) { + // // The event or part of it shall be displayed. + // return true; + // } + // + // // end time is within window + // if (etime >= windowStartTime && etime <= windowEndTime) { + // // The event or part of it shall be displayed. + // return true; + // } + + // crosses the window + if (stime <= windowStartTime && etime >= windowEndTime) { + // The time range is bigger than the selected time window and + // crosses it + return true; + } + + return false; + } + + public TimeRangeEventResource resourcelist_obtain_bdev( + LttngTraceState traceState, Long resourceId) { + return resourcelist_obtain_generic(resourceId, ResourceTypes.BDEV, + traceState.getTraceId()); + } + + public TimeRangeEventResource resourcelist_obtain_trap( + LttngTraceState traceState, Long resourceId) { + return resourcelist_obtain_generic(resourceId, ResourceTypes.TRAP, + traceState.getTraceId()); + } + + public TimeRangeEventResource resourcelist_obtain_irq( + LttngTraceState traceState, Long resourceId) { + return resourcelist_obtain_generic(resourceId, ResourceTypes.IRQ, + traceState.getTraceId()); + } + + public TimeRangeEventResource resourcelist_obtain_soft_irq( + LttngTraceState traceState, Long resourceId) { + return resourcelist_obtain_generic(resourceId, ResourceTypes.SOFT_IRQ, + traceState.getTraceId()); + } + + public TimeRangeEventResource resourcelist_obtain_cpu( + LttngTraceState traceState, Long resourceId) { + return resourcelist_obtain_generic(resourceId, ResourceTypes.CPU, + traceState.getTraceId()); + } + + public TimeRangeEventResource resourcelist_obtain_machine( + LttngTraceState traceState, Long resourceId) { + // *** VERIFY *** + // Does "UNKNOWN" make sense for "obtain_machine" ? + // It seems to be the only choice, thought... + return resourcelist_obtain_generic(resourceId, ResourceTypes.UNKNOWN, + traceState.getTraceId()); + } + + public TimeRangeEventResource resourcelist_obtain_generic(Long resourceId, + ResourceTypes resourceType, String traceId) { + return resContainer.findItem(resourceId, resourceType, traceId); + } + + protected boolean globalProcessBeforeExecmode(LttngEvent trcEvent, + LttngTraceState traceSt) { + + // TODO: Implement the tracking of current resource in order ot speed up + // searching for the relevant resource similar to current_hash_data in + // the C implementation + // e.g. + // hashed_process_data = + // process_list->current_hash_data[trace_num][cpu]; + + TimeRangeEventResource localResource = resourcelist_obtain_cpu(traceSt, + trcEvent.getCpuId()); + Long cpu = trcEvent.getCpuId(); + if (localResource == null) { + TmfTimeRange timeRange = traceSt.getContext() + .getTraceTimeWindow(); + localResource = addLocalResource(timeRange.getStartTime() + .getValue(), timeRange.getEndTime().getValue(), traceSt + .getTraceId(), ResourceTypes.CPU, cpu, trcEvent + .getTimestamp().getValue()); + } + + // get the start time + long stime = localResource.getNext_good_time(); + // Get the resource state mode + String cpuStateMode = localResource.getStateMode(traceSt); + // Call the makeDraw function + makeDraw(traceSt, stime, trcEvent.getTimestamp().getValue(), + localResource, params, cpuStateMode); + + return false; + } + + /** + * @param traceSt + * @param startTime + * @param endTime + * @param localResource + * @param params + * @param stateMode + * @return + */ + protected boolean makeDraw(LttngTraceState traceSt, long stime, long etime, + TimeRangeEventResource localResource, + ParamsUpdater params, String stateMode) { + + // Check if the event is out of range + if (!withinViewRange(stime, etime)) { + params.incrementEventsDiscarded(); + return false; + } + + // Check if the time range is consistent. + if (etime < stime) { + params.incrementEventsDiscardedWrongOrder(); + return false; + } + + // Store the next good time to start drawing the next event + // this is done this early to display an accurate start time of the + // first event + // within the display window + // Moved at the end since it produces space gaps among events + // localResource.setNext_good_time(etime); + + // Determine if the time range event will fit it the current + // pixel map + double duration = etime - stime; + double k = getPixelsPerNs(traceSt, params); + double pixels = duration * k; + + // Visibility check + // Display a "more information" indication by allowing non visible event + // as long as its previous event is visible. + boolean visible = true; + if (pixels < 1) { + boolean prevEventVisibility = true; + // Get the visibility indication on previous event for + // this process + Vector inMemEvents = localResource + .getTraceEvents(); + if (inMemEvents.size() != 0) { + TimeRangeComponent prevEvent = inMemEvents.get(inMemEvents + .size() - 1); + prevEventVisibility = prevEvent.isVisible(); + + // if previous event visibility is false and the time span + // between events less than two pixels, there is no need to + // load it in memory i.e. not visible and a more indicator is + // within two pixels. + // return i.e. event discarded to free up memory + Long eventSpan = stime - prevEvent.getStartTime(); + if (prevEventVisibility == false + && ((double) eventSpan * k) < 2) { + params.incrementEventsDiscarded(); + return false; + } + } + + // if previous event is visible, set this one to not + // visible and continue + visible = false; + } + + Type eventType = getEventType(localResource); + if (eventType != null) { + TimeRangeEvent time_window = new TimeRangeEvent(stime, etime, + localResource, eventType, stateMode); + + time_window.setVisible(visible); + localResource.addChildren(time_window); + + localResource.setNext_good_time(etime); + } + + return false; + } + + /** + * Convert between resource type and timeRange event type + * + * @param resource + * @return + */ + private Type getEventType(TimeRangeEventResource resource) { + // TODO: Can we merge into one type + ResourceTypes resType = resource.getType(); + Type eventType = null; + + switch (resType) { + case CPU: + eventType = Type.CPU_MODE; + break; + case IRQ: + eventType = Type.IRQ_MODE; + break; + case SOFT_IRQ: + eventType = Type.SOFT_IRQ_MODE; + break; + case TRAP: + eventType = Type.TRAP_MODE; + break; + case BDEV: + eventType = Type.BDEV_MODE; + break; + default: + eventType = Type.PROCESS_MODE; + break; + } + + return eventType; + } + +} \ No newline at end of file diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/evProcessor/ResourcesAfterUpdateHandlers.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/evProcessor/ResourcesAfterUpdateHandlers.java new file mode 100644 index 0000000000..11aad14728 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/evProcessor/ResourcesAfterUpdateHandlers.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.resources.evProcessor; + +import org.eclipse.linuxtools.lttng.event.LttngEvent; +import org.eclipse.linuxtools.lttng.state.evProcessor.ILttngEventProcessor; +import org.eclipse.linuxtools.lttng.state.model.LttngTraceState; + +/** + * Creates instances of specific after state update handlers, per corresponding + * event. + * + * @author alvaro + * + */ +public class ResourcesAfterUpdateHandlers { + + /** + *

+ * Handles: LTT_EVENT_SCHED_SCHEDULE + *

+ * Replace C function named "after_schedchange_hook" in eventhooks.c + *

+ * Fields: LTT_FIELD_PREV_PID, LTT_FIELD_NEXT_PID, LTT_FIELD_PREV_STATE + *

+ * + * @return + */ + final ILttngEventProcessor getAfterSchedChangeHandler() { + AbsResourcesTRangeUpdate handler = new AbsResourcesTRangeUpdate() { + + public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { + + // TODO: After sched scheduler handler should implement an + // update to the current resource data, similar to + // current_hash_data in C + // We don't keep track of current hashed resource, we look in + // the hash table every time. keeping track of current hash may + // improve performance, although needs to be bench marked to + // verify + // if there's is a real gain. + + // process_list->current_hash_data[trace_num][process_in->cpu] = + // hashed_process_data_in; + + return false; + } + }; + + return handler; + } + + /** + * Drawing stuff ? + */ + // int after_request(void *hook_data, void *call_data) + // int after_chunk(void *hook_data, void *call_data) + // int before_statedump_end(void *hook_data, void *call_data) +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/evProcessor/ResourcesBeforeUpdateHandlers.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/evProcessor/ResourcesBeforeUpdateHandlers.java new file mode 100644 index 0000000000..ff562de22b --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/evProcessor/ResourcesBeforeUpdateHandlers.java @@ -0,0 +1,374 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.resources.evProcessor; + +import org.eclipse.linuxtools.lttng.event.LttngEvent; +import org.eclipse.linuxtools.lttng.state.StateStrings.Channels; +import org.eclipse.linuxtools.lttng.state.StateStrings.Events; +import org.eclipse.linuxtools.lttng.state.StateStrings.Fields; +import org.eclipse.linuxtools.lttng.state.evProcessor.ILttngEventProcessor; +import org.eclipse.linuxtools.lttng.state.model.LttngTraceState; +import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEventResource; +import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEventResource.ResourceTypes; +import org.eclipse.linuxtools.tmf.event.TmfTimeRange; + +/** + * Creates instances of specific before state update handlers, per corresponding + * event. + * + * @author alvaro + * + */ +public class ResourcesBeforeUpdateHandlers { + + /** + *

+ * Handles: LTT_EVENT_SCHED_SCHEDULE + *

+ * Replace C function named "before_schedchange_hook" in eventhooks.c + *

+ * Fields: LTT_FIELD_PREV_PID, LTT_FIELD_NEXT_PID(?), LTT_FIELD_PREV_STATE + * (?) + *

+ * + * @return + */ + final ILttngEventProcessor getBeforeSchedChangeHandler() { + AbsResourcesTRangeUpdate handler = new AbsResourcesTRangeUpdate() { + + // @Override + public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { + // Create a time range for the cpu. + globalProcessBeforeExecmode(trcEvent, traceSt); + + return false; + } + }; + + return handler; + } + + /** + *

+ * Handles: LTT_EVENT_IRQ_ENTRY, LTT_EVENT_IRQ_EXIT + *

+ * Replace C function named "before_execmode_hook_irq" in eventhooks.c + * + * @return + */ + final ILttngEventProcessor getBeforeExecutionModeIrq() { + AbsResourcesTRangeUpdate handler = new AbsResourcesTRangeUpdate() { + + // @Override + public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { + + Long irqId = null; + + // According to Ltt, we should not draw anything if the channel + // is the kernel one + if (trcEvent.getChannelName().equals( + Channels.LTT_CHANNEL_KERNEL)) { + return false; + } else { + + if (trcEvent.getMarkerName().equals( + Events.LTT_EVENT_IRQ_ENTRY.getInName())) { + irqId = getAFieldLong(trcEvent, traceSt, + Fields.LTT_FIELD_IRQ_ID); + } else if (trcEvent.getMarkerName().equals( + Events.LTT_EVENT_IRQ_EXIT.getInName())) { + long cpu = trcEvent.getCpuId(); + irqId = traceSt.getCpu_states().get(cpu) + .peekFromIrqStack(); + if (irqId.equals(-1L)) { + // nothing to update + return false; + } + } + + + // softIrqId is the resource id here + TimeRangeEventResource localResource = resourcelist_obtain_irq( + traceSt, irqId); + + // If the resource is missing in the list, add it + if (localResource == null) { + TmfTimeRange timeRange = traceSt.getContext() + .getTraceTimeWindow(); + localResource = addLocalResource(timeRange + .getStartTime().getValue(), timeRange + .getEndTime().getValue(), traceSt.getTraceId(), + ResourceTypes.IRQ, irqId, trcEvent + .getTimestamp().getValue()); + } + + // get the start time + long stime = localResource.getNext_good_time(); + + // Get the resource state mode + String irqStateMode = localResource.getStateMode(traceSt); + + // Call the makeDraw function + makeDraw(traceSt, stime, + trcEvent.getTimestamp().getValue(), localResource, + params, irqStateMode); + + // Call the globalProcessBeforeExecmode() after, as + // it is needed by all + // getBeforeExecmode*SOMETHING*() + globalProcessBeforeExecmode(trcEvent, traceSt); + } + return false; + } + }; + + return handler; + } + + /** + *

+ * Handles: LTT_EVENT_SOFT_IRQ_RAISE, LTT_EVENT_SOFT_IRQ_ENTRY, + * LTT_EVENT_SOFT_IRQ_EXIT, + *

+ * Replace C function named "before_execmode_hook_soft_irq" in eventhooks.c + *

+ * Fields: LTT_FIELD_SOFT_IRQ_ID + *

+ * + * @return + */ + final ILttngEventProcessor getBeforeExecutionModeSoftIrq() { + AbsResourcesTRangeUpdate handler = new AbsResourcesTRangeUpdate() { + + // @Override + public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { + + Long softIrqId = null; + + // According to Ltt, we should not draw anything if the channel + // is the kernel one + if (trcEvent.getChannelName().equals( + Channels.LTT_CHANNEL_KERNEL)) { + return false; + } else { + + if ((trcEvent.getMarkerName() + .equals(Events.LTT_EVENT_SOFT_IRQ_RAISE.getInName())) + || (trcEvent.getMarkerName() + .equals(Events.LTT_EVENT_SOFT_IRQ_ENTRY + .getInName()))) { + softIrqId = getAFieldLong(trcEvent, traceSt, + Fields.LTT_FIELD_SOFT_IRQ_ID); + } else if (trcEvent.getMarkerName().equals( + Events.LTT_EVENT_SOFT_IRQ_EXIT.getInName())) { + long cpu = trcEvent.getCpuId(); + softIrqId = traceSt.getCpu_states().get(cpu) + .peekFromSoftIrqStack(); + if (softIrqId < 0) { + // nothing to update + return false; + } + } + + // Add the resource to the resource list + // softIrqId is the resource id here + TimeRangeEventResource localResource = resourcelist_obtain_soft_irq( + traceSt, softIrqId); + + // If the resource is missing in the list, add it + if (localResource == null) { + TmfTimeRange timeRange = traceSt.getContext() + .getTraceTimeWindow(); + localResource = addLocalResource(timeRange + .getStartTime().getValue(), timeRange + .getEndTime().getValue(), traceSt.getTraceId(), + ResourceTypes.SOFT_IRQ, softIrqId, trcEvent + .getTimestamp().getValue()); + } + + // get the start time + long stime = localResource.getNext_good_time(); + + // Get the resource state mode + String softIrqStateMode = localResource + .getStateMode(traceSt); + + // Call the makeDraw function + makeDraw(traceSt, stime, + trcEvent.getTimestamp().getValue(), localResource, + params, softIrqStateMode); + + // Call the globalProcessBeforeExecmode() after, as + // it is needed by all + // getBeforeExecmode*SOMETHING*() + globalProcessBeforeExecmode(trcEvent, traceSt); + + } + + return false; + } + }; + + return handler; + } + + /** + *

+ * Handles: LTT_EVENT_TRAP_ENTRY, LTT_EVENT_TRAP_EXIT, + * LTT_EVENT_PAGE_FAULT_ENTRY, LTT_EVENT_PAGE_FAULT_EXIT, + * LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY, LTT_EVENT_PAGE_FAULT_NOSEM_EXIT + *

+ * Replace C function named "before_execmode_hook_trap" in eventhooks.c + *

+ * Fields: LTT_FIELD_TRAP_ID + *

+ * + * @return + */ + final ILttngEventProcessor getBeforeExecutionModeTrap() { + AbsResourcesTRangeUpdate handler = new AbsResourcesTRangeUpdate() { + + // @Override + public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { + + Long trapId = null; + + // According to Ltt, we should not draw anything if the channel + // is the kernel one + if (trcEvent.getChannelName().equals( + Channels.LTT_CHANNEL_KERNEL)) { + return false; + } else { + + if ((trcEvent.getMarkerName() + .equals(Events.LTT_EVENT_TRAP_ENTRY.getInName())) + || (trcEvent.getMarkerName() + .equals(Events.LTT_EVENT_PAGE_FAULT_ENTRY + .getInName())) + || (trcEvent.getMarkerName() + .equals(Events.LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY + .getInName()))) { + trapId = getAFieldLong(trcEvent, traceSt, + Fields.LTT_FIELD_TRAP_ID); + } else if ((trcEvent.getMarkerName() + .equals(Events.LTT_EVENT_TRAP_EXIT.getInName())) + || (trcEvent.getMarkerName() + .equals(Events.LTT_EVENT_PAGE_FAULT_EXIT + .getInName())) + || (trcEvent.getMarkerName() + .equals(Events.LTT_EVENT_PAGE_FAULT_NOSEM_EXIT + .getInName()))) { + long cpu = trcEvent.getCpuId(); + trapId = traceSt.getCpu_states().get(cpu) + .peekFromTrapStack(); + + if (trapId.equals(-1L)) { + // Nothing to update + return false; + } + } else { + return false; + } + + // Add the resource to the resource list + // trapId is the resource id here + TimeRangeEventResource localResource = resourcelist_obtain_trap( + traceSt, trapId); + + // If the resource is missing in the list, add it + if (localResource == null) { + TmfTimeRange timeRange = traceSt.getContext() + .getTraceTimeWindow(); + localResource = addLocalResource(timeRange + .getStartTime().getValue(), timeRange + .getEndTime().getValue(), traceSt.getTraceId(), + ResourceTypes.TRAP, trapId, trcEvent + .getTimestamp().getValue()); + } + + // Determine the trap state. + String trapStateMode = localResource.getStateMode(traceSt); + + long stime = localResource.getNext_good_time(); + makeDraw(traceSt, stime, + trcEvent.getTimestamp().getValue(), localResource, + params, trapStateMode); + + // Call the globalProcessBeforeExecmode() after, as + // it is needed by all + // getBeforeExecmode*SOMETHING*() + globalProcessBeforeExecmode(trcEvent, traceSt); + + } + + return false; + } + }; + + return handler; + } + + /** + *

+ * Handles: LTT_EVENT_REQUEST_ISSUE, LTT_EVENT_REQUEST_COMPLETE + *

+ * Replace C function named "before_bdev_event_hook" in eventhooks.c + *

+ * Fields: LTT_FIELD_MAJOR, LTT_FIELD_MINOR, LTT_FIELD_OPERATION (?) + *

+ * + * @return + */ + final ILttngEventProcessor getBeforeBdevEvent() { + AbsResourcesTRangeUpdate handler = new AbsResourcesTRangeUpdate() { + + // @Override + public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { + Long major = getAFieldLong(trcEvent, traceSt, + Fields.LTT_FIELD_MAJOR); + Long minor = getAFieldLong(trcEvent, traceSt, + Fields.LTT_FIELD_MINOR); + // This is useless even in LTTv! + // Long oper = getAFieldLong(trcEvent, traceSt, + // Fields.LTT_FIELD_OPERATION); + + Long bdevId = getMkdevId(major, minor); + + // According to Lttv, bdevId (obtain from MKDEV macro) is + // the id here + TimeRangeEventResource localResource = resourcelist_obtain_bdev( + traceSt, bdevId); + + if (localResource == null) { + TmfTimeRange timeRange = traceSt.getContext() + .getTraceTimeWindow(); + localResource = addLocalResource(timeRange.getStartTime() + .getValue(), timeRange.getEndTime().getValue(), + traceSt.getTraceId(), ResourceTypes.BDEV, bdevId, + trcEvent.getTimestamp().getValue()); + } + + // get the start time + long stime = localResource.getNext_good_time(); + // Get the resource state mode + String bdevStateMode = localResource.getStateMode(traceSt); + // Call the makeDraw function + makeDraw(traceSt, stime, trcEvent.getTimestamp().getValue(), + localResource, params, bdevStateMode); + + return false; + } + }; + + return handler; + } +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/evProcessor/ResourcesEventToHandlerFactory.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/evProcessor/ResourcesEventToHandlerFactory.java new file mode 100644 index 0000000000..234435cffd --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/evProcessor/ResourcesEventToHandlerFactory.java @@ -0,0 +1,164 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.resources.evProcessor; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.linuxtools.lttng.event.LttngEvent; +import org.eclipse.linuxtools.lttng.event.LttngSyntheticEvent; +import org.eclipse.linuxtools.lttng.event.LttngSyntheticEvent.SequenceInd; +import org.eclipse.linuxtools.lttng.state.StateStrings; +import org.eclipse.linuxtools.lttng.state.evProcessor.AbsEventToHandlerResolver; +import org.eclipse.linuxtools.lttng.state.evProcessor.ILttngEventProcessor; +import org.eclipse.linuxtools.lttng.state.model.LttngTraceState; + +/** + * Builds a Map from string event name to a processing handler object, the + * processors implement the same interface to facilitate transparent methods + * call, + * + * The map key String is the entry point of the raw events. Using a hash speeds + * up the resolution of the appropriate processor + * + * @author alvaro + * + */ +public class ResourcesEventToHandlerFactory extends AbsEventToHandlerResolver { + // ======================================================================== + // Data + // ======================================================================= + private final Map eventNametoBeforeProcessor = new HashMap(); + private final Map eventNametoAfterProcessor = new HashMap(); + private ResourcesFinishUpdateHandler finishProcessor = null; + private static ResourcesEventToHandlerFactory instance = null; + private ResourcesBeforeUpdateHandlers instantiateBeforeHandler = new ResourcesBeforeUpdateHandlers(); + private ResourcesAfterUpdateHandlers instantiateAfterHandler = new ResourcesAfterUpdateHandlers(); + + private ResourcesEventToHandlerFactory() { + super(); + // Create one instance of each individual event handler and add the + // instance to the map + + // *** BEFORE HOOKS *** + eventNametoBeforeProcessor.put( + StateStrings.Events.LTT_EVENT_SCHED_SCHEDULE.getInName(), + instantiateBeforeHandler.getBeforeSchedChangeHandler()); + + eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_TRAP_ENTRY + .getInName(), instantiateBeforeHandler + .getBeforeExecutionModeTrap()); + eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_TRAP_EXIT + .getInName(), instantiateBeforeHandler + .getBeforeExecutionModeTrap()); + eventNametoBeforeProcessor.put( + StateStrings.Events.LTT_EVENT_PAGE_FAULT_ENTRY.getInName(), + instantiateBeforeHandler.getBeforeExecutionModeTrap()); + eventNametoBeforeProcessor.put( + StateStrings.Events.LTT_EVENT_PAGE_FAULT_EXIT.getInName(), + instantiateBeforeHandler.getBeforeExecutionModeTrap()); + eventNametoBeforeProcessor.put( + StateStrings.Events.LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY + .getInName(), instantiateBeforeHandler + .getBeforeExecutionModeTrap()); + eventNametoBeforeProcessor + .put(StateStrings.Events.LTT_EVENT_PAGE_FAULT_NOSEM_EXIT + .getInName(), instantiateBeforeHandler + .getBeforeExecutionModeTrap()); + + eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_IRQ_ENTRY + .getInName(), instantiateBeforeHandler + .getBeforeExecutionModeIrq()); + eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_IRQ_EXIT + .getInName(), instantiateBeforeHandler + .getBeforeExecutionModeIrq()); + + eventNametoBeforeProcessor.put( + StateStrings.Events.LTT_EVENT_SOFT_IRQ_RAISE.getInName(), + instantiateBeforeHandler.getBeforeExecutionModeSoftIrq()); + eventNametoBeforeProcessor.put( + StateStrings.Events.LTT_EVENT_SOFT_IRQ_ENTRY.getInName(), + instantiateBeforeHandler.getBeforeExecutionModeSoftIrq()); + eventNametoBeforeProcessor.put( + StateStrings.Events.LTT_EVENT_SOFT_IRQ_EXIT.getInName(), + instantiateBeforeHandler.getBeforeExecutionModeSoftIrq()); + + eventNametoBeforeProcessor.put( + StateStrings.Events.LTT_EVENT_REQUEST_ISSUE.getInName(), + instantiateBeforeHandler.getBeforeBdevEvent()); + eventNametoBeforeProcessor.put( + StateStrings.Events.LTT_EVENT_REQUEST_COMPLETE.getInName(), + instantiateBeforeHandler.getBeforeBdevEvent()); + + // *** AFTER HOOKS *** + eventNametoAfterProcessor.put( + StateStrings.Events.LTT_EVENT_SCHED_SCHEDULE.getInName(), + instantiateAfterHandler.getAfterSchedChangeHandler()); + + finishProcessor = new ResourcesFinishUpdateHandler(); + } + + /** + * + */ + public static AbsEventToHandlerResolver getInstance() { + if (instance == null) { + instance = new ResourcesEventToHandlerFactory(); + } + return instance; + } + + @Override + public ILttngEventProcessor getAfterProcessor(String eventType) { + return eventNametoAfterProcessor.get(eventType); + } + + @Override + public ILttngEventProcessor getBeforeProcessor(String eventType) { + return eventNametoBeforeProcessor.get(eventType); + } + + @Override + public ILttngEventProcessor getfinishProcessor() { + return finishProcessor; + } + + public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { + if (trcEvent instanceof LttngSyntheticEvent) { + + LttngSyntheticEvent synEvent = (LttngSyntheticEvent) trcEvent; + String eventType = synEvent.getMarkerName(); + ILttngEventProcessor processor = null; + if (synEvent.getSynType() == SequenceInd.BEFORE) { + processor = getBeforeProcessor(eventType); + } + + if (synEvent.getSynType() == SequenceInd.AFTER) { + processor = getAfterProcessor(eventType); + } + + if (synEvent.getSynType() == SequenceInd.ENDREQ) { + processor = getfinishProcessor(); + } + + if (processor != null) { + processor.process(trcEvent, traceSt); + } + } + return false; + } + + @Override + public ILttngEventProcessor getStateUpdaterProcessor(String eventType) { + return null; + } +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/evProcessor/ResourcesFinishUpdateHandler.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/evProcessor/ResourcesFinishUpdateHandler.java new file mode 100644 index 0000000000..76743e60c8 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/evProcessor/ResourcesFinishUpdateHandler.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.resources.evProcessor; + +import org.eclipse.linuxtools.lttng.event.LttngEvent; +import org.eclipse.linuxtools.lttng.state.StateStrings.Events; +import org.eclipse.linuxtools.lttng.state.evProcessor.ILttngEventProcessor; +import org.eclipse.linuxtools.lttng.state.model.LttngTraceState; +import org.eclipse.linuxtools.lttng.ui.TraceDebug; +import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEventResource; +import org.eclipse.linuxtools.tmf.event.TmfTimestamp; + +/** + * Creates specific finish state data request + * + * @author alvaro + * + */ +public class ResourcesFinishUpdateHandler extends + AbsResourcesTRangeUpdate + implements ILttngEventProcessor { + + public Events getEventHandleType() { + // No specific event + return null; + } + + public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) { + // Draw a last known state to the end of the trace + TmfTimestamp endReqTime = traceSt.getContext() + .getTraceTimeWindow().getEndTime(); + + TraceDebug.debug("Number of localResources: " + + resContainer.readItems().length); + + // for each existing resource + for (TimeRangeEventResource localResource : resContainer + .readItems()) { + + // get the start time + long stime = localResource.getNext_good_time(); + + // Get the resource state mode + String stateMode = localResource.getStateMode(traceSt); + + // Insert an instance from previous time to end request time with + // the current state + makeDraw(traceSt, stime, endReqTime.getValue(), + localResource, params, stateMode); + } + + return false; + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/messages.properties b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/messages.properties new file mode 100644 index 0000000000..032d20a3ef --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/messages.properties @@ -0,0 +1,26 @@ +ResourcesView.Action.Filter=Filter +ResourcesView.Action.Filter.ToolTip=Resource Filter options +ResourcesView.Action.Legend=Legend +ResourcesView.Action.Legend.ToolTip=Show Legend +ResourcesView.Action.LoadData=LoadData +ResourcesView.Action.LoadData.ToolTip=Load data from external plug-in +ResourcesView.Action.NextEvent=NextEv +ResourcesView.Action.NextEvent.Tooltip=Next Event +ResourcesView.Action.NextResource=NextResource +ResourcesView.Action.NextResource.ToolTip=Select Next Resource +ResourcesView.Action.PrevEvent=PrevEv +ResourcesView.Action.PrevEvent.Tooltip=Previous Event +ResourcesView.Action.PreviousResource=PreviousResource +ResourcesView.Action.PreviousResource.Tooltip=Select Previous Resource +ResourcesView.Action.Reset=Reset +ResourcesView.Action.Reset.ToolTip=Reset the Time Scale to Default +ResourcesView.Action.Synchronize=Synchronise +ResourcesView.Action.Synchronize.ToolTip=Synchronise by listening to external API selection calls +ResourcesView.Action.ZoomIn=Zoom In +ResourcesView.Action.ZoomIn.Tooltip=Zoom In +ResourcesView.Action.ZoomOut=Zoom Out +ResourcesView.Action.ZoomOut.tooltip=Zoom Out +ResourcesView.Action.ZoomFilter=Zoom Filter +ResourcesView.Action.ZoomFilter.tooltip=Display elements with events within the zoomed time window +ResourcesView.msgSlogan=Resources View +ResourcesView.tmf.UI=org.eclipse.linuxtools.tmf.ui diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/model/ResourceContainer.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/model/ResourceContainer.java new file mode 100644 index 0000000000..472876444a --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/model/ResourceContainer.java @@ -0,0 +1,230 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.resources.model; + +import java.util.HashMap; +import java.util.Iterator; + +import org.eclipse.linuxtools.lttng.TraceDebug; +import org.eclipse.linuxtools.lttng.ui.model.trange.ItemContainer; +import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEventResource; +import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEventResource.ResourceTypes; + +/** + * Common location to allocate the resources in use by the resource view + * + * @author alvaro + * + */ +public class ResourceContainer implements ItemContainer { + // ======================================================================== + // Data + // ======================================================================== + private final HashMap resources = new HashMap(); + private static Integer uniqueId = 0; + + + // ======================================================================== + // Constructor + // ======================================================================== + /** + * Package level constructor + */ + public ResourceContainer() { } + + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.linuxtools.lttng.ui.views.resources.model.ItemContainer#addItem + * (org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model. + * ITmfTimeAnalysisEntry) + */ + public void addItem(TimeRangeEventResource newItem) { + if (newItem != null) { + resources.put( new ResourceKey(newItem),newItem); + } + } + + // ======================================================================== + // Methods + // ======================================================================== + /* (non-Javadoc) + * @see org.eclipse.linuxtools.lttng.ui.views.resources.model.ItemContainer#getUniqueId() + */ + public Integer getUniqueId() { + return uniqueId++; + } + + /* (non-Javadoc) + * @see org.eclipse.linuxtools.lttng.ui.views.resources.model.ItemContainer#readItems() + */ + public TimeRangeEventResource[] readItems() { + return resources.values().toArray( + new TimeRangeEventResource[resources.size()]); + } + + /* (non-Javadoc) + * @see org.eclipse.linuxtools.lttng.ui.views.resources.model.ItemContainer#clearChildren() + */ + public void clearChildren() { + TimeRangeEventResource newRes = null; + Iterator iterator = resources.keySet().iterator(); + + while (iterator.hasNext()) { + newRes = resources.get(iterator.next()); + newRes.reset(); + } + } + + /* (non-Javadoc) + * @see org.eclipse.linuxtools.lttng.ui.views.resources.model.ItemContainer#clearItems() + */ + public void clearItems() { + resources.clear(); + } + + /* (non-Javadoc) + * @see org.eclipse.linuxtools.lttng.ui.views.resources.model.ItemContainer#removeItems(java.lang.String) + */ + public void removeItems(String traceId) { + ResourceKey newKey = null; + + Iterator iterator = resources.keySet().iterator(); + while (iterator.hasNext()) { + newKey = iterator.next(); + + if (resources.get(newKey).getTraceId().equals(traceId)) { + resources.remove(newKey); + } + } + } + + + /** + * Search by keys (resourceId, traceId and type) + *

+ * + * A match is returned if the three arguments received match an entry + * Otherwise null is returned + * + * @param searchedId + * The ressourceId we are looking for + * @param searchedType + * The ressourceType we are looking for + * @param searchedTraceId + * The traceId (trace name?) we are looking for + * + * @return TimeRangeEventResource + */ + public TimeRangeEventResource findItem(Long searchedId, ResourceTypes searchedType, String searchedTraceId) { + // Get the EventResource associated to a key we create here + TimeRangeEventResource foundResource = resources.get( new ResourceKey(searchedId, searchedTraceId, searchedType) ); + + return foundResource; + } +} + +class ResourceKey { + + private TimeRangeEventResource valueRef = null; + + private Long resourceId = null; + private String traceId = null; + private ResourceTypes type = null; + + @SuppressWarnings("unused") + private ResourceKey() { } + + public ResourceKey(TimeRangeEventResource newRef) { + valueRef = newRef; + } + + public ResourceKey(Long newId, String newTraceId, ResourceTypes newType) { + resourceId = newId; + traceId = newTraceId; + type = newType; + } + + @Override + public boolean equals(Object obj) { + boolean isSame = false; + + if ( obj instanceof ResourceKey ) { + if ( valueRef != null ) { + if ( ( ((ResourceKey)obj).getResourceId().equals(valueRef.getResourceId()) ) && + ( ((ResourceKey)obj).getTraceId().equals(valueRef.getTraceId()) ) && + ( ((ResourceKey)obj).getType().equals(valueRef.getType()) ) ) + { + isSame = true; + } + } + else { + if ( ( ((ResourceKey)obj).getResourceId().equals(this.resourceId)) && + ( ((ResourceKey)obj).getTraceId().equals(this.traceId)) && + ( ((ResourceKey)obj).getType().equals(this.type)) ) + { + isSame = true; + } + } + } + else { + TraceDebug.debug("ERROR : The given key is not of the type ProcessKey!" + obj.getClass().toString()); + } + + return isSame; + } + + // *** WARNING : Everything in there work because the check "valueRef != null" is the same for ALL getter + // Do NOT change this check without checking. + public Long getResourceId() { + if ( valueRef != null ) { + return valueRef.getResourceId(); + } + else { + return resourceId; + } + } + + public String getTraceId() { + if ( valueRef != null ) { + return valueRef.getTraceId(); + } + else { + return traceId; + } + } + + public ResourceTypes getType() { + if ( valueRef != null ) { + return valueRef.getType(); + } + else { + return type; + } + } + + @Override + public int hashCode() { + return this.toString().hashCode(); + } + + + @Override + public String toString() { + if ( valueRef != null ) { + return (valueRef.getResourceId().toString() + ":" + valueRef.getTraceId().toString() + ":" + valueRef.getType().toString()); + } + return (resourceId + ":" + traceId + ":" + type); + } +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/model/ResourceModelFactory.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/model/ResourceModelFactory.java new file mode 100644 index 0000000000..496f669006 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/resources/model/ResourceModelFactory.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.resources.model; + +import org.eclipse.linuxtools.lttng.ui.views.common.ParamsUpdater; + +/** + * Instantiates the entry point classes to build the data model for this view + * + * @author alvaro + * + */ +public class ResourceModelFactory { + // ======================================================================== + // Data + // ======================================================================== + private static ResourceContainer resContainer = null; + private static ParamsUpdater updater = null; + + + // ======================================================================== + // Methods + // ======================================================================== + /** + * Get Process data container + * @return + */ + public static ResourceContainer getResourceContainer() { + if (resContainer == null) { + resContainer = new ResourceContainer(); + } + return resContainer; + } + + + public static ParamsUpdater getParamsUpdater() { + if (updater == null) { + updater = new ParamsUpdater(); + } + return updater; + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/StatisticsView.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/StatisticsView.java new file mode 100644 index 0000000000..ccce8ea741 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/StatisticsView.java @@ -0,0 +1,655 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Yann N. Dauphin (dhaemon@gmail.com) - Implementation + * Francois Chouinard (fchouinard@gmail.com) - Initial API + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.statistics; + +import java.text.DecimalFormat; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.TreeViewerColumn; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerComparator; +import org.eclipse.linuxtools.lttng.request.ILttngSyntEventRequest; +import org.eclipse.linuxtools.lttng.state.evProcessor.AbsEventToHandlerResolver; +import org.eclipse.linuxtools.lttng.ui.TraceDebug; +import org.eclipse.linuxtools.lttng.ui.model.trange.ItemContainer; +import org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView; +import org.eclipse.linuxtools.lttng.ui.views.common.ParamsUpdater; +import org.eclipse.linuxtools.lttng.ui.views.statistics.evProcessor.StatsTimeCountHandlerFactory; +import org.eclipse.linuxtools.lttng.ui.views.statistics.model.StatisticsTreeNode; +import org.eclipse.linuxtools.lttng.ui.views.statistics.model.StatisticsTreeRootFactory; +import org.eclipse.linuxtools.tmf.event.TmfEvent; +import org.eclipse.linuxtools.tmf.event.TmfTimeRange; +import org.eclipse.linuxtools.tmf.experiment.TmfExperiment; +import org.eclipse.linuxtools.tmf.signal.TmfExperimentSelectedSignal; +import org.eclipse.linuxtools.tmf.signal.TmfSignalHandler; +import org.eclipse.linuxtools.tmf.trace.ITmfTrace; +import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITmfTimeAnalysisEntry; +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.Cursor; +import org.eclipse.swt.graphics.Image; +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.Listener; +import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.PlatformUI; + +/** + * StatisticsView + *

+ * The Statistics View displays statistics for traces. + * + * It is implemented according to the MVC pattern. - The model is a + * StatisticsTreeNode built by the State Manager. - The view is built with a + * TreeViewer. - The controller that keeps model and view synchronised is an + * observer of the model. + */ +public class StatisticsView extends AbsTimeUpdateView { + public static final String ID = "org.eclipse.linuxtools.lttng.ui.views.statistics"; + private TreeViewer treeViewer; + + // Table column names + private final String LEVEL_COLUMN = "Level"; + private final String EVENTS_COUNT_COLUMN = "Number of Events"; + private final String CPU_TIME_COLUMN = "CPU Time"; + private final String CUMULATIVE_CPU_TIME_COLUMN = "Cumulative CPU Time"; + private final String ELAPSED_TIME_COLUMN = "Elapsed Time"; + + // Table column tooltips + private final String LEVEL_COLUMN_TIP = "Level at which statistics apply."; + private final String EVENTS_COUNT_COLUMN_TIP = "Total amount of events that are tied to given resource."; + private final String CPU_TIME_COLUMN_TIP = "Total amount of time the CPU was used excluding wait times(I/O, etc.) at that level."; + private final String CUMULATIVE_CPU_TIME_COLUMN_TIP = "Total amount of time between the first and last event excluding wait times in a level."; + private final String ELAPSED_TIME_COLUMN_TIP = "Total amount of time the CPU was used including wait times(I/O, etc.) at that level."; + + // Level for which statistics should not be displayed. + private Set folderLevels = new HashSet(Arrays + .asList(new String[] { "Event Types", "Modes", "Submodes", "CPUs", + "Processes", "Functions" })); + + // Levels for which sub-levels should not contain time-related statistics. + private Set levelsWithEmptyTime = new HashSet(Arrays + .asList(new String[] { "Event Types" })); + + private DecimalFormat decimalFormat = new DecimalFormat("0.#########"); + private Cursor fwaitCursor = null; + + // Used to draw bar charts in columns. + private interface ColumnPercentageProvider { + public double getPercentage(StatisticsTreeNode node); + } + + /** + * Contains all the information necessary to build a column of the table. + */ + private class ColumnData { + // Name of the column. + public final String header; + // Width of the column. + public final int width; + // Alignment of the column. + public final int alignment; + // Tooltip of the column. + public final String tooltip; + // Adapts a StatisticsTreeNode into the content of it's corresponding + // cell for that column. + public final ColumnLabelProvider labelProvider; + // Used to sort elements of this column. Can be null. + public final ViewerComparator comparator; + // Used to draw bar charts in this column. Can be null. + public final ColumnPercentageProvider percentageProvider; + + public ColumnData(String h, int w, int a, String t, + ColumnLabelProvider l, ViewerComparator c, + ColumnPercentageProvider p) { + header = h; + width = w; + alignment = a; + tooltip = t; + labelProvider = l; + comparator = c; + percentageProvider = p; + } + }; + + // List that will be used to create the table. + private ColumnData[] columnDataList = new ColumnData[] { + new ColumnData(LEVEL_COLUMN, 200, SWT.LEFT, LEVEL_COLUMN_TIP, + new ColumnLabelProvider() { + @Override + public String getText(Object element) { + return ((StatisticsTreeNode) element).getKey(); + } + + @Override + public Image getImage(Object element) { + StatisticsTreeNode node = (StatisticsTreeNode) element; + if (folderLevels.contains(node.getKey())) { + return PlatformUI.getWorkbench() + .getSharedImages().getImage( + ISharedImages.IMG_OBJ_FOLDER); + } else { + return PlatformUI.getWorkbench() + .getSharedImages().getImage( + ISharedImages.IMG_OBJ_ELEMENT); + } + } + }, new ViewerComparator() { + @Override + public int compare(Viewer viewer, Object e1, Object e2) { + StatisticsTreeNode n1 = (StatisticsTreeNode) e1; + StatisticsTreeNode n2 = (StatisticsTreeNode) e2; + + return n1.getKey().compareTo(n2.getKey()); + } + }, null), + new ColumnData(EVENTS_COUNT_COLUMN, 125, SWT.LEFT, + EVENTS_COUNT_COLUMN_TIP, new ColumnLabelProvider() { + @Override + public String getText(Object element) { + StatisticsTreeNode node = (StatisticsTreeNode) element; + if (!folderLevels.contains(node.getKey())) { + return Long.toString(node.getValue().nbEvents); + } else { + return ""; + } + } + }, new ViewerComparator() { + @Override + public int compare(Viewer viewer, Object e1, Object e2) { + StatisticsTreeNode n1 = (StatisticsTreeNode) e1; + StatisticsTreeNode n2 = (StatisticsTreeNode) e2; + + return (int) (n1.getValue().nbEvents - n2 + .getValue().nbEvents); + } + }, new ColumnPercentageProvider() { + public double getPercentage(StatisticsTreeNode node) { + StatisticsTreeNode parent = node; + do { + parent = parent.getParent(); + } while (parent != null + && parent.getValue().nbEvents == 0); + + if (parent == null) { + return 0; + } else { + return (double) node.getValue().nbEvents + / parent.getValue().nbEvents; + } + } + }), + new ColumnData(CPU_TIME_COLUMN, 125, SWT.LEFT, CPU_TIME_COLUMN_TIP, + new ColumnLabelProvider() { + @Override + public String getText(Object element) { + StatisticsTreeNode node = (StatisticsTreeNode) element; + + if (folderLevels.contains(node.getKey())) { + return ""; + } else if (node.getParent() != null + && levelsWithEmptyTime.contains(node + .getParent().getKey())) { + return ""; + } else { + return decimalFormat + .format(node.getValue().cpuTime + / Math.pow(10, 9)); + } + } + }, null, null), + new ColumnData(CUMULATIVE_CPU_TIME_COLUMN, 155, SWT.LEFT, + CUMULATIVE_CPU_TIME_COLUMN_TIP, new ColumnLabelProvider() { + @Override + public String getText(Object element) { + StatisticsTreeNode node = (StatisticsTreeNode) element; + if (folderLevels.contains(node.getKey())) { + return ""; + } else if (node.getParent() != null + && levelsWithEmptyTime.contains(node + .getParent().getKey())) { + return ""; + } else { + return decimalFormat + .format(node.getValue().cumulativeCpuTime + / Math.pow(10, 9)); + } + } + }, null, null), + new ColumnData(ELAPSED_TIME_COLUMN, 100, SWT.LEFT, + ELAPSED_TIME_COLUMN_TIP, new ColumnLabelProvider() { + @Override + public String getText(Object element) { + StatisticsTreeNode node = (StatisticsTreeNode) element; + if (folderLevels.contains(node.getKey())) { + return ""; + } else if (node.getParent() != null + && levelsWithEmptyTime.contains(node + .getParent().getKey())) { + return ""; + } else { + return decimalFormat + .format(node.getValue().elapsedTime + / Math.pow(10, 9)); + } + } + }, null, null) }; + + /** + * Adapter TreeViewers can use to interact with StatisticsTreeNode objects. + * + * @see org.eclipse.jface.viewers.ITreeContentProvider + */ + class TreeContentProvider implements ITreeContentProvider { + /* + * (non-Javadoc) + * + * @see + * org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang + * .Object) + */ + public Object[] getChildren(Object parentElement) { + return ((StatisticsTreeNode) parentElement).getChildren().toArray(); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang + * .Object) + */ + public Object getParent(Object element) { + return ((StatisticsTreeNode) element).getParent(); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang + * .Object) + */ + public boolean hasChildren(Object element) { + return ((StatisticsTreeNode) element).hasChildren(); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.jface.viewers.IStructuredContentProvider#getElements( + * java.lang.Object) + */ + public Object[] getElements(Object inputElement) { + return getChildren(inputElement); + } + + /* + * (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) + */ + // @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + } + + public StatisticsView(String viewName) { + super(viewName); + } + + public StatisticsView() { + this("StatisticsView"); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets + * .Composite) + */ + @Override + public void createPartControl(Composite parent) { + parent.setLayout(new FillLayout()); + + treeViewer = new TreeViewer(parent, SWT.BORDER | SWT.H_SCROLL + | SWT.V_SCROLL); + treeViewer.setContentProvider(new TreeContentProvider()); + treeViewer.getTree().setHeaderVisible(true); + treeViewer.setUseHashlookup(true); + + for (final ColumnData columnData : columnDataList) { + final TreeViewerColumn treeColumn = new TreeViewerColumn( + treeViewer, columnData.alignment); + treeColumn.getColumn().setText(columnData.header); + treeColumn.getColumn().setWidth(columnData.width); + treeColumn.getColumn().setToolTipText(columnData.tooltip); + if (columnData.comparator != null) { + treeColumn.getColumn().addSelectionListener( + new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + if (treeViewer.getTree().getSortDirection() == SWT.UP + || treeViewer.getTree().getSortColumn() != treeColumn + .getColumn()) { + treeViewer + .setComparator(columnData.comparator); + treeViewer.getTree().setSortDirection( + SWT.DOWN); + } else { + treeViewer + .setComparator(new ViewerComparator() { + @Override + public int compare( + Viewer viewer, + Object e1, Object e2) { + return -1 + * columnData.comparator + .compare( + viewer, + e1, + e2); + } + }); + treeViewer.getTree().setSortDirection( + SWT.UP); + } + treeViewer.getTree().setSortColumn( + treeColumn.getColumn()); + } + }); + } + treeColumn.setLabelProvider(columnData.labelProvider); + } + + // Handler that will draw the bar charts. + treeViewer.getTree().addListener(SWT.EraseItem, new Listener() { + // @Override + public void handleEvent(Event event) { + if (columnDataList[event.index].percentageProvider != null) { + StatisticsTreeNode node = (StatisticsTreeNode) event.item + .getData(); + + double percentage = columnDataList[event.index].percentageProvider + .getPercentage(node); + if (percentage == 0) { + return; + } + + if ((event.detail & SWT.SELECTED) > 0) { + Color oldForeground = event.gc.getForeground(); + event.gc.setForeground(event.item.getDisplay() + .getSystemColor(SWT.COLOR_LIST_SELECTION)); + event.gc.fillRectangle(event.x, event.y, event.width, + event.height); + event.gc.setForeground(oldForeground); + event.detail &= ~SWT.SELECTED; + } + + int barWidth = (int) ((treeViewer.getTree().getColumn(1) + .getWidth() - 8) * percentage); + int oldAlpha = event.gc.getAlpha(); + Color oldForeground = event.gc.getForeground(); + Color oldBackground = event.gc.getBackground(); + event.gc.setAlpha(64); + event.gc.setForeground(event.item.getDisplay() + .getSystemColor(SWT.COLOR_BLUE)); + event.gc.setBackground(event.item.getDisplay() + .getSystemColor(SWT.COLOR_LIST_BACKGROUND)); + event.gc.fillGradientRectangle(event.x, event.y, barWidth, + event.height, true); + event.gc.drawRectangle(event.x, event.y, barWidth, + event.height); + event.gc.setForeground(oldForeground); + event.gc.setBackground(oldBackground); + event.gc.setAlpha(oldAlpha); + event.detail &= ~SWT.BACKGROUND; + } + } + }); + + treeViewer.setComparator(columnDataList[0].comparator); + treeViewer.getTree().setSortColumn(treeViewer.getTree().getColumn(0)); + treeViewer.getTree().setSortDirection(SWT.DOWN); + + // Read current data if any available + TmfExperiment experiment = TmfExperiment.getCurrentExperiment(); + if (experiment != null) { + requestData(experiment); + } else { + TraceDebug.debug("No selected experiment information available"); + } + } + + @Override + public void dispose() { + super.dispose(); + if (fwaitCursor != null) { + fwaitCursor.dispose(); + } + + // clean the model + StatisticsTreeRootFactory.removeAll(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.part.WorkbenchPart#setFocus() + */ + @Override + public void setFocus() { + treeViewer.getTree().setFocus(); + } + + + /** + * @return + */ + public AbsEventToHandlerResolver getEventProcessor() { + return StatsTimeCountHandlerFactory.getInstance(); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView#waitCursor + * (boolean) + */ + protected void waitCursor(final boolean waitInd) { + if (treeViewer == null) { + return; + } + + Display display = treeViewer.getControl().getDisplay(); + if (fwaitCursor == null) { + fwaitCursor = new Cursor(display, SWT.CURSOR_WAIT); + } + + // Perform the updates on the UI thread + display.asyncExec(new Runnable() { + public void run() { + Cursor cursor = null; /* indicates default */ + if (waitInd) { + cursor = fwaitCursor; + } + treeViewer.getControl().setCursor(cursor); + } + }); + } + + @Override + public void ModelUpdatePrep(TmfTimeRange timeRange, boolean clearAllData) { + Object input = treeViewer.getInput(); + if (input != null && input instanceof StatisticsTreeNode) { + ((StatisticsTreeNode) input).reset(); + treeViewer.getTree().getDisplay().asyncExec(new Runnable() { + // @Override + public void run() { + treeViewer.refresh(); + } + }); + } + } + + @Override + public void modelInputChanged(ILttngSyntEventRequest request, boolean complete) { + treeViewer.getTree().getDisplay().asyncExec(new Runnable() { + // @Override + public void run() { + treeViewer.refresh(); + } + }); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView# + * modelIncomplete + * (org.eclipse.linuxtools.lttng.request.ILttngSyntEventRequest) + */ + @Override + public void modelIncomplete(ILttngSyntEventRequest request) { + Object input = treeViewer.getInput(); + if (input != null && input instanceof StatisticsTreeNode) { + // The data from this experiment is invalid and shall be removed to + // refresh upon next selection + String name = ((StatisticsTreeNode) input).getKey(); + StatisticsTreeRootFactory.removeStatTreeRoot(name); + } + } + + /** + * @param signal + */ + @TmfSignalHandler + public void experimentSelected(TmfExperimentSelectedSignal signal) { + if (signal != null) { + TmfExperiment experiment = signal.getExperiment(); + String experimentName = experiment.getName(); + + if (StatisticsTreeRootFactory.containsTreeRoot(experimentName)) { + // The experiment root is already present + StatisticsTreeNode experimentTreeNode = StatisticsTreeRootFactory.getStatTreeRoot(experimentName); + + ITmfTrace[] traces = experiment.getTraces(); + + // check if there is partial data loaded in the experiment + int numTraces = experiment.getTraces().length; + int numNodeTraces = experimentTreeNode.getNbChildren(); + + if (numTraces == numNodeTraces) { + boolean same = true; + // Detect if the experiment contains the same traces as when + // previously selected + for (int i = 0; i < numTraces; i++) { + String traceName = traces[i].getName(); + if (!experimentTreeNode.containsChild(traceName)) { + same = false; + break; + } + } + + if (same) { + // no need to reload data, all traces are already loaded + treeViewer.setInput(experimentTreeNode); + return; + } + } + } + + // if the data is not available or has changed, reload it + requestData(experiment); + } + } + + /** + * @param experiment + */ + private void requestData(TmfExperiment experiment) { + if (experiment != null) { + StatisticsTreeNode treeModelRoot = StatisticsTreeRootFactory.getStatTreeRoot(experiment.getName()); + + // if the model has contents, clear to start over + if (treeModelRoot.hasChildren()) { + treeModelRoot.reset(); + } + + // set input to a clean data model + treeViewer.setInput(treeModelRoot); + TmfTimeRange experimentTRange = experiment.getTimeRange(); + + // send the initial request, to start filling up model + dataRequest(experimentTRange, experimentTRange, true); + } else { + TraceDebug.debug("No selected experiment information available"); + } + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView#displayModel + * (org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model. + * ITmfTimeAnalysisEntry[], long, long, boolean, long, long, + * java.lang.Object) + */ + @Override + protected void displayModel(ITmfTimeAnalysisEntry[] items, long startBoundTime, long endBoundTime, + boolean updateTimeBounds, long startVisibleWindow, long endVisibleWindow, Object source) { + // No applicable to statistics view + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView# + * getParamsUpdater() + */ + @Override + protected ParamsUpdater getParamsUpdater() { + // Not applicable to statistics view + return null; + } + + @Override + protected ItemContainer getItemContainer() { + // Not applicable to statistics view + return null; + } +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/evProcessor/AbstractStatsEventHandler.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/evProcessor/AbstractStatsEventHandler.java new file mode 100644 index 0000000000..91a02369b0 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/evProcessor/AbstractStatsEventHandler.java @@ -0,0 +1,243 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Yann N. Dauphin (dhaemon@gmail.com) - Implementation for stats + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.statistics.evProcessor; + +import org.eclipse.linuxtools.lttng.event.LttngEvent; +import org.eclipse.linuxtools.lttng.state.StateStrings.Events; +import org.eclipse.linuxtools.lttng.state.StateStrings.ExecutionMode; +import org.eclipse.linuxtools.lttng.state.StateStrings.ProcessStatus; +import org.eclipse.linuxtools.lttng.state.evProcessor.ILttngEventProcessor; +import org.eclipse.linuxtools.lttng.state.model.LttngProcessState; +import org.eclipse.linuxtools.lttng.state.model.LttngTraceState; +import org.eclipse.linuxtools.lttng.ui.views.statistics.model.StatisticsTreeRootFactory; +import org.eclipse.linuxtools.lttng.ui.views.statistics.model.StatisticsTreeNode; + +abstract class AbstractStatsEventHandler implements ILttngEventProcessor { + private Events eventType; + + public AbstractStatsEventHandler(Events eventType) { + super(); + this.eventType = eventType; + } + + /** + * @return root of of the tree for this experiment. + */ + protected StatisticsTreeNode getStatisticsTree(LttngTraceState trcState) { + String experimentName = trcState.getContext().getExperimentName(); + StatisticsTreeNode tree = StatisticsTreeRootFactory.getStatTreeRoot(experimentName); + return tree; + } + + /** + * @return list of paths that should be updated for this event. + */ + protected String[][] getRelevantPaths(LttngEvent event, + LttngTraceState traceState) { + String trace = traceState.getContext().getTraceId(); + + Long cpu = event.getCpuId(); + + LttngProcessState process = traceState.getRunning_process().get( + cpu); + + String processName = getPocessName(process); + + String mode = process.getState().getExec_mode().getInName(); + + String submode = process.getState().getExec_submode(); + + Long function = process.getCurrent_function(); + + // String type = event.getType().getTypeId(); + + String[][] paths = { + {trace}, + {trace, "Modes", mode}, + {trace, "Modes", mode, "Submodes", submode}, + {trace, "Processes", processName}, + {trace, "Processes", processName, "CPUs", cpu.toString()}, + {trace, "Processes", processName, "CPUs", cpu.toString(), "Functions", function.toString()}, + {trace, "Processes", processName, "CPUs", cpu.toString(), "Modes", mode}, + {trace, "Processes", processName, "CPUs", cpu.toString(), "Modes", mode, "Submodes", submode}, + {trace, "Processes", processName, "Modes", mode}, + {trace, "Processes", processName, "Modes", mode, "Submodes", submode}, + {trace, "CPUs", cpu.toString()}, + {trace, "CPUs", cpu.toString(), "Modes", mode}, + {trace, "CPUs", cpu.toString(), "Modes", mode, "Submodes", submode}, + }; + return paths; + } + + /** + * @return list of event types paths that should be updated for this event. + */ + protected String[][] getRelevantEventTypesPaths(LttngEvent event, + LttngTraceState traceState) { + String trace = traceState.getContext().getTraceId(); + + Long cpu = event.getCpuId(); + + LttngProcessState process = traceState.getRunning_process().get( + cpu); + + String processName = getPocessName(process); + + String mode = process.getState().getExec_mode().getInName(); + + String submode = process.getState().getExec_submode(); + + Long function = process.getCurrent_function(); + + String type = event.getType().getTypeId(); + + String[][] paths = { + {trace, "Event Types", type}, + {trace, "Modes", mode, "Event Types", type}, + {trace, "Modes", mode, "Submodes", submode, "Event Types", type}, + {trace, "Processes", processName, "Event Types", type}, + {trace, "Processes", processName, "CPUs", cpu.toString(), "Event Types", type}, + {trace, "Processes", processName, "CPUs", cpu.toString(), "Functions", function.toString(), "Event Types", type}, + {trace, "Processes", processName, "CPUs", cpu.toString(), "Modes", mode, "Event Types", type}, + {trace, "Processes", processName, "CPUs", cpu.toString(), "Modes", mode, "Submodes", submode, "Event Types", type}, + {trace, "Processes", processName, "Modes", mode, "Event Types", type}, + {trace, "Processes", processName, "Modes", mode, "Submodes", submode, "Event Types", type}, + {trace, "CPUs", cpu.toString(), "Event Types", type}, + {trace, "CPUs", cpu.toString(), "Modes", mode, "Event Types", type}, + {trace, "CPUs", cpu.toString(), "Modes", mode, "Submodes", submode, "Event Types", type}, + }; + return paths; + } + + /** + * @return name of the process. Returns special string if the name is "". + */ + private String getPocessName(LttngProcessState process) { + if (process.getName() == null) { + return "Unknown process"; + } + if (process.getName() == "") { + return process.getPid().toString(); + } + else { + return process.getName(); + } + } + + /** + * Increase the NbEvents counter of this node. + */ + protected void increaseNbEvents(StatisticsTreeNode node) { + node.getValue().nbEvents++; + } + + /** + * Increase the CPU Time according to the trace state. + */ + protected void increaseCPUTime(StatisticsTreeNode node, LttngEvent event, + LttngTraceState traceState) { + Long cpu = event.getCpuId(); + + LttngProcessState process = traceState.getRunning_process().get( + cpu); + + if (process.getState().getProc_status().equals(ProcessStatus.LTTV_STATE_RUN) && + !process.getState().getExec_mode().equals(ExecutionMode.LTTV_STATE_MODE_UNKNOWN)) { + node.getValue().cpuTime += event.getTimestamp().getValue() + - process.getState().getChange_LttTime(); + } + } + + /** + * Increase the Elapsed Time according to the trace state. + */ + protected void increaseElapsedTime(StatisticsTreeNode node, LttngEvent event, + LttngTraceState traceState) { + Long cpu = event.getCpuId(); + + LttngProcessState process = traceState.getRunning_process().get( + cpu); + + if (!process.getState().getExec_mode().equals(ExecutionMode.LTTV_STATE_MODE_UNKNOWN)) { + node.getValue().elapsedTime += event.getTimestamp().getValue() + - process.getState().getEntry_LttTime(); + } + } + + /** + * Increase the Cumulative CPU Time according to the trace state. + */ + protected void increaseCumulativeCPUTime(StatisticsTreeNode node, LttngEvent event, + LttngTraceState traceState) { + Long cpu = event.getCpuId(); + + LttngProcessState process = traceState.getRunning_process().get( + cpu); + + if (!process.getState().getExec_mode().equals(ExecutionMode.LTTV_STATE_MODE_UNKNOWN)) { + long cumulativeCpuTime = process.getState().getCum_cpu_time(); + long delta = event.getTimestamp().getValue() - process.getState().getEntry_LttTime(); + process.getState().setCum_cpu_time(cumulativeCpuTime + delta); + node.getValue().cumulativeCpuTime += process.getState().getCum_cpu_time(); + } + else if (process.getState().getProc_status().equals(ProcessStatus.LTTV_STATE_RUN) && + !process.getState().getExec_mode().equals(ExecutionMode.LTTV_STATE_MODE_UNKNOWN)) { + long cumulativeCpuTime = process.getState().getCum_cpu_time(); + long delta = event.getTimestamp().getValue() - process.getState().getChange_LttTime(); + process.getState().setCum_cpu_time(cumulativeCpuTime + delta); + node.getValue().cumulativeCpuTime += process.getState().getCum_cpu_time(); + } + } + + /** + * Increase the State-bound Cumulative CPU Time according to the trace state. + */ + protected void increaseStateCumulativeCPUTime(LttngEvent event, + LttngTraceState traceState) { + Long cpu = event.getCpuId(); + + LttngProcessState process = traceState.getRunning_process().get(cpu); + + if (process.getState().getProc_status().equals(ProcessStatus.LTTV_STATE_RUN) && + !process.getState().getExec_mode().equals(ExecutionMode.LTTV_STATE_MODE_UNKNOWN)) { + long cumulativeCpuTime = process.getState().getCum_cpu_time(); + long delta = event.getTimestamp().getValue() - process.getState().getChange_LttTime(); + process.getState().setCum_cpu_time(cumulativeCpuTime + delta); + } + } + +// @Override + public Events getEventHandleType() { + return eventType; + } + + protected void stepCount(LttngEvent event, LttngTraceState traceState) { + StatisticsTreeNode root = getStatisticsTree(traceState); + + String[][] paths = getRelevantPaths(event, traceState); + + for (String[] path : paths) { + StatisticsTreeNode node = root.getOrCreateChildFromPath(path); + + increaseNbEvents(node); + } + + String[][] eventTypesPaths = getRelevantEventTypesPaths(event, traceState); + + for (String[] path : eventTypesPaths) { + StatisticsTreeNode node = root.getOrCreateChildFromPath(path); + + increaseNbEvents(node); + } + } + +} \ No newline at end of file diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/evProcessor/StatsModeChangeHandler.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/evProcessor/StatsModeChangeHandler.java new file mode 100644 index 0000000000..0e0b861882 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/evProcessor/StatsModeChangeHandler.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Yann N. Dauphin (dhaemon@gmail.com) - Implementation for stats + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.statistics.evProcessor; + +import org.eclipse.linuxtools.lttng.event.LttngEvent; +import org.eclipse.linuxtools.lttng.state.StateStrings.Events; +import org.eclipse.linuxtools.lttng.state.model.LttngTraceState; +import org.eclipse.linuxtools.lttng.ui.views.statistics.model.StatisticsTreeNode; + +class StatsModeChangeHandler extends AbstractStatsEventHandler { + + public StatsModeChangeHandler(Events eventType) { + super(eventType); + } + + /* (non-Javadoc) + * @see org.eclipse.linuxtools.lttng.state.evProcessor.IEventProcessing#process(org.eclipse.linuxtools.lttng.event.LttngEvent, org.eclipse.linuxtools.lttng.state.model.LttngTraceState) + */ + public boolean process(LttngEvent event, LttngTraceState traceState) { + StatisticsTreeNode root = getStatisticsTree(traceState); + + String[][] paths = getRelevantPaths(event, traceState); + + for (String[] path : paths) { + StatisticsTreeNode node = root.getOrCreateChildFromPath(path); + + increaseCPUTime(node, event, traceState); + + increaseStateCumulativeCPUTime(event, traceState); + } + + return false; + } + +} \ No newline at end of file diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/evProcessor/StatsModeEndHandler.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/evProcessor/StatsModeEndHandler.java new file mode 100644 index 0000000000..265b92ef4b --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/evProcessor/StatsModeEndHandler.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Yann N. Dauphin (dhaemon@gmail.com) - Implementation for stats + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.statistics.evProcessor; + +import org.eclipse.linuxtools.lttng.event.LttngEvent; +import org.eclipse.linuxtools.lttng.state.StateStrings.Events; +import org.eclipse.linuxtools.lttng.state.model.LttngTraceState; +import org.eclipse.linuxtools.lttng.ui.views.statistics.model.StatisticsTreeNode; + +class StatsModeEndHandler extends AbstractStatsEventHandler { + + public StatsModeEndHandler(Events eventType) { + super(eventType); + } + + /* (non-Javadoc) + * @see org.eclipse.linuxtools.lttng.state.evProcessor.IEventProcessing#process(org.eclipse.linuxtools.lttng.event.LttngEvent, org.eclipse.linuxtools.lttng.state.model.LttngTraceState) + */ + public boolean process(LttngEvent event, LttngTraceState traceState) { + StatisticsTreeNode root = getStatisticsTree(traceState); + + String[][] paths = getRelevantPaths(event, traceState); + + for (String[] path : paths) { + StatisticsTreeNode node = root.getOrCreateChildFromPath(path); + + increaseCPUTime(node, event, traceState); + + increaseElapsedTime(node, event, traceState); + + increaseCumulativeCPUTime(node, event, traceState); + } + + return false; + } + +} \ No newline at end of file diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/evProcessor/StatsTimeCountHandlerFactory.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/evProcessor/StatsTimeCountHandlerFactory.java new file mode 100644 index 0000000000..97236913e2 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/evProcessor/StatsTimeCountHandlerFactory.java @@ -0,0 +1,137 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Yann N. Dauphin (dhaemon@gmail.com) - Implementation for stats + * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.statistics.evProcessor; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.linuxtools.lttng.state.StateStrings; +import org.eclipse.linuxtools.lttng.state.evProcessor.AbsEventToHandlerResolver; +import org.eclipse.linuxtools.lttng.state.evProcessor.ILttngEventProcessor; + +/** + * Provide the handlers that will count the CPU Time, Cumulative CPU Time and + * Elapsed Time and update the appropriate tree. + * + * Builds a Map from string event name to a processing handler object, the + * processors implement the same interface to facilitate transparent methods + * call, + * + * The map key STring is the entry point of the raw events, using a hash speeds + * up the resolution of the appropriate processor + * + * @author alvaro + * + */ +public class StatsTimeCountHandlerFactory extends AbsEventToHandlerResolver { + // ======================================================================== + // Data + // ======================================================================= + private final Map eventNametoBeforeProcessor = new HashMap(); + ILttngEventProcessor afterhandler; + private static StatsTimeCountHandlerFactory instance = null; + private StatsTimeCountHandlers instantiateHandler = new StatsTimeCountHandlers(); + + // ======================================================================== + // Constructors + // ======================================================================= + private StatsTimeCountHandlerFactory() { + super(); + //create one instance of each individual event handler and add the instance to the map + eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_SYSCALL_ENTRY + .getInName(), instantiateHandler.getSyscallEntryBeforeHandler()); + + eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_SYSCALL_EXIT + .getInName(), instantiateHandler.getsySyscallExitBeforeHandler()); + + eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_TRAP_ENTRY + .getInName(), instantiateHandler.getTrapEntryBeforeHandler()); + + eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_TRAP_EXIT + .getInName(), instantiateHandler.getTrapExitBeforeHandler()); + + eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_PAGE_FAULT_ENTRY + .getInName(), instantiateHandler.getTrapEntryBeforeHandler()); + + eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_PAGE_FAULT_EXIT + .getInName(), instantiateHandler.getTrapExitBeforeHandler()); + + eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY + .getInName(), instantiateHandler.getTrapEntryBeforeHandler()); + + eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_PAGE_FAULT_NOSEM_EXIT + .getInName(), instantiateHandler.getTrapExitBeforeHandler()); + + eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_IRQ_ENTRY + .getInName(), instantiateHandler.getIrqEntryBeforeHandler()); + + eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_IRQ_EXIT + .getInName(), instantiateHandler.getIrqExitBeforeHandler()); + + eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_SOFT_IRQ_ENTRY + .getInName(), instantiateHandler.getSoftIrqEntryBeforeHandler()); + + eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_SOFT_IRQ_EXIT + .getInName(), instantiateHandler.getSoftIrqExitBeforeHandler()); + + eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_FUNCTION_ENTRY + .getInName(), instantiateHandler.getFunctionEntryBeforeHandler()); + + eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_FUNCTION_EXIT + .getInName(), instantiateHandler.getFunctionExitBeforeHandler()); + + eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_SCHED_SCHEDULE + .getInName(), instantiateHandler.getSchedChangeBeforeHandler()); + + afterhandler = instantiateHandler.getAfterHandler(); + + } + + // ======================================================================== + // Public methods + // ======================================================================= + /** + * The event processors are common to all traces an multiple instances will + * use more memory unnecessarily + * + * @return + */ + public static AbsEventToHandlerResolver getInstance() { + if (instance == null) { + instance = new StatsTimeCountHandlerFactory(); + } + return instance; + } + + + @Override + public ILttngEventProcessor getAfterProcessor(String eventType) { + return afterhandler; + } + + @Override + public ILttngEventProcessor getBeforeProcessor(String eventType) { + return eventNametoBeforeProcessor.get(eventType); + } + + @Override + public ILttngEventProcessor getfinishProcessor() { + // No finishing processor used + return null; + } + + @Override + public ILttngEventProcessor getStateUpdaterProcessor(String eventType) { + return null; + } +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/evProcessor/StatsTimeCountHandlers.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/evProcessor/StatsTimeCountHandlers.java new file mode 100644 index 0000000000..2fb581e2e3 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/evProcessor/StatsTimeCountHandlers.java @@ -0,0 +1,178 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Yann N. Dauphin (dhaemon@gmail.com) - Implementation for stats + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.statistics.evProcessor; + +import org.eclipse.linuxtools.lttng.event.LttngEvent; +import org.eclipse.linuxtools.lttng.state.StateStrings; +import org.eclipse.linuxtools.lttng.state.StateStrings.Events; +import org.eclipse.linuxtools.lttng.state.evProcessor.ILttngEventProcessor; +import org.eclipse.linuxtools.lttng.state.model.LttngTraceState; + +/** + * Process the system call entry event + * + * @author alvaro + * + */ +class StatsTimeCountHandlers { + + /** + * Method to handle the event: LTT_EVENT_SYSCALL_ENTRY + * + * @return + */ + final ILttngEventProcessor getSyscallEntryBeforeHandler() { + AbstractStatsEventHandler handler = new StatsModeChangeHandler(Events.LTT_EVENT_SYSCALL_ENTRY); + return handler; + } + + /** + * Method to handle the event: LTT_EVENT_SYSCALL_EXIT + * + * @return + */ + final ILttngEventProcessor getsySyscallExitBeforeHandler() { + AbstractStatsEventHandler handler = new StatsModeEndHandler(Events.LTT_EVENT_SYSCALL_EXIT); + return handler; + } + + /** + * Method to handle the event: LTT_EVENT_TRAP_ENTRY + * + * @return + */ + final ILttngEventProcessor getTrapEntryBeforeHandler() { + AbstractStatsEventHandler handler = new StatsModeChangeHandler(Events.LTT_EVENT_TRAP_ENTRY); + return handler; + } + + /** + * Method to handle the event: LTT_EVENT_TRAP_EXIT + * + * @return + */ + final ILttngEventProcessor getTrapExitBeforeHandler() { + AbstractStatsEventHandler handler = new StatsModeEndHandler(Events.LTT_EVENT_TRAP_EXIT); + return handler; + } + + /** + * Method to handle the event: LTT_EVENT_IRQ_ENTRY + * + * @return + */ + final ILttngEventProcessor getIrqEntryBeforeHandler() { + AbstractStatsEventHandler handler = new StatsModeChangeHandler(Events.LTT_EVENT_IRQ_ENTRY); + return handler; + } + + /** + * Method to handle the event: LTT_EVENT_IRQ_EXIT + * + * @return + */ + final ILttngEventProcessor getIrqExitBeforeHandler() { + AbstractStatsEventHandler handler = new StatsModeEndHandler(Events.LTT_EVENT_IRQ_EXIT); + return handler; + } + + /** + * Method to handle the event: LTT_EVENT_SOFT_IRQ_ENTRY + * + * @return + */ + final ILttngEventProcessor getSoftIrqEntryBeforeHandler() { + AbstractStatsEventHandler handler = new StatsModeChangeHandler(Events.LTT_EVENT_SOFT_IRQ_ENTRY); + return handler; + } + + /** + * Method to handle the event: LTT_EVENT_SOFT_IRQ_EXIT + * + * @return + */ + final ILttngEventProcessor getSoftIrqExitBeforeHandler() { + AbstractStatsEventHandler handler = new StatsModeEndHandler(Events.LTT_EVENT_SOFT_IRQ_EXIT); + return handler; + } + + /** + *

+ * Handles event: LTT_EVENT_FUNCTION_ENTRY + *

+ *

+ * FIELDS: LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE + *

+ * + * @return + */ + final ILttngEventProcessor getFunctionEntryBeforeHandler() { + AbstractStatsEventHandler handler = new StatsModeChangeHandler(Events.LTT_EVENT_FUNCTION_ENTRY); + return handler; + } + + /** + * + * @return + */ + final ILttngEventProcessor getFunctionExitBeforeHandler() { + AbstractStatsEventHandler handler = new StatsModeEndHandler(Events.LTT_EVENT_FUNCTION_EXIT); + return handler; + } + + /** + *

+ * Handles: LTT_EVENT_SCHED_SCHEDULE + *

+ *

+ * Fields: LTT_FIELD_PREV_PID, LTT_FIELD_NEXT_PID, LTT_FIELD_PREV_STATE + *

+ * + * @return + */ + final ILttngEventProcessor getSchedChangeBeforeHandler() { + AbstractStatsEventHandler handler = new StatsModeChangeHandler(Events.LTT_EVENT_SCHED_SCHEDULE); + return handler; + } + + /** + *

+ * Handles: LTT_EVENT_SCHED_SCHEDULE + *

+ *

+ * Fields: LTT_FIELD_PREV_PID, LTT_FIELD_NEXT_PID, LTT_FIELD_PREV_STATE + *

+ * + * @return + */ + final ILttngEventProcessor getAfterHandler() { + AbstractStatsEventHandler handler = new StatsModeChangeHandler(null) { + int sched_hash = StateStrings.Events.LTT_EVENT_SCHED_SCHEDULE.getInName().hashCode(); + public boolean process(LttngEvent event, LttngTraceState traceState) { + // Step the event counter for any after event + stepCount(event, traceState); + + int eventNameHash = event.getMarkerName().hashCode(); + // specific processing for after sched schedule + if (sched_hash == eventNameHash + && event.getMarkerName().equals(StateStrings.Events.LTT_EVENT_SCHED_SCHEDULE.getInName())) { + return super.process(event, traceState); + } + + return false; + } + }; + + return handler; + } + +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/model/Statistics.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/model/Statistics.java new file mode 100644 index 0000000000..53caa96580 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/model/Statistics.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Yann N. Dauphin (dhaemon@gmail.com) - Implementation for stats + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.statistics.model; + +public class Statistics { + public long nbEvents = 0; + + public long cpuTime = 0; + + public long cumulativeCpuTime = 0; + + public long elapsedTime = 0; +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/model/StatisticsTreeNode.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/model/StatisticsTreeNode.java new file mode 100644 index 0000000000..172e05e3ad --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/model/StatisticsTreeNode.java @@ -0,0 +1,215 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Yann N. Dauphin (dhaemon@gmail.com) - Implementation for stats + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.statistics.model; + +import java.util.AbstractMap; +import java.util.Collection; +import java.util.HashMap; + +/* + * A tree where nodes can be accessed efficiently using paths. + * + * It works like file systems. Each node is identified by a key. A path is a list of keys separated by the character '/'. + * For example, the path 'persons/yann' will browse to the child 'persons' and return it's 'yann' child. + * + * If a key might contains the character '/', use the #escapeKey method to get an escaped key. Use the #unescapeKey + * method to unescaped the key. + */ +public class StatisticsTreeNode { + + private StatisticsTreeNode parent; + + private String key; + + private Statistics value; + + private AbstractMap children; + + /* + * Construct a node with the given key + */ + public StatisticsTreeNode(String key) { + this(null, key); + } + + /* + * Construct a node with the given parent, key and value. + */ + public StatisticsTreeNode(StatisticsTreeNode parent, String key) { + super(); + this.parent = parent; + this.key = key; + this.value = new Statistics(); + this.children = new HashMap(); + } + + /* + * @return key associated with this node. + */ + public StatisticsTreeNode getParent() { + return this.parent; + } + + /* + * @return key associated with this node. + */ + public String getKey() { + return this.key; + } + + /* + * @return value associated with this node. + */ + public Statistics getValue() { + return this.value; + } + + /* + * Add a direct child with the given value at the given path. + * + * @return children node that was created. + */ + public StatisticsTreeNode addChild(String key) { + StatisticsTreeNode created = new StatisticsTreeNode(this, key); + + this.children.put(key, created); + + return created; + } + + /* + * @return direct children node with the given key. null if not found. + */ + public StatisticsTreeNode getChild(String key) { + if (!this.children.containsKey(key)) { + return null; + } + + return this.children.get(key); + } + + /* + * @return number of direct children of this node. + */ + public boolean hasChildren() { + return getNbChildren() > 0; + } + + /* + * @return direct children of this node. + */ + public Collection getChildren() { + return children.values(); + } + + /* + * @return number of direct children of this node. + */ + public int getNbChildren() { + return children.size(); + } + + /* + * Get the node at the given path. If it doesn't exist each node in the path + * will be created with the given class. + * + * @return children node with the given path. null if not found. + */ + public StatisticsTreeNode getOrCreateChildFromPath(String[] path) { + // StatisticsTreeNode previous = this.parent; + StatisticsTreeNode current = this; + for (String key : path) { + if (!current.children.containsKey(key)) { + current.children.put(key, new StatisticsTreeNode(current, key)); + } + + // previous = current; + current = current.children.get(key); + } + + return current; + } + + /* + * Get the node at the given path. If it doesn't exist each node in the path + * will be created with the given class. + * + * @return children node with the given path. null if not found. + */ + public StatisticsTreeNode getOrCreateChildFromPath(String path) { + StatisticsTreeNode previous = this.parent; + StatisticsTreeNode current = this; + for (String key : path.split("/")) { + if (!current.children.containsKey(key)) { + current.children.put(key, new StatisticsTreeNode(previous, key)); + } + + previous = current; + current = current.children.get(key); + } + + return current; + } + + /* + * @return children node with the given path. null if not found. + */ + public StatisticsTreeNode getChildFromPath(String path) { + StatisticsTreeNode current = this; + for (String key : path.split("/")) { + if (!current.children.containsKey(key)) { + return null; + } + + current = current.children.get(key); + } + + return current; + } + + /* + * Use this to escape a key that might contain the '/' character. + * + * @return escaped key + */ + public static String escapeKey(String key) { + return key.replace("%", "%25").replace("/", "%2F"); + } + + /* + * Use this to unescape a key. + * + * @return unescaped key + */ + public static String unescapeKey(String key) { + return key.replace("%2F", "/").replace("%25", "%"); + } + + /** + * Start from creation time i.e. keep key and parent but new statistics and + * no children + */ + public void reset() { + this.value = new Statistics(); + this.children = new HashMap(); + } + + /** + * + * @param key + * @return true: if child with given key is present, false: if no child + * exists with given key name + */ + public boolean containsChild(String key) { + return children.containsKey(key); + } +} \ No newline at end of file diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/model/StatisticsTreeRootFactory.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/model/StatisticsTreeRootFactory.java new file mode 100644 index 0000000000..23038062f2 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/statistics/model/StatisticsTreeRootFactory.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Yann N. Dauphin (dhaemon@gmail.com) - Implementation for stats + *******************************************************************************/ +package org.eclipse.linuxtools.lttng.ui.views.statistics.model; + +import java.util.HashMap; +import java.util.Map; + +public class StatisticsTreeRootFactory { + // ======================================================================== + // Data + // ======================================================================= + + private static final Map rootInstances = new HashMap(); + + // ======================================================================== + // Methods + // ======================================================================= + + /** + * Provide a statisticsTree instance per trace + * + * @return + */ + public static StatisticsTreeNode getStatTreeRoot(String traceUniqueId) { + if (traceUniqueId == null) { + return null; + } + + if (rootInstances.containsKey(traceUniqueId)) { + return rootInstances.get(traceUniqueId); + } + + StatisticsTreeNode tree = new StatisticsTreeNode(traceUniqueId); + + rootInstances.put(traceUniqueId, tree); + + return tree; + } + + /** + * @param traceUniqueId + * @return + */ + public static boolean containsTreeRoot(String traceUniqueId) { + return rootInstances.containsKey(traceUniqueId); + } + + /** + * Remove previously registered statistics tree. + * @param traceUniqueId + */ + public static void removeStatTreeRoot(String traceUniqueId) { + if (traceUniqueId != null && rootInstances.containsKey(traceUniqueId)) { + rootInstances.remove(traceUniqueId); + } + } + + /** + * Remove all tree root instances + */ + public static void removeAll() { + rootInstances.clear(); + } +} diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/timeframe/SpinnerGroup.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/timeframe/SpinnerGroup.java new file mode 100644 index 0000000000..be2a5e7622 --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/timeframe/SpinnerGroup.java @@ -0,0 +1,321 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.timeframe; + +import org.eclipse.linuxtools.tmf.event.TmfTimeRange; +import org.eclipse.linuxtools.tmf.event.TmfTimestamp; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Spinner; + +// ======================================================================== +// SpinnerGroup +// ======================================================================== + +/** + * SpinnerGroup + *

+ * A SpinnerGroup holds two coordinated spinners (for seconds and + * nanoseconds) representing the current time within the trace. + *

+ * The current time can take any value anything within the time range (start + * and end time). + */ +public class SpinnerGroup { + + // The nanosecond scale (10^9) + private static final int NS_PER_SECOND = 1000 * 1000 * 1000; + private static final byte NS_SCALING_FACTOR = -9; + + // Labels + private static final String SECONDS_LABEL = "sec"; + private static final String NANOSEC_LABEL = "ns"; + + // Widgets + private Group group; + private Spinner seconds; + private Spinner nanosec; + + // The valid time range - start time + private TmfTimestamp startTime; + private int startSeconds; + private int startNanosec; + + // The valid time range - end time + private TmfTimestamp endTime; + private int endSeconds; + private int endNanosec; + + // The current time value + private TmfTimestamp currentTime; + private int currentSeconds; + private int currentNanosec; + + @SuppressWarnings("unused") + private TimeFrameView fOwner; + + /** + * Constructor + *

+ *

  • Creates the display group and formats it for the grid cell + *
  • Sets the initial values for Start/End/Current time + *
  • + *

    + * @param parent - the parent Composite + * @param groupName - the group name + * @param range - the valid time range (start/end time) + * @param current - the current time + */ + public SpinnerGroup(TimeFrameView owner, Composite parent, String groupName, TmfTimeRange range, TmfTimestamp current) { + + fOwner = owner; + + // Create the group + group = new Group(parent, SWT.BORDER); + group.setText(groupName); + + // Make it use the whole grid cell + GridData gridData = new GridData(SWT.LEFT, SWT.TOP, true, false); + gridData.horizontalAlignment = SWT.FILL; + group.setLayoutData(gridData); + + // Create and position the widgets + seconds = new Spinner(group, SWT.BORDER); + seconds.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + currentSeconds = seconds.getSelection(); + refreshCurrentTime(); + } + }); + seconds.setBounds(5, 25, 110, 25); + + Label label = new Label(group, SWT.LEFT); + label.setText(SECONDS_LABEL); + label.setBounds(120, 28, 25, 22); + + nanosec = new Spinner(group, SWT.BORDER); + nanosec.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + currentNanosec = nanosec.getSelection(); + // Correct for nanosec underflow + if (currentNanosec < 0) { + currentSeconds--; + currentNanosec = NS_PER_SECOND - 1; + } + // Correct for nanosec overflow + if (currentNanosec >= NS_PER_SECOND) { + currentSeconds++; + currentNanosec = 0; + } + refreshCurrentTime(); + } + }); + nanosec.setBounds(150, 25, 110, 25); + + label = new Label(group, SWT.LEFT); + label.setText(NANOSEC_LABEL); + label.setBounds(265, 28, 25, 22); + + setContent(range, current); + } + + private void refreshCurrentTime() { + long newCurrentTime = ((long) currentSeconds) * NS_PER_SECOND + currentNanosec; + TmfTimestamp ts = new TmfTimestamp(newCurrentTime, NS_SCALING_FACTOR, 0); + currentTime = ts; +// fOwner.synchTimeFrameWidgets(this); + } + + // ==================================================================== + // Get/Set + // ==================================================================== + + public TmfTimestamp getStartTime() { + return startTime; + } + + public TmfTimestamp getEndTime() { + return endTime; + } + + public TmfTimestamp getCurrentTime() { + return currentTime; + } + + public TmfTimestamp getSpan() { + TmfTimestamp span = new TmfTimestamp(startTime.getAdjustment(endTime, NS_SCALING_FACTOR), NS_SCALING_FACTOR, 0); + return span; + } + + public TmfTimeRange getTimeRange() { + TmfTimeRange range = new TmfTimeRange(startTime, endTime); + return range; + } + + public void setStartTime(TmfTimestamp ts) { + try { + startTime = ts.synchronize(0, NS_SCALING_FACTOR); + startSeconds = (int) (startTime.getValue() / NS_PER_SECOND); + startNanosec = (int) (startTime.getValue() % NS_PER_SECOND); + } + catch (ArithmeticException e) { + } + } + + public void setEndTime(TmfTimestamp ts) { + try { + endTime = ts.synchronize(0, NS_SCALING_FACTOR); + endSeconds = (int) (endTime.getValue() / NS_PER_SECOND); + endNanosec = (int) (endTime.getValue() % NS_PER_SECOND); + } + catch (ArithmeticException e) { + } + } + + public void setCurrentTime(TmfTimestamp ts) { + try { + currentTime = ts.synchronize(0, NS_SCALING_FACTOR); + currentSeconds = (int) (currentTime.getValue() / NS_PER_SECOND); + currentNanosec = (int) (currentTime.getValue() % NS_PER_SECOND); + } + catch (ArithmeticException e) { + } + } + + // ==================================================================== + // Operators + // ==================================================================== + + /** + * setContent + *

    + *

  • validates that [startTime <= currentTime <= endTime] is respected + *
  • sets the start/current/end time and update the spinners + *
  • + *

    + * + * @param range + * @param current + */ + public void setContent(TmfTimeRange range, TmfTimestamp current) { + + if (range != null) { + // Extract the time range + TmfTimestamp start = range.getStartTime(); + TmfTimestamp end = range.getEndTime(); + + // Assume start time is OK + setStartTime(start); + + // Make sure end time >= start time + if (end.compareTo(start, false) < 0) { + end = start; + } + setEndTime(end); + + // Make sure [start time <= current time <= end time] + // If not: current = min(max(start, current), end); + if (current.compareTo(start, false) < 0) { + current = start; + } + if (current.compareTo(end, false) > 0) { + current = end; + } + } + setCurrentTime(current); + + // And configure the spinners + updateSpinners(); + } + + /** + * setValue + *

    + *

  • validates that [startTime <= currentTime <= endTime] is respected + *
  • sets the current time and the spinners + *
  • + *

    + * + * @param range + * @param current + */ + public void setValue(TmfTimestamp current) { + + // Make sure [start time <= current time <= end time] + // If not: current = min(max(start, current), end); + if (current.compareTo(startTime, false) < 0) { + current = startTime; + } + if (current.compareTo(endTime, false) > 0) { + current = endTime; + } + setCurrentTime(current); + + // And configure the spinners + updateSpinners(); + } + + /** + * Update the spinners with the new current time value + * Perform the update on the UI thread + */ + public void updateSpinners() { + + seconds.getDisplay().asyncExec(new Runnable() { + public void run() { + if (!seconds.isDisposed() && !nanosec.isDisposed()) { + // If we are on the start second, ensure that [currentNS >= startNS] + // If the currentSeconds > startSeconds, set startns to -1 so we can + // "underflow" + int startns = -1; + if (currentSeconds <= startSeconds) { + currentSeconds = startSeconds; + startns = startNanosec; + if (currentNanosec < startns) { + currentNanosec = startns; + } + } + + // If we are on the end second, ensure that [currentNS <= endNS] + // If the currentSeconds < endSeconds, set endns to MAX so we can + // "overflow" + int endns = NS_PER_SECOND; + if (currentSeconds >= endSeconds) { + currentSeconds = endSeconds; + endns = endNanosec; + if (currentNanosec > endns) { + currentNanosec = endns; + } + } + + // Refresh the spinners (value, range, increments, ...) + // To ensure that the spinners are properly set, the range has to be > 0 +// seconds.setValues(currentSeconds, startSeconds - 1, endSeconds + 1, 0, 1, 10); +// nanosec.setValues(currentNanosec, startns - 1, endns + 1, 0, 1, 1000000); + seconds.setValues(currentSeconds, startSeconds, endSeconds, 0, 1, 10); + nanosec.setValues(currentNanosec, startns, endns, 0, 100000, 10000000); + + // If start == end (i.e. no range), disable the spinner + // (if start == end, the spinner widget range is set to [0..100] by default) + seconds.setEnabled(startSeconds != endSeconds); + nanosec.setEnabled(startns != endns); + } + } + }); + } +} \ No newline at end of file diff --git a/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/timeframe/TimeFrameView.java b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/timeframe/TimeFrameView.java new file mode 100644 index 0000000000..1ee55437bd --- /dev/null +++ b/org.eclipse.linuxtools.lttng.ui/src/org/eclipse/linuxtools/lttng/ui/views/timeframe/TimeFrameView.java @@ -0,0 +1,380 @@ +/******************************************************************************* + * Copyright (c) 2009 2010 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Francois Chouinard - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.linuxtools.lttng.ui.views.timeframe; + +import org.eclipse.linuxtools.lttng.event.LttngEvent; +import org.eclipse.linuxtools.tmf.event.TmfTimeRange; +import org.eclipse.linuxtools.tmf.event.TmfTimestamp; +import org.eclipse.linuxtools.tmf.experiment.TmfExperiment; +import org.eclipse.linuxtools.tmf.signal.TmfExperimentSelectedSignal; +import org.eclipse.linuxtools.tmf.signal.TmfExperimentUpdatedSignal; +import org.eclipse.linuxtools.tmf.signal.TmfRangeSynchSignal; +import org.eclipse.linuxtools.tmf.signal.TmfSignalHandler; +import org.eclipse.linuxtools.tmf.signal.TmfTimeSynchSignal; +import org.eclipse.linuxtools.tmf.ui.views.TmfView; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Slider; + +/** + * TimeFrameView + *

    + * The TimeFrameView provides a set of spinners to monitor and set the start + * time, end time, the current time interval and current time of the trace + * set at the nanosecond level. + *

    + * It ensures that the following relations are always true: + *

    + *

  • [ startTime >= start time of the trace ] + *
  • [ endTime <= end time of the trace ] + *
  • [ startTime <= currentTime <= endTime ] + *
  • [ interval == (endTime - startTime) ] + *
  • + *

    + * It provides a slider to rapidly set the current time within the time range + * (i.e. between startTime and endTime). + *

    + * Finally, it allows modification of the time range and the current time. This + * triggers notifications to the other LTTng views. + *

    + * FIXME: The slider is very jumpy due to the large number of async updates + * FIXME: Revisit the control flow between View, Spinners and Slider + */ +public class TimeFrameView extends TmfView { + + public static final String ID = "org.eclipse.linuxtools.lttng.ui.views.timeframe"; + + // ======================================================================== + // TimeFrameView + // ======================================================================== + + // The event log timestamp characteristics + private TmfTimestamp fTraceStartTime = new TmfTimestamp(); + private TmfTimestamp fTraceEndTime = new TmfTimestamp(); + + private TmfTimestamp fCurrentTime = new TmfTimestamp(); + + private TmfTimeRange fTraceTimeRange = new TmfTimeRange(fTraceStartTime, fTraceEndTime); + private TmfTimeRange fTraceSpan = new TmfTimeRange(fTraceStartTime, fTraceEndTime); + private byte fScale = 0; + + // Labels + private static final String START_TIME_LABEL = "Window Start Time"; + private static final String END_TIME_LABEL = "Window End Time"; + private static final String TIME_RANGE_LABEL = "Window Range"; + private static final String CURRENT_TIME_LABEL = "Current Time"; + + private static final int SLIDER_RANGE = 10000; + + private SpinnerGroup fStartGroup; + private SpinnerGroup fEndGroup; + private SpinnerGroup fRangeGroup; + private SpinnerGroup fCurrentGroup; + + // The slider + private Slider fSlider; + + // The current experiment + TmfExperiment fExperiment = null; + // notify external listeners may not be needed if the update originated + // externally + private boolean fupdateExternalListeners = true; + + + /** + * Constructor + */ + public TimeFrameView() { + super("TimeFrameView"); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) + */ + @Override + public void createPartControl(Composite parent) { + + // Set the view layout + GridLayout layout = new GridLayout(4, true); + parent.setLayout(layout); + + fStartGroup = new SpinnerGroup(this, parent, START_TIME_LABEL, fTraceTimeRange, fTraceStartTime); + fEndGroup = new SpinnerGroup(this, parent, END_TIME_LABEL, fTraceTimeRange, fTraceEndTime); + fRangeGroup = new SpinnerGroup(this, parent, TIME_RANGE_LABEL, fTraceTimeRange, fTraceEndTime); + fCurrentGroup = new SpinnerGroup(this, parent, CURRENT_TIME_LABEL, fTraceTimeRange, fTraceStartTime); + + // Create the slider + createSlider(parent); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.part.WorkbenchPart#setFocus() + */ + @Override + public void setFocus() { + // TODO Auto-generated method stub + } + + // ======================================================================== + // Operators + // ======================================================================== + + /** + * One of the spinners has been updated. Synchronize the other widgets. + */ + public void synchTimeFrameWidgets(SpinnerGroup trigger) { + boolean trangeUpdated = false; + + // Collect the data + TmfTimestamp startTime = fStartGroup.getCurrentTime(); + TmfTimestamp endTime = fEndGroup.getCurrentTime(); + TmfTimestamp timeRange = fRangeGroup.getCurrentTime(); + TmfTimestamp currentTime = fCurrentGroup.getCurrentTime(); + + // If startTime was set beyond endTime, adjust endTime and interval + if (trigger == fStartGroup) { + if (startTime.compareTo(endTime, false) > 0) { + endTime = startTime; + trangeUpdated = true; + } + } + + // If endTime was set beyond startTime, adjust startTime and interval + if (trigger == fEndGroup) { + if (endTime.compareTo(startTime, false) < 0) { + startTime = endTime; + trangeUpdated = true; + } + } + + // If timeRange was set, adjust endTime + if (trigger == fRangeGroup) { + long start = startTime.getValue(); + long span = timeRange.getValue(); + TmfTimestamp ts = new TmfTimestamp(start + span, startTime.getScale(), 0); + if (ts.compareTo(fTraceEndTime, false) > 0) { + ts = fTraceEndTime.synchronize(fTraceEndTime.getValue(), startTime.getScale()); + } + endTime = ts; + trangeUpdated = true; + } + + // Compute the new time range + TmfTimeRange subrange = new TmfTimeRange(startTime, endTime); + byte scale = startTime.getScale(); + TmfTimestamp interval = new TmfTimestamp(startTime.getAdjustment(endTime, scale), scale, 0); + + // Update the spinner groups + fStartGroup.setContent(fTraceTimeRange, startTime); + fEndGroup.setContent(fTraceTimeRange, endTime); + fRangeGroup.setContent(fTraceSpan, interval); + fCurrentGroup.setContent(subrange, currentTime); + + updateSlider(subrange, currentTime); + // Notify other views, only if the update originated from this view + if (fupdateExternalListeners) { + if (!fCurrentTime.equals(currentTime)) { + fCurrentTime = currentTime; + broadcast(new TmfTimeSynchSignal(this, currentTime)); + } + + // Notify the views if the time range has been impacted + if (trangeUpdated) { + TmfTimeRange trange = new TmfTimeRange(startTime, endTime); + broadcast(new TmfRangeSynchSignal(this, trange, currentTime)); + } + } + } + + // ======================================================================== + // Slider Handling + // ======================================================================== + + /** + * @param parent + */ + private void createSlider(Composite parent) { + fSlider = new Slider(parent, SWT.SMOOTH | SWT.FILL); + fSlider.setMinimum(0); + fSlider.setMaximum(SLIDER_RANGE + fSlider.getThumb()); + fSlider.setIncrement(SLIDER_RANGE / 100); + fSlider.setPageIncrement(SLIDER_RANGE / 10); + fSlider.setSelection(0); + + GridData gridData = new GridData(SWT.LEFT, SWT.TOP, true, false); + gridData.horizontalAlignment = SWT.FILL; + gridData.horizontalSpan = 4; + fSlider.setLayoutData(gridData); + + fSlider.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event event) { + int ratio = fSlider.getSelection(); + TmfTimestamp span = fCurrentGroup.getSpan(); + long value = span.getValue() * ratio / SLIDER_RANGE; + TmfTimestamp start = fCurrentGroup.getStartTime(); + TmfTimestamp current = new TmfTimestamp(start.getValue() + value, start.getScale(), 0); + fCurrentGroup.setValue(current); + } + }); + + } + + /** + * @param range + * @param timestamp + */ + private void updateSlider(TmfTimeRange range, TmfTimestamp timestamp) { + + // Determine the new relative position + byte scale = range.getEndTime().getScale(); + long total = range.getStartTime().getAdjustment(range.getEndTime(), scale); + long relative = range.getStartTime().getAdjustment(timestamp, scale); + + // Set the slider value + final long position = (total > 0) ? (relative * SLIDER_RANGE / total) : 0; + + // Update the slider on the UI thread + long current = fSlider.getSelection(); + if (position != current) { + fSlider.getDisplay().asyncExec(new Runnable() { + public void run() { + fSlider.setSelection((int) position); + } + }); + } + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "[TimeFrameView]"; + } + + // ======================================================================== + // TMF Signal Handling + // ======================================================================== + + /** + * @param signal + */ + @SuppressWarnings("unchecked") + @TmfSignalHandler + public void experimentSelected(TmfExperimentSelectedSignal signal) { + + // Update the trace reference + fExperiment = (TmfExperiment) signal.getExperiment(); + + // Update the time frame + fTraceTimeRange = fExperiment.getTimeRange(); + fTraceStartTime = fTraceTimeRange.getStartTime(); + fTraceEndTime = fTraceTimeRange.getEndTime(); + fScale = fTraceStartTime.getScale(); + + // Update the widgets + fStartGroup.setContent(fTraceTimeRange, fTraceStartTime); + fEndGroup.setContent(fTraceTimeRange, fTraceEndTime); + fCurrentGroup.setContent(fTraceTimeRange, fTraceStartTime); + + fCurrentTime = fTraceStartTime; + + TmfTimestamp delta = new TmfTimestamp(fTraceStartTime.getAdjustment(fTraceEndTime, fScale), fScale, 0); + fTraceSpan = new TmfTimeRange(new TmfTimestamp(0, fScale, 0), delta); +// fRangeGroup.setContent(fTraceSpan, delta); + TmfTimestamp start = new TmfTimestamp(1, (byte) -1, 0); + fRangeGroup.setContent(fTraceSpan, start); + } + + /** + * @param signal + */ + @TmfSignalHandler + public void experimentUpdated(TmfExperimentUpdatedSignal signal) { + + // Update the time frame + fTraceTimeRange = signal.getTrace().getTimeRange(); + fTraceStartTime = fTraceTimeRange.getStartTime(); + fTraceEndTime = fTraceTimeRange.getEndTime(); + fScale = fTraceStartTime.getScale(); + + // Update the widgets + fStartGroup.setContent(fTraceTimeRange, fStartGroup.getCurrentTime()); + fEndGroup.setContent(fTraceTimeRange, fTraceEndTime); + fCurrentGroup.setContent(fTraceTimeRange, fCurrentGroup.getCurrentTime()); + + TmfTimestamp delta = new TmfTimestamp(fTraceStartTime.getAdjustment(fTraceEndTime, fScale), fScale, 0); + fTraceSpan = new TmfTimeRange(new TmfTimestamp(0, fScale, 0), delta); + fRangeGroup.setContent(fTraceSpan, delta); + } + + /** + * @param signal + */ + @TmfSignalHandler + public void currentTimeRangeUpdated(TmfRangeSynchSignal signal) { + if (signal.getSource() != this) { + // Update the time frame + TmfTimeRange selTimeRange = signal.getCurrentRange(); + TmfTimestamp selStart = selTimeRange.getStartTime().synchronize(0, + fScale); + TmfTimestamp selEnd = selTimeRange.getEndTime().synchronize(0, + fScale); + + fupdateExternalListeners = false; + // Update the widgets and prevent broadcast notifications to + // the views which have been notified already. + { + fStartGroup.setContent(fTraceTimeRange, selStart); + fEndGroup.setContent(fTraceTimeRange, selEnd); + + TmfTimestamp delta = new TmfTimestamp(selStart.getAdjustment( + selEnd, fScale), fScale, 0); + + fRangeGroup.setContent(fTraceSpan, delta); + } + + // restore the external notification flag + fupdateExternalListeners = true; + + } + } + + /** + * @param signal + */ + @TmfSignalHandler + public void currentTimeUpdated(TmfTimeSynchSignal signal) { + if (signal.getSource() != this) { + // prevent loop to external notifications + fupdateExternalListeners = false; + fCurrentTime = signal.getCurrentTime().synchronize(0, fStartGroup.getCurrentTime().getScale()); + if (fStartGroup.getCurrentTime().compareTo(fCurrentTime, false) > 0) { + fStartGroup.setContent(new TmfTimeRange(fCurrentTime, fEndGroup.getCurrentTime()), fCurrentTime); + } + if (fEndGroup.getCurrentTime().compareTo(fCurrentTime, false) < 0) { + fEndGroup.setContent(new TmfTimeRange(fStartGroup.getCurrentTime(), fCurrentTime), fCurrentTime); + } + fCurrentGroup.setContent(null, fCurrentTime); + updateSlider(fCurrentGroup.getTimeRange(), fCurrentTime); + + // Enable external notifications + fupdateExternalListeners = true; + } + } + +} \ No newline at end of file -- 2.34.1