From 735b1ca2b2e149bb22d85df231af4239b5e5522d Mon Sep 17 00:00:00 2001 From: Alexandre Montplaisir Date: Tue, 27 Jun 2017 15:09:04 -0400 Subject: [PATCH] Import views plugins From LTTng-Scope commit c5f55ff6c3525a528c60fd6f4589ba47abe7c406. Change-Id: I783e5b54d132cb605b1da3f65dbe8c8db5fe12cd Signed-off-by: Alexandre Montplaisir --- .../.classpath | 15 + tmf/org.lttng.scope.tmf2.views.core/.project | 34 + .../org.eclipse.core.resources.prefs | 2 + .../.settings/org.eclipse.core.runtime.prefs | 2 + .../.settings/org.eclipse.jdt.core.prefs | 436 ++++++++ .../.settings/org.eclipse.jdt.ui.prefs | 65 ++ .../.settings/org.eclipse.pde.api.tools.prefs | 102 ++ .../.settings/org.eclipse.pde.prefs | 32 + .../META-INF/MANIFEST.MF | 38 + .../about.html | 28 + .../build.properties | 18 + .../plugin.properties | 11 + .../views/core/ChangeListenerHandler.java | 59 ++ .../scope/tmf2/views/core/MathUtils.java | 35 + .../scope/tmf2/views/core/NestingBoolean.java | 73 ++ .../scope/tmf2/views/core/TimeRange.java | 154 +++ .../core/activator/internal/Activator.java | 40 + .../core/activator/internal/package-info.java | 11 + .../tmf2/views/core/config/ConfigOption.java | 55 + .../tmf2/views/core/context/SignalBridge.java | 212 ++++ .../views/core/context/ViewGroupContext.java | 210 ++++ .../tmf2/views/core/context/package-info.java | 11 + .../scope/tmf2/views/core/package-info.java | 11 + .../control/TimeGraphModelControl.java | 269 +++++ .../core/timegraph/control/package-info.java | 11 + .../provider/ITimeGraphModelProvider.java | 207 ++++ .../ITimeGraphModelProviderFactory.java | 25 + .../timegraph/model/provider/Messages.java | 33 + .../provider/TimeGraphModelProvider.java | 180 ++++ .../TimeGraphModelProviderManager.java | 99 ++ .../arrows/ITimeGraphModelArrowProvider.java | 76 ++ .../arrows/TimeGraphModelArrowProvider.java | 59 ++ .../model/provider/arrows/package-info.java | 11 + .../ITimeGraphDrawnEventProvider.java | 85 ++ .../TimeGraphDrawnEventProvider.java | 59 ++ .../TimeGraphDrawnEventProviderManager.java | 58 ++ .../provider/drawnevents/package-info.java | 11 + .../model/provider/messages.properties | 10 + .../model/provider/package-info.java | 11 + .../states/ITimeGraphModelStateProvider.java | 94 ++ .../states/TimeGraphModelStateProvider.java | 54 + .../model/provider/states/package-info.java | 11 + .../StateSystemModelArrowProvider.java | 84 ++ .../statesystem/StateSystemModelProvider.java | 204 ++++ .../StateSystemModelStateProvider.java | 318 ++++++ .../StateSystemTimeGraphTreeElement.java | 54 + .../provider/statesystem/package-info.java | 11 + .../model/render/ColorDefinition.java | 113 +++ .../timegraph/model/render/FlatUIColors.java | 52 + .../timegraph/model/render/LineThickness.java | 30 + .../model/render/StateDefinition.java | 69 ++ .../model/render/TimeGraphEvent.java | 82 ++ .../model/render/arrows/TimeGraphArrow.java | 74 ++ .../render/arrows/TimeGraphArrowRender.java | 67 ++ .../render/arrows/TimeGraphArrowSeries.java | 85 ++ .../model/render/arrows/package-info.java | 11 + .../drawnevents/TimeGraphDrawnEvent.java | 86 ++ .../TimeGraphDrawnEventRender.java | 62 ++ .../TimeGraphDrawnEventSeries.java | 97 ++ .../render/drawnevents/package-info.java | 11 + .../timegraph/model/render/package-info.java | 11 + .../states/BasicTimeGraphStateInterval.java | 161 +++ .../render/states/MultiStateInterval.java | 61 ++ .../render/states/TimeGraphStateInterval.java | 127 +++ .../render/states/TimeGraphStateRender.java | 85 ++ .../model/render/states/package-info.java | 11 + .../render/tree/TimeGraphTreeElement.java | 122 +++ .../render/tree/TimeGraphTreeRender.java | 97 ++ .../model/render/tree/package-info.java | 11 + .../timegraph/view/TimeGraphModelView.java | 102 ++ .../timegraph/view/json/RenderToJson.java | 97 ++ .../view/json/TimeGraphJsonOutput.java | 44 + .../timegraph/view/json/package-info.java | 11 + .../core/timegraph/view/package-info.java | 11 + tmf/org.lttng.scope.tmf2.views.ui/.classpath | 15 + tmf/org.lttng.scope.tmf2.views.ui/.project | 34 + .../org.eclipse.core.resources.prefs | 2 + .../.settings/org.eclipse.core.runtime.prefs | 2 + .../.settings/org.eclipse.jdt.core.prefs | 436 ++++++++ .../.settings/org.eclipse.jdt.ui.prefs | 65 ++ .../.settings/org.eclipse.pde.api.tools.prefs | 102 ++ .../.settings/org.eclipse.pde.prefs | 32 + .../META-INF/MANIFEST.MF | 29 + tmf/org.lttng.scope.tmf2.views.ui/about.html | 28 + .../build.properties | 20 + .../icons/toolbar/config.gif | Bin 0 -> 538 bytes .../icons/toolbar/help.gif | Bin 0 -> 259 bytes .../icons/toolbar/legend.gif | Bin 0 -> 200 bytes .../icons/toolbar/nav_arrow_back.gif | Bin 0 -> 204 bytes .../icons/toolbar/nav_arrow_fwd.gif | Bin 0 -> 312 bytes .../icons/toolbar/nav_bookmark_back.gif | Bin 0 -> 554 bytes .../icons/toolbar/nav_bookmark_fwd.gif | Bin 0 -> 556 bytes .../icons/toolbar/nav_event_back.gif | Bin 0 -> 323 bytes .../icons/toolbar/nav_event_fwd.gif | Bin 0 -> 328 bytes .../icons/toolbar/nav_statechange_back.gif | Bin 0 -> 218 bytes .../icons/toolbar/nav_statechange_fwd.gif | Bin 0 -> 326 bytes .../icons/toolbar/zoom_full.gif | Bin 0 -> 583 bytes .../icons/toolbar/zoom_in.gif | Bin 0 -> 560 bytes .../icons/toolbar/zoom_out.gif | Bin 0 -> 560 bytes .../plugin.properties | 13 + tmf/org.lttng.scope.tmf2.views.ui/plugin.xml | 16 + .../ui/activator/internal/Activator.java | 41 + .../ui/activator/internal/package-info.java | 11 + .../lttng/scope/tmf2/views/ui/jfx/Arrow.java | 251 +++++ .../tmf2/views/ui/jfx/CountingGridPane.java | 36 + .../tmf2/views/ui/jfx/JfxColorFactory.java | 70 ++ .../tmf2/views/ui/jfx/JfxImageFactory.java | 71 ++ .../scope/tmf2/views/ui/jfx/JfxUtils.java | 142 +++ .../lttng/scope/tmf2/views/ui/jfx/Logo.java | 76 ++ .../views/ui/jfx/examples/ArrowExample.java | 54 + .../tmf2/views/ui/jfx/examples/Example.java | 61 ++ .../tmf2/views/ui/jfx/examples/Example2.java | 79 ++ .../views/ui/jfx/examples/ExampleCanvas.java | 55 + .../ui/jfx/examples/ExampleMouseDrag.java | 85 ++ .../ui/jfx/examples/ExampleMouseDrag2.java | 382 +++++++ .../ui/jfx/examples/FadeTransitionEx.java | 39 + .../examples/ParallelTransitionExample.java | 74 ++ .../views/ui/jfx/examples/SwtToobar2.java | 78 ++ .../views/ui/jfx/examples/TestSwtToolbar.java | 62 ++ .../views/ui/jfx/examples/ZoomExample.java | 194 ++++ .../views/ui/jfx/examples/application.css | 3 + .../views/ui/jfx/examples/package-info.java | 11 + .../scope/tmf2/views/ui/jfx/package-info.java | 11 + .../tmf2/views/ui/jfx/testapp/DummyTrace.java | 71 ++ .../ui/jfx/testapp/LttngScopeApplication.java | 53 + .../jfx/testapp/TestModelArrowProvider1.java | 68 ++ .../jfx/testapp/TestModelArrowProvider2.java | 64 ++ .../ui/jfx/testapp/TestModelProvider.java | 56 ++ .../jfx/testapp/TestModelStateProvider.java | 79 ++ .../tmf2/views/ui/jfx/testapp/UiModelApp.java | 157 +++ .../views/ui/jfx/testapp/UiModelApp2.java | 175 ++++ .../views/ui/jfx/testapp/package-info.java | 11 + .../tmf2/views/ui/timeline/DebugOptions.java | 164 +++ .../views/ui/timeline/ITimelineWidget.java | 42 + .../tmf2/views/ui/timeline/Messages.java | 34 + .../views/ui/timeline/TimelineManager.java | 121 +++ .../tmf2/views/ui/timeline/TimelineView.java | 82 ++ .../views/ui/timeline/messages.properties | 10 + .../tmf2/views/ui/timeline/package-info.java | 11 + .../widgets/timegraph/LatestTaskExecutor.java | 48 + .../widgets/timegraph/LoadingOverlay.java | 102 ++ .../timeline/widgets/timegraph/Messages.java | 38 + .../widgets/timegraph/PeriodicRedrawTask.java | 89 ++ .../widgets/timegraph/StateRectangle.java | 294 ++++++ .../widgets/timegraph/TimeGraphWidget.java | 946 ++++++++++++++++++ .../timegraph/TimeGraphWidgetTreeArea.java | 284 ++++++ .../widgets/timegraph/VerticalPosition.java | 67 ++ .../timegraph/layer/TimeGraphArrowLayer.java | 194 ++++ .../layer/TimeGraphBackgroundLayer.java | 93 ++ .../layer/TimeGraphDrawnEventLayer.java | 259 +++++ .../timegraph/layer/TimeGraphLayer.java | 89 ++ .../layer/TimeGraphSelectionLayer.java | 232 +++++ .../timegraph/layer/TimeGraphStateLayer.java | 258 +++++ .../widgets/timegraph/layer/package-info.java | 11 + .../widgets/timegraph/messages.properties | 14 + .../widgets/timegraph/package-info.java | 11 + .../toolbar/ArrowSeriesMenuButton.java | 69 ++ .../toolbar/FilterModeMenuButton.java | 62 ++ .../widgets/timegraph/toolbar/Messages.java | 42 + .../toolbar/SortingModeMenuButton.java | 70 ++ .../timegraph/toolbar/ViewerToolBar.java | 106 ++ .../timegraph/toolbar/ZoomInButton.java | 37 + .../timegraph/toolbar/ZoomOutButton.java | 38 + .../toolbar/ZoomToFullRangeButton.java | 39 + .../toolbar/ZoomToSelectionButton.java | 49 + .../toolbar/debugopts/DebugOptionsButton.java | 71 ++ .../toolbar/debugopts/DebugOptionsDialog.java | 319 ++++++ .../timegraph/toolbar/debugopts/Messages.java | 64 ++ .../toolbar/debugopts/messages.properties | 40 + .../toolbar/debugopts/package-info.java | 11 + .../drawnevents/CreateEventSeriesDialog.java | 177 ++++ .../drawnevents/EventSeriesMenuButton.java | 157 +++ .../toolbar/drawnevents/Messages.java | 44 + .../PredicateDrawnEventProvider.java | 136 +++ .../toolbar/drawnevents/messages.properties | 20 + .../toolbar/drawnevents/package-info.java | 11 + .../timegraph/toolbar/messages.properties | 18 + .../toolbar/modelconfig/Messages.java | 42 + .../modelconfig/ModelConfigButton.java | 50 + .../modelconfig/ModelConfigDialog.java | 238 +++++ .../toolbar/modelconfig/messages.properties | 18 + .../toolbar/modelconfig/package-info.java | 11 + .../timegraph/toolbar/nav/Messages.java | 40 + .../timegraph/toolbar/nav/NavUtils.java | 73 ++ .../toolbar/nav/NavigationButtons.java | 157 +++ .../timegraph/toolbar/nav/NavigationMode.java | 100 ++ .../nav/NavigationModeFollowArrows.java | 58 ++ .../nav/NavigationModeFollowBookmarks.java | 55 + .../nav/NavigationModeFollowEvents.java | 117 +++ .../nav/NavigationModeFollowStateChanges.java | 190 ++++ .../timegraph/toolbar/nav/messages.properties | 16 + .../timegraph/toolbar/nav/package-info.java | 11 + .../timegraph/toolbar/package-info.java | 11 + 193 files changed, 15152 insertions(+) create mode 100644 tmf/org.lttng.scope.tmf2.views.core/.classpath create mode 100644 tmf/org.lttng.scope.tmf2.views.core/.project create mode 100644 tmf/org.lttng.scope.tmf2.views.core/.settings/org.eclipse.core.resources.prefs create mode 100644 tmf/org.lttng.scope.tmf2.views.core/.settings/org.eclipse.core.runtime.prefs create mode 100644 tmf/org.lttng.scope.tmf2.views.core/.settings/org.eclipse.jdt.core.prefs create mode 100644 tmf/org.lttng.scope.tmf2.views.core/.settings/org.eclipse.jdt.ui.prefs create mode 100644 tmf/org.lttng.scope.tmf2.views.core/.settings/org.eclipse.pde.api.tools.prefs create mode 100644 tmf/org.lttng.scope.tmf2.views.core/.settings/org.eclipse.pde.prefs create mode 100644 tmf/org.lttng.scope.tmf2.views.core/META-INF/MANIFEST.MF create mode 100644 tmf/org.lttng.scope.tmf2.views.core/about.html create mode 100644 tmf/org.lttng.scope.tmf2.views.core/build.properties create mode 100644 tmf/org.lttng.scope.tmf2.views.core/plugin.properties create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/ChangeListenerHandler.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/MathUtils.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/NestingBoolean.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/TimeRange.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/activator/internal/Activator.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/activator/internal/package-info.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/config/ConfigOption.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/context/SignalBridge.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/context/ViewGroupContext.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/context/package-info.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/package-info.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/control/TimeGraphModelControl.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/control/package-info.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/ITimeGraphModelProvider.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/ITimeGraphModelProviderFactory.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/Messages.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/TimeGraphModelProvider.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/TimeGraphModelProviderManager.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/arrows/ITimeGraphModelArrowProvider.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/arrows/TimeGraphModelArrowProvider.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/arrows/package-info.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/drawnevents/ITimeGraphDrawnEventProvider.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/drawnevents/TimeGraphDrawnEventProvider.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/drawnevents/TimeGraphDrawnEventProviderManager.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/drawnevents/package-info.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/messages.properties create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/package-info.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/states/ITimeGraphModelStateProvider.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/states/TimeGraphModelStateProvider.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/states/package-info.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/statesystem/StateSystemModelArrowProvider.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/statesystem/StateSystemModelProvider.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/statesystem/StateSystemModelStateProvider.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/statesystem/StateSystemTimeGraphTreeElement.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/statesystem/package-info.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/ColorDefinition.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/FlatUIColors.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/LineThickness.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/StateDefinition.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/TimeGraphEvent.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/arrows/TimeGraphArrow.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/arrows/TimeGraphArrowRender.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/arrows/TimeGraphArrowSeries.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/arrows/package-info.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/drawnevents/TimeGraphDrawnEvent.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/drawnevents/TimeGraphDrawnEventRender.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/drawnevents/TimeGraphDrawnEventSeries.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/drawnevents/package-info.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/package-info.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/states/BasicTimeGraphStateInterval.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/states/MultiStateInterval.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/states/TimeGraphStateInterval.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/states/TimeGraphStateRender.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/states/package-info.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/tree/TimeGraphTreeElement.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/tree/TimeGraphTreeRender.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/tree/package-info.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/view/TimeGraphModelView.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/view/json/RenderToJson.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/view/json/TimeGraphJsonOutput.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/view/json/package-info.java create mode 100644 tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/view/package-info.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/.classpath create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/.project create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/.settings/org.eclipse.core.resources.prefs create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/.settings/org.eclipse.core.runtime.prefs create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/.settings/org.eclipse.jdt.core.prefs create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/.settings/org.eclipse.jdt.ui.prefs create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/.settings/org.eclipse.pde.api.tools.prefs create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/.settings/org.eclipse.pde.prefs create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/META-INF/MANIFEST.MF create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/about.html create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/build.properties create mode 100755 tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/config.gif create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/help.gif create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/legend.gif create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/nav_arrow_back.gif create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/nav_arrow_fwd.gif create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/nav_bookmark_back.gif create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/nav_bookmark_fwd.gif create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/nav_event_back.gif create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/nav_event_fwd.gif create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/nav_statechange_back.gif create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/nav_statechange_fwd.gif create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/zoom_full.gif create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/zoom_in.gif create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/zoom_out.gif create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/plugin.properties create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/plugin.xml create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/activator/internal/Activator.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/activator/internal/package-info.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/Arrow.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/CountingGridPane.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/JfxColorFactory.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/JfxImageFactory.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/JfxUtils.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/Logo.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/ArrowExample.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/Example.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/Example2.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/ExampleCanvas.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/ExampleMouseDrag.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/ExampleMouseDrag2.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/FadeTransitionEx.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/ParallelTransitionExample.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/SwtToobar2.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/TestSwtToolbar.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/ZoomExample.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/application.css create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/package-info.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/package-info.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/DummyTrace.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/LttngScopeApplication.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/TestModelArrowProvider1.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/TestModelArrowProvider2.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/TestModelProvider.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/TestModelStateProvider.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/UiModelApp.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/UiModelApp2.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/package-info.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/DebugOptions.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/ITimelineWidget.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/Messages.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/TimelineManager.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/TimelineView.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/messages.properties create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/package-info.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/LatestTaskExecutor.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/LoadingOverlay.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/Messages.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/PeriodicRedrawTask.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/StateRectangle.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/TimeGraphWidget.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/TimeGraphWidgetTreeArea.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/VerticalPosition.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/layer/TimeGraphArrowLayer.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/layer/TimeGraphBackgroundLayer.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/layer/TimeGraphDrawnEventLayer.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/layer/TimeGraphLayer.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/layer/TimeGraphSelectionLayer.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/layer/TimeGraphStateLayer.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/layer/package-info.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/messages.properties create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/package-info.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/ArrowSeriesMenuButton.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/FilterModeMenuButton.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/Messages.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/SortingModeMenuButton.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/ViewerToolBar.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/ZoomInButton.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/ZoomOutButton.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/ZoomToFullRangeButton.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/ZoomToSelectionButton.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/debugopts/DebugOptionsButton.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/debugopts/DebugOptionsDialog.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/debugopts/Messages.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/debugopts/messages.properties create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/debugopts/package-info.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/drawnevents/CreateEventSeriesDialog.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/drawnevents/EventSeriesMenuButton.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/drawnevents/Messages.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/drawnevents/PredicateDrawnEventProvider.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/drawnevents/messages.properties create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/drawnevents/package-info.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/messages.properties create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/modelconfig/Messages.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/modelconfig/ModelConfigButton.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/modelconfig/ModelConfigDialog.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/modelconfig/messages.properties create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/modelconfig/package-info.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/nav/Messages.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/nav/NavUtils.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/nav/NavigationButtons.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/nav/NavigationMode.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/nav/NavigationModeFollowArrows.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/nav/NavigationModeFollowBookmarks.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/nav/NavigationModeFollowEvents.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/nav/NavigationModeFollowStateChanges.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/nav/messages.properties create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/nav/package-info.java create mode 100644 tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/toolbar/package-info.java diff --git a/tmf/org.lttng.scope.tmf2.views.core/.classpath b/tmf/org.lttng.scope.tmf2.views.core/.classpath new file mode 100644 index 0000000000..0be7b35db4 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/.classpath @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/tmf/org.lttng.scope.tmf2.views.core/.project b/tmf/org.lttng.scope.tmf2.views.core/.project new file mode 100644 index 0000000000..971601e8c6 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/.project @@ -0,0 +1,34 @@ + + + org.lttng.scope.tmf2.views.core + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.pde.api.tools.apiAnalysisBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + org.eclipse.pde.api.tools.apiAnalysisNature + + diff --git a/tmf/org.lttng.scope.tmf2.views.core/.settings/org.eclipse.core.resources.prefs b/tmf/org.lttng.scope.tmf2.views.core/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000000..99f26c0203 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/tmf/org.lttng.scope.tmf2.views.core/.settings/org.eclipse.core.runtime.prefs b/tmf/org.lttng.scope.tmf2.views.core/.settings/org.eclipse.core.runtime.prefs new file mode 100644 index 0000000000..5a0ad22d2a --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/.settings/org.eclipse.core.runtime.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +line.separator=\n diff --git a/tmf/org.lttng.scope.tmf2.views.core/.settings/org.eclipse.jdt.core.prefs b/tmf/org.lttng.scope.tmf2.views.core/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..bf5f566b99 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,436 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.codeComplete.argumentPrefixes= +org.eclipse.jdt.core.codeComplete.argumentSuffixes= +org.eclipse.jdt.core.codeComplete.fieldPrefixes=f +org.eclipse.jdt.core.codeComplete.fieldSuffixes= +org.eclipse.jdt.core.codeComplete.localPrefixes= +org.eclipse.jdt.core.codeComplete.localSuffixes= +org.eclipse.jdt.core.codeComplete.staticFieldPrefixes= +org.eclipse.jdt.core.codeComplete.staticFieldSuffixes= +org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes= +org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes= +org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=enabled +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=info +org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnull.secondary= +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary= +org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable +org.eclipse.jdt.core.compiler.annotation.nullable.secondary= +org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.doc.comment.support=enabled +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=error +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=error +org.eclipse.jdt.core.compiler.problem.deadCode=error +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=error +org.eclipse.jdt.core.compiler.problem.fallthroughCase=error +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=error +org.eclipse.jdt.core.compiler.problem.finalParameterBound=error +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=error +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=error +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=error +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=error +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=error +org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning +org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=protected +org.eclipse.jdt.core.compiler.problem.localVariableHiding=error +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error +org.eclipse.jdt.core.compiler.problem.missingDefaultCase=error +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=error +org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=enabled +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=error +org.eclipse.jdt.core.compiler.problem.missingJavadocComments=warning +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=protected +org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=all_standard_tags +org.eclipse.jdt.core.compiler.problem.missingJavadocTags=warning +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=protected +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=error +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=error +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=error +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=error +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning +org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning +org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=info +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=warning +org.eclipse.jdt.core.compiler.problem.nullReference=error +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=error +org.eclipse.jdt.core.compiler.problem.parameterAssignment=error +org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error +org.eclipse.jdt.core.compiler.problem.potentialNullReference=error +org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=error +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=error +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=error +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=error +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=error +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unclosedCloseable=error +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=error +org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning +org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled +org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=error +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=error +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=disabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=disabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=error +org.eclipse.jdt.core.compiler.problem.unusedLocal=error +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameter=warning +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=warning +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error +org.eclipse.jdt.core.compiler.source=1.8 +org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header=0 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_type_arguments=0 +org.eclipse.jdt.core.formatter.alignment_for_type_parameters=0 +org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=true +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert +org.eclipse.jdt.core.formatter.comment.line_length=80 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=2 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false +org.eclipse.jdt.core.formatter.indentation.size=4 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=true +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=250 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause=common_lines +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_on_off_tags=false +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_assignment_operator=false +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_before_conditional_operator=true +org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true +org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter diff --git a/tmf/org.lttng.scope.tmf2.views.core/.settings/org.eclipse.jdt.ui.prefs b/tmf/org.lttng.scope.tmf2.views.core/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 0000000000..2591ac9163 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,65 @@ +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +formatter_profile=_tmf-style +formatter_settings_version=12 +org.eclipse.jdt.ui.exception.name=e +org.eclipse.jdt.ui.gettersetter.use.is=true +org.eclipse.jdt.ui.keywordthis=false +org.eclipse.jdt.ui.overrideannotation=true +sp_cleanup.add_default_serial_version_id=true +sp_cleanup.add_generated_serial_version_id=false +sp_cleanup.add_missing_annotations=false +sp_cleanup.add_missing_deprecated_annotations=true +sp_cleanup.add_missing_methods=false +sp_cleanup.add_missing_nls_tags=false +sp_cleanup.add_missing_override_annotations=true +sp_cleanup.add_missing_override_annotations_interface_methods=true +sp_cleanup.add_serial_version_id=false +sp_cleanup.always_use_blocks=true +sp_cleanup.always_use_parentheses_in_expressions=false +sp_cleanup.always_use_this_for_non_static_field_access=false +sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.convert_functional_interfaces=false +sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.correct_indentation=false +sp_cleanup.format_source_code=false +sp_cleanup.format_source_code_changes_only=false +sp_cleanup.insert_inferred_type_arguments=false +sp_cleanup.make_local_variable_final=false +sp_cleanup.make_parameters_final=false +sp_cleanup.make_private_fields_final=true +sp_cleanup.make_type_abstract_if_missing_method=false +sp_cleanup.make_variable_declarations_final=false +sp_cleanup.never_use_blocks=false +sp_cleanup.never_use_parentheses_in_expressions=true +sp_cleanup.on_save_use_additional_actions=true +sp_cleanup.organize_imports=true +sp_cleanup.qualify_static_field_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_redundant_type_arguments=false +sp_cleanup.remove_trailing_whitespaces=true +sp_cleanup.remove_trailing_whitespaces_all=true +sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +sp_cleanup.remove_unnecessary_casts=false +sp_cleanup.remove_unnecessary_nls_tags=false +sp_cleanup.remove_unused_imports=false +sp_cleanup.remove_unused_local_variables=false +sp_cleanup.remove_unused_private_fields=true +sp_cleanup.remove_unused_private_members=false +sp_cleanup.remove_unused_private_methods=true +sp_cleanup.remove_unused_private_types=true +sp_cleanup.sort_members=false +sp_cleanup.sort_members_all=false +sp_cleanup.use_anonymous_class_creation=false +sp_cleanup.use_blocks=true +sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_lambda=true +sp_cleanup.use_parentheses_in_expressions=false +sp_cleanup.use_this_for_non_static_field_access=false +sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true +sp_cleanup.use_this_for_non_static_method_access=false +sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/tmf/org.lttng.scope.tmf2.views.core/.settings/org.eclipse.pde.api.tools.prefs b/tmf/org.lttng.scope.tmf2.views.core/.settings/org.eclipse.pde.api.tools.prefs new file mode 100644 index 0000000000..ce92bf3ae1 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/.settings/org.eclipse.pde.api.tools.prefs @@ -0,0 +1,102 @@ +ANNOTATION_ELEMENT_TYPE_ADDED_METHOD_WITHOUT_DEFAULT_VALUE=Error +ANNOTATION_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error +ANNOTATION_ELEMENT_TYPE_REMOVED_FIELD=Error +ANNOTATION_ELEMENT_TYPE_REMOVED_METHOD=Error +ANNOTATION_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error +API_COMPONENT_ELEMENT_TYPE_REMOVED_API_TYPE=Error +API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_API_TYPE=Error +API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_TYPE=Error +API_COMPONENT_ELEMENT_TYPE_REMOVED_TYPE=Error +API_USE_SCAN_FIELD_SEVERITY=Error +API_USE_SCAN_METHOD_SEVERITY=Error +API_USE_SCAN_TYPE_SEVERITY=Error +CLASS_ELEMENT_TYPE_ADDED_METHOD=Error +CLASS_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error +CLASS_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error +CLASS_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error +CLASS_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error +CLASS_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error +CLASS_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error +CLASS_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error +CLASS_ELEMENT_TYPE_REMOVED_CONSTRUCTOR=Error +CLASS_ELEMENT_TYPE_REMOVED_FIELD=Error +CLASS_ELEMENT_TYPE_REMOVED_METHOD=Error +CLASS_ELEMENT_TYPE_REMOVED_SUPERCLASS=Error +CLASS_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error +CLASS_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error +CONSTRUCTOR_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error +CONSTRUCTOR_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error +CONSTRUCTOR_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error +CONSTRUCTOR_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error +ENUM_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error +ENUM_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error +ENUM_ELEMENT_TYPE_REMOVED_ENUM_CONSTANT=Error +ENUM_ELEMENT_TYPE_REMOVED_FIELD=Error +ENUM_ELEMENT_TYPE_REMOVED_METHOD=Error +ENUM_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error +FIELD_ELEMENT_TYPE_ADDED_VALUE=Error +FIELD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error +FIELD_ELEMENT_TYPE_CHANGED_FINAL_TO_NON_FINAL_STATIC_CONSTANT=Error +FIELD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error +FIELD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error +FIELD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error +FIELD_ELEMENT_TYPE_CHANGED_TYPE=Error +FIELD_ELEMENT_TYPE_CHANGED_VALUE=Error +FIELD_ELEMENT_TYPE_REMOVED_TYPE_ARGUMENT=Error +FIELD_ELEMENT_TYPE_REMOVED_VALUE=Error +ILLEGAL_EXTEND=Warning +ILLEGAL_IMPLEMENT=Warning +ILLEGAL_INSTANTIATE=Warning +ILLEGAL_OVERRIDE=Warning +ILLEGAL_REFERENCE=Warning +INTERFACE_ELEMENT_TYPE_ADDED_DEFAULT_METHOD=Ignore +INTERFACE_ELEMENT_TYPE_ADDED_FIELD=Error +INTERFACE_ELEMENT_TYPE_ADDED_METHOD=Error +INTERFACE_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error +INTERFACE_ELEMENT_TYPE_ADDED_SUPER_INTERFACE_WITH_METHODS=Error +INTERFACE_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error +INTERFACE_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error +INTERFACE_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error +INTERFACE_ELEMENT_TYPE_REMOVED_FIELD=Error +INTERFACE_ELEMENT_TYPE_REMOVED_METHOD=Error +INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error +INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error +INVALID_ANNOTATION=Warning +INVALID_JAVADOC_TAG=Warning +INVALID_REFERENCE_IN_SYSTEM_LIBRARIES=Warning +LEAK_EXTEND=Warning +LEAK_FIELD_DECL=Warning +LEAK_IMPLEMENT=Warning +LEAK_METHOD_PARAM=Warning +LEAK_METHOD_RETURN_TYPE=Warning +METHOD_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error +METHOD_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error +METHOD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error +METHOD_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error +METHOD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error +METHOD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error +METHOD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error +METHOD_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error +METHOD_ELEMENT_TYPE_REMOVED_ANNOTATION_DEFAULT_VALUE=Error +METHOD_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error +MISSING_EE_DESCRIPTIONS=Ignore +TYPE_PARAMETER_ELEMENT_TYPE_ADDED_CLASS_BOUND=Error +TYPE_PARAMETER_ELEMENT_TYPE_ADDED_INTERFACE_BOUND=Error +TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_CLASS_BOUND=Error +TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_INTERFACE_BOUND=Error +TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_CLASS_BOUND=Error +TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_INTERFACE_BOUND=Error +UNUSED_PROBLEM_FILTERS=Warning +automatically_removed_unused_problem_filters=false +changed_execution_env=Error +eclipse.preferences.version=1 +incompatible_api_component_version=Error +incompatible_api_component_version_include_major_without_breaking_change=Disabled +incompatible_api_component_version_include_minor_without_api_change=Disabled +incompatible_api_component_version_report_major_without_breaking_change=Warning +incompatible_api_component_version_report_minor_without_api_change=Warning +invalid_since_tag_version=Error +malformed_since_tag=Error +missing_since_tag=Error +report_api_breakage_when_major_version_incremented=Disabled +report_resolution_errors_api_component=Warning diff --git a/tmf/org.lttng.scope.tmf2.views.core/.settings/org.eclipse.pde.prefs b/tmf/org.lttng.scope.tmf2.views.core/.settings/org.eclipse.pde.prefs new file mode 100644 index 0000000000..01d624df11 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/.settings/org.eclipse.pde.prefs @@ -0,0 +1,32 @@ +compilers.f.unresolved-features=1 +compilers.f.unresolved-plugins=1 +compilers.incompatible-environment=1 +compilers.p.build=1 +compilers.p.build.bin.includes=0 +compilers.p.build.encodings=2 +compilers.p.build.java.compiler=2 +compilers.p.build.java.compliance=1 +compilers.p.build.missing.output=2 +compilers.p.build.output.library=1 +compilers.p.build.source.library=0 +compilers.p.build.src.includes=0 +compilers.p.deprecated=1 +compilers.p.discouraged-class=1 +compilers.p.internal=1 +compilers.p.missing-packages=1 +compilers.p.missing-version-export-package=2 +compilers.p.missing-version-import-package=2 +compilers.p.missing-version-require-bundle=2 +compilers.p.no-required-att=0 +compilers.p.not-externalized-att=1 +compilers.p.unknown-attribute=1 +compilers.p.unknown-class=1 +compilers.p.unknown-element=1 +compilers.p.unknown-identifier=1 +compilers.p.unknown-resource=1 +compilers.p.unresolved-ex-points=0 +compilers.p.unresolved-import=0 +compilers.s.create-docs=false +compilers.s.doc-folder=doc +compilers.s.open-tags=1 +eclipse.preferences.version=1 diff --git a/tmf/org.lttng.scope.tmf2.views.core/META-INF/MANIFEST.MF b/tmf/org.lttng.scope.tmf2.views.core/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..ae32157d62 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/META-INF/MANIFEST.MF @@ -0,0 +1,38 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %Bundle-Name +Bundle-Vendor: %Bundle-Vendor +Bundle-Version: 0.2.0.qualifier +Bundle-Localization: plugin +Bundle-SymbolicName: org.lttng.scope.tmf2.views.core;singleton:=true +Bundle-Activator: org.lttng.scope.tmf2.views.core.activator.internal.Activator +Bundle-ActivationPolicy: lazy +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Eclipse-ExtensibleAPI: true +Require-Bundle: org.eclipse.core.runtime, + org.eclipse.core.resources, + org.lttng.scope.common.core, + ca.polymtl.dorsal.libdelorean, + org.eclipse.tracecompass.tmf.core +Export-Package: org.lttng.scope.tmf2.views.core, + org.lttng.scope.tmf2.views.core.activator.internal;x-internal:=true, + org.lttng.scope.tmf2.views.core.config, + org.lttng.scope.tmf2.views.core.context, + org.lttng.scope.tmf2.views.core.timegraph.control, + org.lttng.scope.tmf2.views.core.timegraph.model.provider, + org.lttng.scope.tmf2.views.core.timegraph.model.provider.arrows, + org.lttng.scope.tmf2.views.core.timegraph.model.provider.drawnevents, + org.lttng.scope.tmf2.views.core.timegraph.model.provider.states, + org.lttng.scope.tmf2.views.core.timegraph.model.provider.statesystem, + org.lttng.scope.tmf2.views.core.timegraph.model.render, + org.lttng.scope.tmf2.views.core.timegraph.model.render.arrows, + org.lttng.scope.tmf2.views.core.timegraph.model.render.drawnevents, + org.lttng.scope.tmf2.views.core.timegraph.model.render.states, + org.lttng.scope.tmf2.views.core.timegraph.model.render.tree, + org.lttng.scope.tmf2.views.core.timegraph.view, + org.lttng.scope.tmf2.views.core.timegraph.view.json +Import-Package: com.google.common.annotations;version="15.0.0", + com.google.common.base, + com.google.common.collect, + com.google.gson, + org.json diff --git a/tmf/org.lttng.scope.tmf2.views.core/about.html b/tmf/org.lttng.scope.tmf2.views.core/about.html new file mode 100644 index 0000000000..28737f60b7 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/about.html @@ -0,0 +1,28 @@ + + + + +About + + +

About This Content

+ +

June 5, 2006

+

License

+ +

The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise +indicated below, the Content is provided to you under the terms and conditions of the +Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available +at http://www.eclipse.org/legal/epl-v10.html. +For purposes of the EPL, "Program" will mean the Content.

+ +

If you did not receive this Content directly from the Eclipse Foundation, the Content is +being redistributed by another party ("Redistributor") and different terms and conditions may +apply to your use of any object code in the Content. Check the Redistributor's license that was +provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise +indicated below, the terms and conditions of the EPL still apply to any source code in the Content +and such source code may be obtained at http://www.eclipse.org.

+ + + \ No newline at end of file diff --git a/tmf/org.lttng.scope.tmf2.views.core/build.properties b/tmf/org.lttng.scope.tmf2.views.core/build.properties new file mode 100644 index 0000000000..e08e216e55 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/build.properties @@ -0,0 +1,18 @@ +############################################################################### +# Copyright (C) 2017 EfficiOS Inc. +# +# 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 +############################################################################### + +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + plugin.properties,\ + about.html,\ + . +src.includes = about.html +additional.bundles = org.eclipse.jdt.annotation +jars.extra.classpath = platform:/plugin/org.eclipse.jdt.annotation diff --git a/tmf/org.lttng.scope.tmf2.views.core/plugin.properties b/tmf/org.lttng.scope.tmf2.views.core/plugin.properties new file mode 100644 index 0000000000..92fd267fa8 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/plugin.properties @@ -0,0 +1,11 @@ +############################################################################### +# Copyright (C) 2017 EfficiOS Inc. +# +# 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 +############################################################################### + +Bundle-Vendor = LTTng Scope +Bundle-Name = LTTng Scope TMF2 Core Plug-in diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/ChangeListenerHandler.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/ChangeListenerHandler.java new file mode 100644 index 0000000000..c2ddb73cb8 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/ChangeListenerHandler.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.core; + +import javafx.beans.property.Property; +import javafx.beans.value.ChangeListener; + +/** + * Simple class encapsulating a {@link ChangeListener} and its target property. + * It allows disabling and re-enabling the listener, by simply detaching it from + * its target, on demand. The calling class then only has one class to manage + * (this handler) instead of two. + * + * @author Alexandre Montplaisir + * + * @param + * The type of property + */ +public final class ChangeListenerHandler { + + private final Property fTarget; + private final ChangeListener fListener; + + /** + * Build a new listener handler. The listener will be added to the target + * (enabled). + * + * @param target + * The target property + * @param listener + * The listener + */ + public ChangeListenerHandler(Property target, ChangeListener listener) { + fTarget = target; + fListener = listener; + enable(); + } + + /** + * Attach the listener to its property, re-enabling it. + */ + public void enable() { + fTarget.addListener(fListener); + } + + /** + * Detach the listener from its property, disabling it. + */ + public void disable() { + fTarget.removeListener(fListener); + } +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/MathUtils.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/MathUtils.java new file mode 100644 index 0000000000..1ba0008793 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/MathUtils.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.core; + +/** + * Uncommon math utility methods. + * + * @author Alexandre Montplaisir + */ +public final class MathUtils { + + private MathUtils() {} + + /** + * Find the multiple of 'multipleOf' that is greater but closest to + * 'number'. If 'number' is already a multiple of 'multipleOf', the same + * value will be returned. + * + * @param number + * The starting number + * @param multipleOf + * We want the returned value to be a multiple of this number + * @return The closest, greater multiple + */ + public static long roundToClosestHigherMultiple(long number, long multipleOf) { + return (long) (Math.ceil((double) number / multipleOf) * multipleOf); + } +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/NestingBoolean.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/NestingBoolean.java new file mode 100644 index 0000000000..7155de4d3f --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/NestingBoolean.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.core; + +import java.util.concurrent.atomic.AtomicInteger; + +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.ReadOnlyBooleanProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.value.ChangeListener; + +/** + * Utility class that serves as a wrapper around a single boolean flag that can + * be enabled/disabled. It counts the number of times {@link #disable()} is + * called, and only really re-enables the inner value when {@link #enable()} is + * called that many times. + * + * It is meant to be useful in multi-thread scenarios, where concurrent + * "critical sections" may want to disable something like a listener, and not + * have it really be re-enabled until all critical sections are finished. Thus + * it is thread-safe. + * + * The inner value is exposed through the {@link #enabledProperty()} method, which + * returns a {@link ReadOnlyBooleanProperty}. You can attach + * {@link ChangeListener}s to that property to get notified of inner value + * changes. + * + * It is "enabled" at creation time. + * + * @author Alexandre Montplaisir + */ +public class NestingBoolean { + + private final AtomicInteger fDisabledCount = new AtomicInteger(0); + private final BooleanProperty fBoolean = new SimpleBooleanProperty(true); + + /** + * Decrease the "disabled" count by 1. If it reaches (or already was at) 0 + * then the value is truly enabled. + */ + public synchronized void enable() { + /* Decrement the count but only if it is currently above 0 */ + int ret = fDisabledCount.updateAndGet(value -> value > 0 ? value - 1 : 0); + if (ret == 0) { + fBoolean.set(true); + } + } + + /** + * Increase the "disabled" count by 1. The inner value will necessarily be + * disabled after this call. + */ + public synchronized void disable() { + fDisabledCount.incrementAndGet(); + fBoolean.set(false); + } + + /** + * Property representing the inner boolean value. + * + * @return The inner value + */ + public ReadOnlyBooleanProperty enabledProperty() { + return fBoolean; + } +} \ No newline at end of file diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/TimeRange.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/TimeRange.java new file mode 100644 index 0000000000..229b756e73 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/TimeRange.java @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.core; + +import java.util.Objects; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange; +import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp; + +import com.google.common.base.MoreObjects; + +/** + * Simple class representing a time range, encapsulating two timestamps stored + * as long's. + * + * @author Alexandre Montplaisir + */ +public final class TimeRange { + + private final long fStartTime; + private final long fEndTime; + + private TimeRange(long startTime, long endTime) { + if (endTime < startTime) { + throw new IllegalArgumentException("End of time range earlier than the start:[" + startTime + ", " + endTime + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + if (startTime < 0 || endTime < 0) { + throw new IllegalArgumentException("One of the bounds is negative:[" + startTime + ", " + endTime + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + fStartTime = startTime; + fEndTime = endTime; + } + + /** + * Factory method, creating a new time range from its start and end. + * + * @param startTime + * The start time of the range + * @param endTime + * The end time of the range. Should be equal or greater than the + * start time. + * @return The new time range + */ + public static TimeRange of(long startTime, long endTime) { + // TODO Implement caching? + return new TimeRange(startTime, endTime); + } + + /** + * Get the range's start time + * + * @return The start time + */ + public long getStart() { + return fStartTime; + } + + /** + * Get the range's end time + * + * @return The end time + */ + public long getEnd() { + return fEndTime; + } + + /** + * Get the duration, or "span", of this time range. + * + * @return The duration + */ + public long getDuration() { + return (fEndTime - fStartTime); + } + + /** + * Check if this time range contains, inclusively, the given timestamp. + * + * @param timestamp + * The timestamp to check + * @return True if the timestamp is contained in the range, false otherwise + */ + public boolean contains(long timestamp) { + return (fStartTime <= timestamp && timestamp <= fEndTime); + } + + /** + * Check if the bounds of this time range are the exact same one (single + * timestamp). + * + * @return If this range represents a single timestamp + */ + public boolean isSingleTimestamp() { + return (fStartTime == fEndTime); + } + + @Override + public int hashCode() { + return Objects.hash(fStartTime, fEndTime); + } + + @Override + public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + TimeRange other = (TimeRange) obj; + return (fStartTime == other.fStartTime + && fEndTime == other.fEndTime); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("start", fStartTime) //$NON-NLS-1$ + .add("end", fEndTime) //$NON-NLS-1$ + .toString(); + } + + /** + * Convert this range into a {@link TmfTimeRange}. + * + * @return The equivalent TmfTimeRange + */ + public TmfTimeRange toTmfTimeRange() { + return new TmfTimeRange(TmfTimestamp.fromNanos(fStartTime), TmfTimestamp.fromNanos(fEndTime)); + } + + /** + * Create a {@link TimeRange} from a {@link TmfTimeRange}. + * + * @param range + * The TmfTimeRange + * @return The TimeRange + */ + public static TimeRange fromTmfTimeRange(TmfTimeRange range) { + return new TimeRange(range.getStartTime().toNanos(), range.getEndTime().toNanos()); + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/activator/internal/Activator.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/activator/internal/Activator.java new file mode 100644 index 0000000000..c65947995f --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/activator/internal/Activator.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.core.activator.internal; + +import org.lttng.scope.common.core.ScopeCoreActivator; +import org.lttng.scope.tmf2.views.core.context.ViewGroupContext; + +/** + * Plugin activator + * + * @noreference This class should not be accessed outside of this plugin. + */ +public class Activator extends ScopeCoreActivator { + + /** + * Return the singleton instance of this activator. + * + * @return The singleton instance + */ + public static Activator instance() { + return ScopeCoreActivator.getInstance(Activator.class); + } + + @Override + protected void startActions() { + } + + @Override + protected void stopActions() { + ViewGroupContext.cleanup(); + } + +} \ No newline at end of file diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/activator/internal/package-info.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/activator/internal/package-info.java new file mode 100644 index 0000000000..bcfea26b49 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/activator/internal/package-info.java @@ -0,0 +1,11 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +@org.eclipse.jdt.annotation.NonNullByDefault +package org.lttng.scope.tmf2.views.core.activator.internal; diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/config/ConfigOption.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/config/ConfigOption.java new file mode 100644 index 0000000000..627f561031 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/config/ConfigOption.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.core.config; + +import javafx.beans.property.SimpleObjectProperty; + +/** + * Configuration option, which is basically a JavaFX property with a default + * value. + * + * @author Alexandre Montplaisir + * + * @param + * The type of property + */ +public class ConfigOption extends SimpleObjectProperty { + + private final T fDefaultValue; + + /** + * Constructor + * + * @param defaultValue + * The initial and default value + */ + public ConfigOption(T defaultValue) { + super(defaultValue); + fDefaultValue = defaultValue; + } + + /** + * Retrieve the default value of this option. This does not modify the + * current value. + * + * @return The default value + */ + public T getDefaultValue() { + return fDefaultValue; + } + + /** + * Reset the current value to its default. + */ + public void resetToDefault() { + set(fDefaultValue); + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/context/SignalBridge.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/context/SignalBridge.java new file mode 100644 index 0000000000..f861514548 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/context/SignalBridge.java @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.core.context; + +import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal; +import org.eclipse.tracecompass.tmf.core.signal.TmfSignal; +import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler; +import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager; +import org.eclipse.tracecompass.tmf.core.signal.TmfSignalThrottler; +import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal; +import org.eclipse.tracecompass.tmf.core.signal.TmfTraceRangeUpdatedSignal; +import org.eclipse.tracecompass.tmf.core.signal.TmfTraceSelectedSignal; +import org.eclipse.tracecompass.tmf.core.signal.TmfWindowRangeUpdatedSignal; +import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp; +import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange; +import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager; +import org.lttng.scope.tmf2.views.core.TimeRange; + +/** + * Bridge between a {@link ViewGroupContext} and the {@link TmfSignalManager}. + * It sends equivalent "signals" back-and-forth between the two APIs. + * + * Note: Needs to be public because of the way TmfSignalManager works. + * + * @author Alexandre Montplaisir + */ +public class SignalBridge { + + private static final int SIGNAL_DELAY_MS = 200; + + private final TmfSignalThrottler fVisibleRangeSignalThrottler = new TmfSignalThrottler(null, SIGNAL_DELAY_MS); + + private final ViewGroupContext fViewContext; + + /** + * Constructor + * + * @param viewContext + * The view context this bridge will connect to + */ + public SignalBridge(ViewGroupContext viewContext) { + TmfSignalManager.register(this); + fViewContext = viewContext; + + viewContext.currentTraceProperty().addListener((obs, oldTrace, newTrace) -> { + if (newTrace == null) { + return; + } + TmfSignal newTraceSignal = new TmfTraceSelectedSignal(SignalBridge.this, newTrace); + TmfSignalManager.dispatchSignal(newTraceSignal); + + viewContext.currentTraceFullRangeProperty().addListener((observable, oldRange, newRange) -> { + TmfTimeRange tmfTimeRange = newRange.toTmfTimeRange(); + TmfSignal signal = new TmfTraceRangeUpdatedSignal(SignalBridge.this, viewContext.getCurrentTrace(), tmfTimeRange); + TmfSignalManager.dispatchSignal(signal); + }); + + viewContext.currentVisibleTimeRangeProperty().addListener((observable, oldRange, newRange) -> { + TmfTimeRange tmfTimeRange = newRange.toTmfTimeRange(); + TmfSignal signal = new TmfWindowRangeUpdatedSignal(SignalBridge.this, tmfTimeRange); + fVisibleRangeSignalThrottler.queue(signal); + }); + + viewContext.currentSelectionTimeRangeProperty().addListener((observable, oldRange, newRange) -> { + TmfSignal signal; + if (newRange.isSingleTimestamp()) { + ITmfTimestamp ts = TmfTimestamp.fromNanos(newRange.getStart()); + signal = new TmfSelectionRangeUpdatedSignal(SignalBridge.this, ts); + } else { + ITmfTimestamp startTs = TmfTimestamp.fromNanos(newRange.getStart()); + ITmfTimestamp endTs = TmfTimestamp.fromNanos(newRange.getEnd()); + signal = new TmfSelectionRangeUpdatedSignal(SignalBridge.this, startTs, endTs); + } + TmfSignalManager.dispatchSignal(signal); + }); + + }); + } + + /** + * Dispose of this bridge, deregistering it from the signal manager. + */ + public void dispose() { + TmfSignalManager.deregister(this); + } + + // ------------------------------------------------------------------------ + // Signal handlers + // ------------------------------------------------------------------------ + + /** + * Handler for the trace selected signal + * + * @param signal + * Received signal + */ + @TmfSignalHandler + public void traceSelected(final TmfTraceSelectedSignal signal) { + if (signal.getSource() == this) { + return; + } + ITmfTrace trace = signal.getTrace(); + fViewContext.setCurrentTrace(trace); + } + + /** + * Handler for the trace closed signal + * + * @param signal + * Received signal + */ + @TmfSignalHandler + public void traceClosed(final TmfTraceClosedSignal signal) { + if (signal.getSource() == this) { + return; + } + if (TmfTraceManager.getInstance().getActiveTrace() == null) { + fViewContext.setCurrentTrace(null); + } + } + + /** + * Handler for the trace range updated signal + * + * @param signal + * Received signal + */ + @TmfSignalHandler + public void traceRangeUpdated(TmfTraceRangeUpdatedSignal signal) { + if (signal.getSource() == this) { + return; + } + /* + * This signal is a disaster, it's very inconsistent, has no guarantee + * of even showing up and sometimes gives values outside of the trace's + * own range. Best to ignore its contents completely. + */ + + ITmfTrace trace = fViewContext.getCurrentTrace(); + if (trace == null) { + return; + } + long traceStart = trace.getStartTime().toNanos(); + long traceEnd = trace.getEndTime().toNanos(); + fViewContext.setCurrentTraceFullRange(TimeRange.of(traceStart, traceEnd)); + } + + /** + * Handler for the selection range updated signal + * + * @param signal + * Received signal + */ + @TmfSignalHandler + public void selectionRangeUpdated(final TmfSelectionRangeUpdatedSignal signal) { + if (signal.getSource() == this) { + return; + } + long rangeStart = signal.getBeginTime().toNanos(); + long rangeEnd = signal.getEndTime().toNanos(); + + /* Sometimes the range is weird... */ + if (rangeStart == Long.MAX_VALUE || rangeEnd == Long.MAX_VALUE) { + return; + } + + /* + * This signal's end can be before its start time, against all logic. + */ + TimeRange range; + if (rangeStart > rangeEnd) { + range = TimeRange.of(rangeEnd, rangeStart); + } else { + range = TimeRange.of(rangeStart, rangeEnd); + } + + ITmfTrace trace = fViewContext.getCurrentTrace(); + if (trace == null) { + return; + } + fViewContext.setCurrentSelectionTimeRange(range); + } + + /** + * Handler for the window range updated signal + * + * @param signal + * Received signal + */ + @TmfSignalHandler + public void windowRangeUpdated(final TmfWindowRangeUpdatedSignal signal) { + if (signal.getSource() == this) { + return; + } + TmfTimeRange windowRange = signal.getCurrentRange(); + ITmfTrace trace = fViewContext.getCurrentTrace(); + if (windowRange == null || trace == null) { + return; + } + fViewContext.setCurrentVisibleTimeRange(TimeRange.fromTmfTimeRange(windowRange)); + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/context/ViewGroupContext.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/context/ViewGroupContext.java new file mode 100644 index 0000000000..a683375f02 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/context/ViewGroupContext.java @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.core.context; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.lttng.scope.tmf2.views.core.TimeRange; + +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.ReadOnlyObjectProperty; +import javafx.beans.property.SimpleObjectProperty; + +/** + * A common context for a group of views. Information is stored as properties, + * and views can add listeners to get notified of value changes. + * + * @author Alexandre Montplaisir + */ +public class ViewGroupContext { + + /** Value representing uninitialized timestamps */ + public static final TimeRange UNINITIALIZED_RANGE = TimeRange.of(0, 0); + + private final SignalBridge fSignalBridge; + + private final ObjectProperty<@Nullable ITmfTrace> fCurrentTrace = new SimpleObjectProperty<>(null); + + private ObjectProperty fCurrentTraceFullRange = new SimpleObjectProperty<>(UNINITIALIZED_RANGE); + private ObjectProperty fCurrentVisibleTimeRange = new SimpleObjectProperty<>(UNINITIALIZED_RANGE); + private ObjectProperty fCurrentSelectionRange = new SimpleObjectProperty<>(UNINITIALIZED_RANGE); + + /** + * The context is a singleton for now, but the framework could be extended + * to support several contexts (one per "view group") at the same time. + */ + private static @Nullable ViewGroupContext INSTANCE; + + private ViewGroupContext() { + fSignalBridge = new SignalBridge(this); + } + + /** + * For now, there is only a single view context for the framework. This + * method returns this singleton instance. + * + * @return The view context + */ + public static ViewGroupContext getCurrent() { + ViewGroupContext ctx = INSTANCE; + if (ctx != null) { + return ctx; + } + ctx = new ViewGroupContext(); + INSTANCE = ctx; + return ctx; + } + + /** + * Cleanup all view group contexts. + */ + public static void cleanup() { + ViewGroupContext ctx = INSTANCE; + if (ctx != null) { + ctx.fSignalBridge.dispose(); + } + } + + /** + * Set the current trace being displayed by this view context. + * + * @param trace + * The trace, can be null to indicate no trace + */ + public void setCurrentTrace(@Nullable ITmfTrace trace) { + /* On trace change, adjust the other properties accordingly. */ + if (trace == null) { + fCurrentTraceFullRange = new SimpleObjectProperty<>(UNINITIALIZED_RANGE); + fCurrentVisibleTimeRange = new SimpleObjectProperty<>(UNINITIALIZED_RANGE); + fCurrentSelectionRange = new SimpleObjectProperty<>(UNINITIALIZED_RANGE); + + } else { + long traceStart = trace.getStartTime().toNanos(); + long traceEnd = trace.getEndTime().toNanos(); + long visibleRangeEnd = Math.min(traceStart + trace.getInitialRangeOffset().toNanos(), traceEnd); + + fCurrentTraceFullRange = new SimpleObjectProperty<>((TimeRange.of(traceStart, traceEnd))); + fCurrentVisibleTimeRange = new SimpleObjectProperty<>((TimeRange.of(traceStart, visibleRangeEnd))); + fCurrentSelectionRange = new SimpleObjectProperty<>((TimeRange.of(traceStart, traceStart))); + } + + fCurrentTrace.set(trace); + } + + /** + * Retrieve the current trace displayed by this view context. + * + * @return The context's current trace. Can be null to indicate no trace. + */ + public @Nullable ITmfTrace getCurrentTrace() { + return fCurrentTrace.get(); + } + + /** + * The current trace property. + * + * Make sure you use {@link #setCurrentTrace} to modify the current trace. + * + * @return The current trace property. + */ + public ReadOnlyObjectProperty<@Nullable ITmfTrace> currentTraceProperty() { + return fCurrentTrace; + } + + /** + * Set a new full range for the current trace + * + * @param range + * The new full range of the trace + */ + public void setCurrentTraceFullRange(TimeRange range) { + fCurrentTraceFullRange.set(range); + } + + /** + * Get the full range of the current trace. + * + * @return The full range of the trace + */ + public TimeRange getCurrentTraceFullRange() { + return fCurrentTraceFullRange.get(); + } + + /** + * The property representing the full range of the current trace. + * + * TODO This property should move to the trace object itself. + * + * @return The full range property + */ + public ObjectProperty currentTraceFullRangeProperty() { + return fCurrentTraceFullRange; + } + + /** + * Set the current visible time range of this view context. + * + * @param range + * The new visible time range + */ + public void setCurrentVisibleTimeRange(TimeRange range) { + fCurrentVisibleTimeRange.set(range); + } + + /** + * Retrieve the current visible time range of the view context. + * + * @return The current visible time range + */ + public TimeRange getCurrentVisibleTimeRange() { + return fCurrentVisibleTimeRange.get(); + } + + /** + * The visible time range property. This indicates the time range bounded by + * the views of this context. + * + * @return The visible time range property + */ + public ObjectProperty currentVisibleTimeRangeProperty() { + return fCurrentVisibleTimeRange; + } + + /** + * Set the current time range selection. + * + * @param range + * The new selection range + */ + public void setCurrentSelectionTimeRange(TimeRange range) { + fCurrentSelectionRange.set(range); + } + + /** + * Retrieve the current time range selection + * + * @return The current selection range + */ + public TimeRange getCurrentSelectionTimeRange() { + return fCurrentSelectionRange.get(); + } + + /** + * The property representing the current time range selection. This is the + * "highlighted" part of the trace, which can be selected by the mouse or + * other means, and on which action can act. + * + * @return The time range selection property + */ + public ObjectProperty currentSelectionTimeRangeProperty() { + return fCurrentSelectionRange; + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/context/package-info.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/context/package-info.java new file mode 100644 index 0000000000..7ee533ceaf --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/context/package-info.java @@ -0,0 +1,11 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +@org.eclipse.jdt.annotation.NonNullByDefault +package org.lttng.scope.tmf2.views.core.context; diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/package-info.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/package-info.java new file mode 100644 index 0000000000..838f3e1562 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/package-info.java @@ -0,0 +1,11 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +@org.eclipse.jdt.annotation.NonNullByDefault +package org.lttng.scope.tmf2.views.core; diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/control/TimeGraphModelControl.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/control/TimeGraphModelControl.java new file mode 100644 index 0000000000..a29542bcf4 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/control/TimeGraphModelControl.java @@ -0,0 +1,269 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + *******************************************************************************/ + +package org.lttng.scope.tmf2.views.core.timegraph.control; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.lttng.scope.tmf2.views.core.TimeRange; +import org.lttng.scope.tmf2.views.core.context.ViewGroupContext; +import org.lttng.scope.tmf2.views.core.timegraph.model.provider.ITimeGraphModelProvider; +import org.lttng.scope.tmf2.views.core.timegraph.view.TimeGraphModelView; + +import javafx.beans.value.ChangeListener; + +/** + * Control part of the timegraph MVC mechanism. It links a + * {@link TimeGraphModelView} to a {@link ITimeGraphModelProvider}. + * + * @author Alexandre Montplaisir + */ +public final class TimeGraphModelControl { + + private final ChangeListener fVisibleRangeChangeListener = (obs, oldRange, newRange) -> seekVisibleRange(newRange); + + private final ViewGroupContext fViewContext; + private final ITimeGraphModelProvider fRenderProvider; + + private @Nullable TimeGraphModelView fView = null; + + /** + * Constructor. + * + * The control links a model provider, and a view. But the view also needs a + * back-reference to the control. The suggested pattern is to do: + * + *
+     * ITimeGraphModelProvider provider = ...
+     * TimeGraphModelControl control = new TimeGraphModelControl(viewContext, provider);
+     * TimeGraphModelView view = new TimeGraphModelView(control);
+     * control.attachView(view);
+     * 
+ * + * @param viewContext + * The view context to which this timegraph belongs + * @param provider + * The model provider that goes with this control + */ + public TimeGraphModelControl(ViewGroupContext viewContext, ITimeGraphModelProvider provider) { + fViewContext = viewContext; + fRenderProvider = provider; + + attachListeners(viewContext); + } + + /** + * Attach a view to this control + * + * @param view + * The view to attach + */ + public void attachView(TimeGraphModelView view) { + fView = view; + + /* + * Initially populate the view with the context of the current trace. + */ + ITmfTrace trace = getViewContext().getCurrentTrace(); + initializeForTrace(trace); + } + + @Nullable TimeGraphModelView getView() { + return fView; + } + + /** + * Dispose this control and its components. + */ + public void dispose() { + if (fView != null) { + fView.dispose(); + } + } + + private void attachListeners(ViewGroupContext viewContext) { + viewContext.currentTraceProperty().addListener((observable, oldTrace, newTrace) -> { + initializeForTrace(newTrace); + + viewContext.currentSelectionTimeRangeProperty().addListener((obs, oldRange, newRange) -> { + drawSelection(newRange); + }); + + viewContext.currentVisibleTimeRangeProperty().addListener(fVisibleRangeChangeListener); + }); + } + + // ------------------------------------------------------------------------ + // Accessors + // ------------------------------------------------------------------------ + + /** + * Get the view context to which this control belongs. + * + * @return The view context + */ + public ViewGroupContext getViewContext() { + return fViewContext; + } + + /** + * Get the model provider of this control + * + * @return The model provider + */ + public ITimeGraphModelProvider getModelRenderProvider() { + return fRenderProvider; + } + + // ------------------------------------------------------------------------ + // Control -> View operations + // ------------------------------------------------------------------------ + + /** + * Initialize this timegraph for a new trace. + * + * @param trace + * The trace to initialize in the view. If it is null it indcates + * 'no trace'. + */ + public synchronized void initializeForTrace(@Nullable ITmfTrace trace) { + fRenderProvider.setTrace(trace); + + TimeGraphModelView view = fView; + if (view == null) { + return; + } + view.clear(); + + if (trace == null) { + /* View will remain cleared, good */ + return; + } + + TimeRange currentVisibleRange = fViewContext.getCurrentVisibleTimeRange(); + checkWindowTimeRange(currentVisibleRange); + view.seekVisibleRange(currentVisibleRange); + } + + /** + * Repaint, without seeking anywhere else, the current displayed area of the + * view. + * + * This can be called whenever some settings like filters etc. have changed, + * so that a repaint will show updated information. + */ + public void repaintCurrentArea() { + ITmfTrace trace = fViewContext.getCurrentTrace(); + TimeRange currentRange = fViewContext.getCurrentVisibleTimeRange(); + if (trace == null || currentRange == ViewGroupContext.UNINITIALIZED_RANGE) { + return; + } + + TimeGraphModelView view = fView; + if (view != null) { + view.clear(); + view.seekVisibleRange(currentRange); + } + } + + void seekVisibleRange(TimeRange newRange) { + checkWindowTimeRange(newRange); + TimeGraphModelView view = fView; + if (view != null) { + view.seekVisibleRange(newRange); + } + } + + void drawSelection(TimeRange selectionRange) { + checkWindowTimeRange(selectionRange); + TimeGraphModelView view = fView; + if (view != null) { + view.drawSelection(selectionRange); + } + } + + + + // ------------------------------------------------------------------------ + // View -> Control operations (Control external API) + // ------------------------------------------------------------------------ + + /** + * Change the current time range selection. + * + * Called by the view to indicate that the user has input a new time range + * selection from the view. The control will relay this to the rest of the + * framework. + * + * @param newSelectionRange + * The new time range selection. + */ + public void updateTimeRangeSelection(TimeRange newSelectionRange) { + fViewContext.setCurrentSelectionTimeRange(newSelectionRange); + } + + /** + * Change the current visible time range. + * + * Called by the view whenever the user selects a new visible time range, + * for example by scrolling left or right. + * + * @param newVisibleRange + * The new visible time range + * @param echo + * This flag indicates if the view wants to receive the new time + * range notification back to itself (via + * {@link #seekVisibleRange}. + */ + public void updateVisibleTimeRange(TimeRange newVisibleRange, boolean echo) { + checkTimeRange(newVisibleRange); + + /* + * If 'echo' is 'off', we will avoid triggering our change listener on + * this modification by detaching then re-attaching it afterwards. + */ + if (echo) { + fViewContext.setCurrentVisibleTimeRange(newVisibleRange); + } else { + fViewContext.currentVisibleTimeRangeProperty().removeListener(fVisibleRangeChangeListener); + fViewContext.setCurrentVisibleTimeRange(newVisibleRange); + fViewContext.currentVisibleTimeRangeProperty().addListener(fVisibleRangeChangeListener); + } + } + + // ------------------------------------------------------------------------ + // Utils + // ------------------------------------------------------------------------ + + private static void checkTimeRange(TimeRange range) { + if (range.getStart() == Long.MAX_VALUE) { + throw new IllegalArgumentException("You are trying to make me believe the range starts at " + //$NON-NLS-1$ + range.getStart() + ". I do not believe you."); //$NON-NLS-1$ + } + if (range.getEnd() == Long.MAX_VALUE) { + throw new IllegalArgumentException("You are trying to make me believe the range ends at " + //$NON-NLS-1$ + range.getEnd() + ". I do not believe you."); //$NON-NLS-1$ + } + } + + private void checkWindowTimeRange(TimeRange windowRange) { + checkTimeRange(windowRange); + TimeRange fullRange = fViewContext.getCurrentTraceFullRange(); + + if (windowRange.getStart() < fullRange.getStart()) { + throw new IllegalArgumentException("Requested window start time: " + windowRange.getStart() + //$NON-NLS-1$ + " is smaller than trace start time " + fullRange.getStart()); //$NON-NLS-1$ + } + if (windowRange.getEnd() > fullRange.getEnd()) { + throw new IllegalArgumentException("Requested window end time: " + windowRange.getEnd() + //$NON-NLS-1$ + " is greater than trace end time " + fullRange.getEnd()); //$NON-NLS-1$ + } + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/control/package-info.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/control/package-info.java new file mode 100644 index 0000000000..985b37b2a4 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/control/package-info.java @@ -0,0 +1,11 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc. and others + * + * 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 + *******************************************************************************/ + +@org.eclipse.jdt.annotation.NonNullByDefault +package org.lttng.scope.tmf2.views.core.timegraph.control; diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/ITimeGraphModelProvider.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/ITimeGraphModelProvider.java new file mode 100644 index 0000000000..dc43a7a4c4 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/ITimeGraphModelProvider.java @@ -0,0 +1,207 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + *******************************************************************************/ + +package org.lttng.scope.tmf2.views.core.timegraph.model.provider; + +import java.util.Collection; +import java.util.List; +import java.util.Set; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.lttng.scope.tmf2.views.core.timegraph.model.provider.arrows.ITimeGraphModelArrowProvider; +import org.lttng.scope.tmf2.views.core.timegraph.model.provider.states.ITimeGraphModelStateProvider; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeRender; + +import javafx.beans.property.ObjectProperty; + +/** + * Base interface for time graph model providers. + * + * This object is responsible for the generation of the "tree" part of the + * timegraph, and other generic options like sorting and filtering modes. + * + * It also encapsulates one {@link ITimeGraphModelStateProvider} (which is + * responsible of providing state intervals), and zero or more + * {@link ITimeGraphModelArrowProvider} (which provide model-defined arrow + * series). + * + * @author Alexandre Montplaisir + */ +public interface ITimeGraphModelProvider { + + // ------------------------------------------------------------------------ + // Configuration option classes + // ------------------------------------------------------------------------ + + /** + * Class representing one sorting mode. A sorting mode is like a comparator + * to sort tree elements. Only one can be active at any time. + * + * The exact behavior of the sorting mode is defined by the model provider + * itself. + */ + class SortingMode { + + private final String fName; + + public SortingMode(String name) { + fName = name; + } + + public String getName() { + return fName; + } + } + + /** + * Class representing a filter mode. A filter mode is like a filter applied + * on the list tree elements. Zero or more can be active at the same time. + * + * The exact behavior of the filter mode is defined by the model provider + * itself. + */ + class FilterMode { + + private final String fName; + + public FilterMode(String name) { + fName = name; + } + + public String getName() { + return fName; + } + } + + // ------------------------------------------------------------------------ + // General methods + // ------------------------------------------------------------------------ + + /** + * Get the name of this model provider. This can be used for example to name + * a corresponding view in the UI. + * + * @return The model provider's name + */ + String getName(); + + /** + * Set the trace for which this model provider fetches its information. + * + * @param trace + * The source trace + */ + void setTrace(@Nullable ITmfTrace trace); + + + /** + * Get the trace for which this model provider fetches its information. + * + * @return The current trace + */ + @Nullable ITmfTrace getTrace(); + + /** + * The property representing the target trace of this model provider. + * + * @return The trace property + */ + ObjectProperty<@Nullable ITmfTrace> traceProperty(); + + // ------------------------------------------------------------------------ + // Render providers + // ------------------------------------------------------------------------ + + /** + * Get a tree render corresponding to the current configuration settings. + * + * @return A tree render + */ + TimeGraphTreeRender getTreeRender(); + + /** + * Get the state provider supplied by this model provider. + * + * @return The state provider + */ + ITimeGraphModelStateProvider getStateProvider(); + + /** + * Get the arrow providers supplied by this model provider. + * + * @return The arrow providers. May be empty but should not be null. + */ + Collection getArrowProviders(); + + // ------------------------------------------------------------------------ + // Sorting modes + // ------------------------------------------------------------------------ + + /** + * Get a list of all the available sorting modes for this provider. + * + * @return The sorting modes + */ + List getSortingModes(); + + /** + * Get the current sorting mode. There should always be one and only one. + * + * @return The current sorting mode + */ + SortingMode getCurrentSortingMode(); + + /** + * Change the configured sorting mode to another one. + * + * @param index + * The index of the corresponding mode in the list returned by + * {@link #getSortingModes()}. + */ + void setCurrentSortingMode(int index); + + // ------------------------------------------------------------------------ + // Filter modes + // ------------------------------------------------------------------------ + + /** + * Get a list of all the available filter modes for this provider. + * + * @return The list of available filter modes. It may be empty but should + * not be null. + */ + List getFilterModes(); + + /** + * Enable the specified filter mode. + * + * @param index + * The index of the filter mode in the list returned by + * {@link #getFilterModes()}. + */ + void enableFilterMode(int index); + + /** + * Disable the specified filter mode. + * + * @param index + * The index of the filter mode in the list returned by + * {@link #getFilterModes()}. + */ + void disableFilterMode(int index); + + /** + * Get the currently active filter modes. + * + * @return The active filter modes. There might be 0 or more. + */ + Set getActiveFilterModes(); + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/ITimeGraphModelProviderFactory.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/ITimeGraphModelProviderFactory.java new file mode 100644 index 0000000000..940ab925b7 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/ITimeGraphModelProviderFactory.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.core.timegraph.model.provider; + +import java.util.function.Supplier; + +/** + * Factory for {@link ITimeGraphModelProvider} objects. + * + * Used to register possible time graphs to the framework using the + * {@link TimeGraphModelProviderManager}. + * + * @author Alexandre Montplaisir + */ +@FunctionalInterface +public interface ITimeGraphModelProviderFactory extends Supplier { + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/Messages.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/Messages.java new file mode 100644 index 0000000000..29442b56d6 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/Messages.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + *******************************************************************************/ + +package org.lttng.scope.tmf2.views.core.timegraph.model.provider; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.osgi.util.NLS; + +/** + * Package message bundle + * + * @noreference Messages class + */ +@NonNullByDefault({}) +@SuppressWarnings("javadoc") +public class Messages extends NLS { + + private static final String BUNDLE_NAME = Messages.class.getPackage().getName() + ".messages"; //$NON-NLS-1$ + + public static String DefaultSortingModeName; + + static { + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() {} +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/TimeGraphModelProvider.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/TimeGraphModelProvider.java new file mode 100644 index 0000000000..18fa89d976 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/TimeGraphModelProvider.java @@ -0,0 +1,180 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + *******************************************************************************/ + +package org.lttng.scope.tmf2.views.core.timegraph.model.provider; + +import static org.lttng.scope.common.core.NonNullUtils.nullToEmptyString; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.lttng.scope.tmf2.views.core.timegraph.model.provider.arrows.ITimeGraphModelArrowProvider; +import org.lttng.scope.tmf2.views.core.timegraph.model.provider.states.ITimeGraphModelStateProvider; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeRender; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; + +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; + +/** + * Base implementation of {@link ITimeGraphModelProvider}. + * + * @author Alexandre Montplaisir + */ +public abstract class TimeGraphModelProvider implements ITimeGraphModelProvider { + + /** + * A "default" sorting mode, for use when only one is needed. + */ + protected static final SortingMode DEFAULT_SORTING_MODE = new SortingMode(nullToEmptyString(Messages.DefaultSortingModeName)); + + private final String fName; + private final List fSortingModes; + private final List fFilterModes; + + private final ITimeGraphModelStateProvider fStateProvider; + private final List fArrowProviders; + + private final Set fActiveFilterModes = new HashSet<>(); + private SortingMode fCurrentSortingMode; + + private final ObjectProperty<@Nullable ITmfTrace> fTraceProperty = new SimpleObjectProperty<>(); + + /** + * Constructor + * + * @param name + * The name of this provider + * @param sortingModes + * The available sorting modes + * @param filterModes + * The available filter modes + * @param stateProvider + * The state provider part of this model provider + * @param arrowProviders + * The arrow provider(s) supplied by this model provider + */ + public TimeGraphModelProvider(String name, + @Nullable List sortingModes, + @Nullable List filterModes, + ITimeGraphModelStateProvider stateProvider, + @Nullable List arrowProviders) { + fName = name; + + fStateProvider = stateProvider; + stateProvider.traceProperty().bind(fTraceProperty); + + if (sortingModes == null || sortingModes.isEmpty()) { + fSortingModes = ImmutableList.of(DEFAULT_SORTING_MODE); + } else { + fSortingModes = ImmutableList.copyOf(sortingModes); + + } + fCurrentSortingMode = fSortingModes.get(0); + + if (filterModes == null || filterModes.isEmpty()) { + fFilterModes = ImmutableList.of(); + } else { + fFilterModes = ImmutableList.copyOf(filterModes); + } + + if (arrowProviders == null || arrowProviders.isEmpty()) { + fArrowProviders = ImmutableList.of(); + } else { + fArrowProviders = ImmutableList.copyOf(arrowProviders); + } + fArrowProviders.forEach(ap -> ap.traceProperty().bind(fTraceProperty)); + } + + @Override + public final String getName() { + return fName; + } + + @Override + public final void setTrace(@Nullable ITmfTrace trace) { + fTraceProperty.set(trace); + } + + @Override + public final @Nullable ITmfTrace getTrace() { + return fTraceProperty.get(); + } + + @Override + public final ObjectProperty<@Nullable ITmfTrace> traceProperty() { + return fTraceProperty; + } + + @Override + public final ITimeGraphModelStateProvider getStateProvider() { + return fStateProvider; + } + + @Override + public final List getArrowProviders() { + return fArrowProviders; + } + + // ------------------------------------------------------------------------ + // Render generation methods. Implementation left to subclasses. + // ------------------------------------------------------------------------ + + @Override + public abstract TimeGraphTreeRender getTreeRender(); + + // ------------------------------------------------------------------------ + // Sorting modes + // ------------------------------------------------------------------------ + + @Override + public final List getSortingModes() { + return fSortingModes; + } + + @Override + public final SortingMode getCurrentSortingMode() { + return fCurrentSortingMode; + } + + @Override + public final void setCurrentSortingMode(int index) { + fCurrentSortingMode = fSortingModes.get(index); + } + + // ------------------------------------------------------------------------ + // Filter modes + // ------------------------------------------------------------------------ + + @Override + public final List getFilterModes() { + return fFilterModes; + } + + @Override + public final void enableFilterMode(int index) { + fActiveFilterModes.add(fFilterModes.get(index)); + } + + @Override + public final void disableFilterMode(int index) { + fActiveFilterModes.remove(fFilterModes.get(index)); + } + + @Override + public final Set getActiveFilterModes() { + return ImmutableSet.copyOf(fActiveFilterModes); + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/TimeGraphModelProviderManager.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/TimeGraphModelProviderManager.java new file mode 100644 index 0000000000..3dad27efe4 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/TimeGraphModelProviderManager.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.core.timegraph.model.provider; + +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Set; + +/** + * Manager for the time graph model providers. + * + * Components can register their possible time graphs, and views etc. may query + * and instantiate them. + * + * @author Alexandre Montplaisir + */ +public final class TimeGraphModelProviderManager { + + /** + * Interface for classes displaying Time Graphs. Implement this interface and + * register your class using {@link #registerOutput} to receive notifications + * about current and newly-registered time graph providers. + */ + public static interface TimeGraphOutput { + + /** + * Callback called by the provider manager when model providers are registered. + * + * @param factory + * The model provider factory + */ + void providerRegistered(ITimeGraphModelProviderFactory factory); + } + + private static final TimeGraphModelProviderManager INSTANCE = new TimeGraphModelProviderManager(); + + private TimeGraphModelProviderManager() {} + + /** + * Get the singleton instance of this manager. + * + * @return The instance + */ + public static TimeGraphModelProviderManager instance() { + return INSTANCE; + } + + private final Set fRegisteredProviderFactories = new LinkedHashSet<>(); + private final Set fRegisteredOutputs = new HashSet<>(); + + /** + * Register a time graph provider by specifying its + * {@link ITimeGraphModelProviderFactory}. If a factory is already registered, + * this method will have no effect. + * + * @param factory + * The provider's factory + */ + public synchronized void registerProviderFactory(ITimeGraphModelProviderFactory factory) { + boolean added = fRegisteredProviderFactories.add(factory); + if (added) { + fRegisteredOutputs.forEach(output -> output.providerRegistered(factory)); + } + } + + /** + * Register a time graph output to this manager. Upon registration, + * notifications will be sent, using {@link TimeGraphOutput#providerRegistered}, + * for all existing providers. Additional notifications will be sent for future + * registered providers. + * + * @param output + * The time graph output to register + */ + public synchronized void registerOutput(TimeGraphOutput output) { + /* Send notifications for currently-registered factories */ + fRegisteredProviderFactories.forEach(factory -> output.providerRegistered(factory)); + fRegisteredOutputs.add(output); + } + + /** + * Unregister a previously-registered output, so that it does not receive any + * more notifications. Has no effect if the output was not already registered. + * + * @param output + * The output to unregister + */ + public synchronized void unregisterOutput(TimeGraphOutput output) { + fRegisteredOutputs.remove(output); + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/arrows/ITimeGraphModelArrowProvider.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/arrows/ITimeGraphModelArrowProvider.java new file mode 100644 index 0000000000..bee5fa632b --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/arrows/ITimeGraphModelArrowProvider.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.core.timegraph.model.provider.arrows; + +import java.util.concurrent.FutureTask; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.lttng.scope.tmf2.views.core.TimeRange; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.arrows.TimeGraphArrowRender; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.arrows.TimeGraphArrowSeries; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeRender; + +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.ObjectProperty; + +/** + * Provider for timegraph arrow series. + * + * It can be used stand-alone (ie, for testing) but usually would be part of a + * {@link org.lttng.scope.tmf2.views.core.timegraph.model.provider.ITimeGraphModelProvider}. + * + * @author Alexandre Montplaisir + */ +public interface ITimeGraphModelArrowProvider { + + /** + * Property representing the trace this arrow provider fetches its data for. + * + * @return The trace property + */ + ObjectProperty<@Nullable ITmfTrace> traceProperty(); + + /** + * Property indicating if this specific arrow provider is currently enabled + * or not. + * + * Normally the controls should not send queries to this provider if it is + * disabled (they would only query this state), but the arrow provider is + * free to make use of this property for other reasons. + * + * @return The enabled property + */ + BooleanProperty enabledProperty(); + + /** + * Get the arrow series supplied by this arrow provider. A single provider + * supplies one and only one arrow series. + * + * @return The arrow series + */ + TimeGraphArrowSeries getArrowSeries(); + + /** + * Get a render of arrows from this arrow provider. + * + * @param treeRender + * The tree render for which the query is done + * @param timeRange + * The time range of the query. The provider may decide to + * include arrows partially inside this range, or not. + * @param task + * An optional task parameter, which can be checked for + * cancellation to stop processing at any point and return. + * @return The corresponding arrow render + */ + TimeGraphArrowRender getArrowRender(TimeGraphTreeRender treeRender, TimeRange timeRange, @Nullable FutureTask task); + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/arrows/TimeGraphModelArrowProvider.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/arrows/TimeGraphModelArrowProvider.java new file mode 100644 index 0000000000..f3833cbb66 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/arrows/TimeGraphModelArrowProvider.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.core.timegraph.model.provider.arrows; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.arrows.TimeGraphArrowSeries; + +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleObjectProperty; + +/** + * Basic implementation of {@link ITimeGraphModelArrowProvider}. It takes care + * of basic definitions of the interface, and lets query definition (the + * {@link #getArrowRender} method) up to the subclass. + * + * @author Alexandre Montplaisir + */ +public abstract class TimeGraphModelArrowProvider implements ITimeGraphModelArrowProvider { + + private final ObjectProperty<@Nullable ITmfTrace> fTraceProperty = new SimpleObjectProperty<>(null); + private final BooleanProperty fEnabledProperty = new SimpleBooleanProperty(false); + private final TimeGraphArrowSeries fArrowSeries; + + /** + * Constructor + * + * @param arrowSeries + * The arrow series that will be represented by this arrow + * provider + */ + public TimeGraphModelArrowProvider(TimeGraphArrowSeries arrowSeries) { + fArrowSeries = arrowSeries; + } + + @Override + public final ObjectProperty<@Nullable ITmfTrace> traceProperty() { + return fTraceProperty; + } + + @Override + public BooleanProperty enabledProperty() { + return fEnabledProperty; + } + + @Override + public final TimeGraphArrowSeries getArrowSeries() { + return fArrowSeries; + } +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/arrows/package-info.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/arrows/package-info.java new file mode 100644 index 0000000000..e6f3fbe8ac --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/arrows/package-info.java @@ -0,0 +1,11 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc. and others + * + * 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 + *******************************************************************************/ + +@org.eclipse.jdt.annotation.NonNullByDefault +package org.lttng.scope.tmf2.views.core.timegraph.model.provider.arrows; diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/drawnevents/ITimeGraphDrawnEventProvider.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/drawnevents/ITimeGraphDrawnEventProvider.java new file mode 100644 index 0000000000..a9631a982f --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/drawnevents/ITimeGraphDrawnEventProvider.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.core.timegraph.model.provider.drawnevents; + +import java.util.concurrent.FutureTask; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.lttng.scope.tmf2.views.core.TimeRange; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.drawnevents.TimeGraphDrawnEventRender; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.drawnevents.TimeGraphDrawnEventSeries; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeRender; + +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.ObjectProperty; + +/** + * Interface defining providers of drawn events. + * + * A "drawn event" is a symbol in a timegraph representing one particular + * (trace) event. Contrary to a trace event, a drawn event has both horizontal + * and vertical coordinates, being time and its corresponding time graph entry. + * + * @author Alexandre Montplaisir + * @see TimeGraphDrawnEventProviderManager + */ +public interface ITimeGraphDrawnEventProvider { + + /** + * The trace from which the provider will fetch its events. The Property + * mechanisms can be used to sync with trace changes elsewhere in the + * framework. + * + * @return The target trace + */ + ObjectProperty<@Nullable ITmfTrace> traceProperty(); + + /** + * The 'enabled' property of this provider. A provider can be created and + * registered to the manager, but considered disabled so that it stops + * painting its events. + * + * For example, if the user can uncheck elements in a list showing all + * existing event providers, this could disable said providers without + * completely destroying them. + * + * @return The enabled property + */ + BooleanProperty enabledProperty(); + + /** + * Return the {@link TimeGraphDrawnEventSeries} provided by this provider. A + * single provider should manage a single event series; different providers + * should be implemented for different series. + * + * @return The event series of this provider + */ + TimeGraphDrawnEventSeries getEventSeries(); + + /** + * Query for a render of drawn events on this provider. + * + * @param treeRender + * The tree render of the timegraph to paint on + * @param timeRange + * The time range of the timegraph (and trace) to run the query + * on. + * @param task + * If this method is called from within a {@link FutureTask}, it + * can optionally be passed here. If the execution is expected to + * take a long time, the implementation is suggested to + * periodically check this parameter for cancellation. + * @return The corresponding event render that contains the result of the + * query + */ + TimeGraphDrawnEventRender getEventRender(TimeGraphTreeRender treeRender, + TimeRange timeRange, @Nullable FutureTask task); +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/drawnevents/TimeGraphDrawnEventProvider.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/drawnevents/TimeGraphDrawnEventProvider.java new file mode 100644 index 0000000000..2ace59007b --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/drawnevents/TimeGraphDrawnEventProvider.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.core.timegraph.model.provider.drawnevents; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.drawnevents.TimeGraphDrawnEventSeries; + +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleObjectProperty; + +/** + * Basic implementation of {@link ITimeGraphDrawnEventProvider}. + * + * Implementation of the {@link #getEventRender} method is left to subclasses. + * + * @author Alexandre Montplaisir + */ +public abstract class TimeGraphDrawnEventProvider implements ITimeGraphDrawnEventProvider { + + private final ObjectProperty<@Nullable ITmfTrace> fTraceProperty = new SimpleObjectProperty<>(null); + private final BooleanProperty fEnabledProperty = new SimpleBooleanProperty(false); + private final TimeGraphDrawnEventSeries fDrawnEventSeries; + + /** + * Constructor + * + * @param drawnEventSeries + * The event series provided by this provider. + */ + protected TimeGraphDrawnEventProvider(TimeGraphDrawnEventSeries drawnEventSeries) { + fDrawnEventSeries = drawnEventSeries; + } + + @Override + public final ObjectProperty<@Nullable ITmfTrace> traceProperty() { + return fTraceProperty; + } + + @Override + public final BooleanProperty enabledProperty() { + return fEnabledProperty; + } + + @Override + public final TimeGraphDrawnEventSeries getEventSeries() { + return fDrawnEventSeries; + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/drawnevents/TimeGraphDrawnEventProviderManager.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/drawnevents/TimeGraphDrawnEventProviderManager.java new file mode 100644 index 0000000000..4aac391ec3 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/drawnevents/TimeGraphDrawnEventProviderManager.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.core.timegraph.model.provider.drawnevents; + +import java.util.Comparator; +import java.util.Set; +import java.util.TreeSet; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableSet; + +/** + * Manager of {@link ITimeGraphDrawnEventProvider}s. + * + * @author Alexandre Montplaisir + */ +public final class TimeGraphDrawnEventProviderManager { + + private static final Comparator COMPARATOR = + Comparator.comparing(provider -> provider.getEventSeries().getSeriesName()); + + private static final TimeGraphDrawnEventProviderManager INSTANCE = new TimeGraphDrawnEventProviderManager(); + + private final ObservableSet fRegisteredProviders = + FXCollections.observableSet(new TreeSet<>(COMPARATOR)); + + private TimeGraphDrawnEventProviderManager() {} + + /** + * Get the singleton instance. + * + * @return The instance + */ + public static TimeGraphDrawnEventProviderManager instance() { + return INSTANCE; + } + + /** + * Return the {@link ObservableSet} of registered providers. + * + * You can use {@link Set#add} and {@link Set#remove} to register and + * deregister providers, but also the {@link ObservableSet#addListener} + * methods to be notified of provider changes. + * + * @return The registered providers + */ + public ObservableSet getRegisteredProviders() { + return fRegisteredProviders; + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/drawnevents/package-info.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/drawnevents/package-info.java new file mode 100644 index 0000000000..3afaaa8a38 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/drawnevents/package-info.java @@ -0,0 +1,11 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc. and others + * + * 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 + *******************************************************************************/ + +@org.eclipse.jdt.annotation.NonNullByDefault +package org.lttng.scope.tmf2.views.core.timegraph.model.provider.drawnevents; diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/messages.properties b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/messages.properties new file mode 100644 index 0000000000..96fad2f2c3 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/messages.properties @@ -0,0 +1,10 @@ +############################################################################### +# Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir +# +# 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 +############################################################################### + +DefaultSortingModeName = Default diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/package-info.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/package-info.java new file mode 100644 index 0000000000..f977cbd757 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/package-info.java @@ -0,0 +1,11 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc. and others + * + * 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 + *******************************************************************************/ + +@org.eclipse.jdt.annotation.NonNullByDefault +package org.lttng.scope.tmf2.views.core.timegraph.model.provider; diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/states/ITimeGraphModelStateProvider.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/states/ITimeGraphModelStateProvider.java new file mode 100644 index 0000000000..2422328bf7 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/states/ITimeGraphModelStateProvider.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.core.timegraph.model.provider.states; + +import java.util.List; +import java.util.concurrent.FutureTask; +import java.util.stream.Collectors; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.lttng.scope.tmf2.views.core.TimeRange; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.StateDefinition; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.states.TimeGraphStateRender; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeElement; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeRender; + +import javafx.beans.property.ObjectProperty; + +/** + * Provider for timegraph state intervals. + * + * It can be used stand-alone (ie, for testing) but usually would be part of a + * {@link org.lttng.scope.tmf2.views.core.timegraph.model.provider.ITimeGraphModelProvider}. + * + * @author Alexandre Montplaisir + */ +public interface ITimeGraphModelStateProvider { + + /** + * Property representing the trace this arrow provider fetches its data for. + * + * @return The trace property + */ + ObjectProperty<@Nullable ITmfTrace> traceProperty(); + + /** + * Get an aggregated list of {@link StateDefinition} used in this provider. + * + * @return The state definitions used in this provider + */ + List getStateDefinitions(); + + /** + * Get a state render for a single tree element + * + * @param treeElement + * The tree element to target + * @param timeRange + * The time range of the query + * @param resolution + * The resolution, in timestamp units, of the query. For example, + * a resolution of 1000 means the provider does not need to + * return states that don't cross at least 1 1000-units borders. + * @param task + * An optional task parameter, which can be checked for + * cancellation to stop processing at any point and return. + * @return The corresponding state render for this tree element and settings + */ + TimeGraphStateRender getStateRender(TimeGraphTreeElement treeElement, + TimeRange timeRange, long resolution, @Nullable FutureTask task); + + /** + * Helper method to fetch all the state renders for all tree elements of a + * *tree* render. + * + * Default implementation simply calls {@link #getStateRender} on each tree + * element sequentially, but more advanced providers could override it if + * they can provide a faster mechanism. + * + * @param treeRender + * The tree render for which to prepare all the state renders + * @param timeRange + * The time range of the query + * @param resolution + * The resolution of the query, see {@link #getStateRender}. + * @param task + * The optional task parameter which can be used for + * cancellation. + * @return The corresponding state renders + */ + default List getStateRenders(TimeGraphTreeRender treeRender, TimeRange timeRange, long resolution, @Nullable FutureTask task) { + return treeRender.getAllTreeElements().stream() + .map(treeElem -> getStateRender(treeElem, timeRange, resolution, task)) + .collect(Collectors.toList()); + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/states/TimeGraphModelStateProvider.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/states/TimeGraphModelStateProvider.java new file mode 100644 index 0000000000..0fa4250702 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/states/TimeGraphModelStateProvider.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.core.timegraph.model.provider.states; + +import java.util.List; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.StateDefinition; + +import com.google.common.collect.ImmutableList; + +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; + +/** + * Basic implementation of {@link ITimeGraphModelStateProvider}. + * + * @author Alexandre Montplaisir + */ +public abstract class TimeGraphModelStateProvider implements ITimeGraphModelStateProvider { + + private final ObjectProperty<@Nullable ITmfTrace> fTraceProperty = new SimpleObjectProperty<>(null); + + private final List fStateDefinitions; + + /** + * Constructor + * + * @param stateDefinitions + * The state definitions used in this provider + */ + public TimeGraphModelStateProvider(List stateDefinitions) { + fStateDefinitions = ImmutableList.copyOf(stateDefinitions); + } + + @Override + public ObjectProperty<@Nullable ITmfTrace> traceProperty() { + return fTraceProperty; + } + + @Override + public List getStateDefinitions() { + return fStateDefinitions; + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/states/package-info.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/states/package-info.java new file mode 100644 index 0000000000..f1f8b6c327 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/states/package-info.java @@ -0,0 +1,11 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc. and others + * + * 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 + *******************************************************************************/ + +@org.eclipse.jdt.annotation.NonNullByDefault +package org.lttng.scope.tmf2.views.core.timegraph.model.provider.states; diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/statesystem/StateSystemModelArrowProvider.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/statesystem/StateSystemModelArrowProvider.java new file mode 100644 index 0000000000..3e79da82bd --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/statesystem/StateSystemModelArrowProvider.java @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.core.timegraph.model.provider.statesystem; + +import java.util.concurrent.FutureTask; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.lttng.scope.tmf2.views.core.TimeRange; +import org.lttng.scope.tmf2.views.core.timegraph.model.provider.arrows.TimeGraphModelArrowProvider; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.arrows.TimeGraphArrowRender; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.arrows.TimeGraphArrowSeries; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeRender; + +import ca.polymtl.dorsal.libdelorean.ITmfStateSystem; + +/** + * Basic implementation of a {@link TimeGraphModelArrowProvider} backed by a + * state system. + * + * @author Alexandre Montplaisir + */ +public abstract class StateSystemModelArrowProvider extends TimeGraphModelArrowProvider { + + private final String fStateSystemModuleId; + + private transient @Nullable ITmfStateSystem fStateSystem = null; + + /** + * Constructor + * + * @param arrowSeries + * The arrow series that will be represented by this arrow + * provider + * @param stateSystemModuleId + * The ID of the state system from which the information should + * be fetched + */ + public StateSystemModelArrowProvider(TimeGraphArrowSeries arrowSeries, + String stateSystemModuleId) { + super(arrowSeries); + fStateSystemModuleId = stateSystemModuleId; + + /* + * Change listener which will take care of keeping the target state + * system up to date. + */ + traceProperty().addListener((obs, oldValue, newValue) -> { + ITmfTrace trace = newValue; + if (trace == null) { + fStateSystem = null; + return; + } + + // FIXME Remove the extra thread once we move to Jabberwocky + Thread thread = new Thread(() -> { + fStateSystem = TmfStateSystemAnalysisModule.getStateSystem(trace, fStateSystemModuleId); + }); + thread.start(); + }); + } + + /** + * The state system from which the data should be fetched. This will be kept + * in sync with the {@link #traceProperty}. + * + * @return The target state system. It will be null if the current trace is + * null. + */ + protected final @Nullable ITmfStateSystem getStateSystem() { + return fStateSystem; + } + + @Override + public abstract TimeGraphArrowRender getArrowRender(TimeGraphTreeRender treeRender, TimeRange timeRange, @Nullable FutureTask task); +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/statesystem/StateSystemModelProvider.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/statesystem/StateSystemModelProvider.java new file mode 100644 index 0000000000..2b251dcafe --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/statesystem/StateSystemModelProvider.java @@ -0,0 +1,204 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + *******************************************************************************/ + +package org.lttng.scope.tmf2.views.core.timegraph.model.provider.statesystem; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.WeakHashMap; +import java.util.function.Function; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.lttng.scope.tmf2.views.core.timegraph.model.provider.TimeGraphModelProvider; +import org.lttng.scope.tmf2.views.core.timegraph.model.provider.arrows.ITimeGraphModelArrowProvider; +import org.lttng.scope.tmf2.views.core.timegraph.model.provider.states.ITimeGraphModelStateProvider; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeRender; + +import ca.polymtl.dorsal.libdelorean.ITmfStateSystem; +import ca.polymtl.dorsal.libdelorean.exceptions.StateSystemDisposedException; +import ca.polymtl.dorsal.libdelorean.interval.ITmfStateInterval; + +/** + * Basic implementation of a {@link TimeGraphModelProvider} backed by a state + * system. + * + * @author Alexandre Montplaisir + */ +public abstract class StateSystemModelProvider extends TimeGraphModelProvider { + + /** + * The context of a tree render. Should contain all the information to + * generate the corresponding tree render, according to all configuration + * options like sorting, filtering etc. specified by the user. + */ + protected static final class TreeRenderContext { + + /** Trace name */ + public final String traceName; + /** State system */ + public final ITmfStateSystem ss; + /** Sorting mode */ + public final SortingMode sortingMode; + /** Filter modes */ + public final Set filterModes; + /** Full query */ + public final List fullQueryAtRangeStart; + + /** + * Constructor + * + * @param ss + * State system + * @param sortingMode + * Current sorting mode + * @param filterModes + * Current filter modes + * @param fullQueryAtRangeStart + * Full query at the start of the time range. + */ + public TreeRenderContext(String traceName, + ITmfStateSystem ss, + SortingMode sortingMode, + Set filterModes, + List fullQueryAtRangeStart) { + this.traceName = traceName; + this.ss = ss; + this.sortingMode = sortingMode; + this.filterModes = filterModes; + this.fullQueryAtRangeStart = fullQueryAtRangeStart; + } + } + + /** + * Class to encapsulate a cached {@link TimeGraphTreeRender}. This render + * should never change, except if the number of attributes in the state + * system does (for example, if queries were made before the state system + * was done building). + */ + private static final class CachedTreeRender { + + public final int nbAttributes; + public final TimeGraphTreeRender treeRender; + + public CachedTreeRender(int nbAttributes, TimeGraphTreeRender treeRender) { + this.nbAttributes = nbAttributes; + this.treeRender = treeRender; + } + } + + private final String fStateSystemModuleId; + private final Function fTreeRenderFunction; + + private final Map fLastTreeRenders = new WeakHashMap<>(); + + private transient @Nullable ITmfStateSystem fStateSystem = null; + + /** + * Constructor + * + * @param name + * The name of this provider + * @param sortingModes + * The available sorting modes + * @param filterModes + * The available filter modes + * @param stateProvider + * The state provider part of this model provider + * @param arrowProviders + * The arrow provider(s) supplied by this model provider + * @param stateSystemModuleId + * ID of the state system from which data will be fetched + * @param treeRenderFunction + * Function to generate a tree render for a given tree context + */ + public StateSystemModelProvider(String name, + @Nullable List sortingModes, + @Nullable List filterModes, + ITimeGraphModelStateProvider stateProvider, + @Nullable List arrowProviders, + String stateSystemModuleId, + Function treeRenderFunction) { + + super(name, sortingModes, filterModes, stateProvider, arrowProviders); + + fStateSystemModuleId = stateSystemModuleId; + fTreeRenderFunction = treeRenderFunction; + + /* + * Change listener which will take care of keeping the target state + * system up to date. + */ + traceProperty().addListener((obs, oldValue, newValue) -> { + ITmfTrace trace = newValue; + if (trace == null) { + fStateSystem = null; + return; + } + + /* + * Set the state system in another thread, so that if it blocks on + * waitForInitialization, it does not block the application + * thread... + * + * FIXME We ought to get rid of this blocking in Jabberwocky. + */ + Thread thread = new Thread(() -> { + fStateSystem = TmfStateSystemAnalysisModule.getStateSystem(trace, fStateSystemModuleId); + }); + thread.start(); + }); + } + + // ------------------------------------------------------------------------ + // Render generation methods + // ------------------------------------------------------------------------ + + @Override + public @NonNull TimeGraphTreeRender getTreeRender() { + ITmfStateSystem ss = fStateSystem; + if (ss == null) { + /* This trace does not provide the expected state system */ + return TimeGraphTreeRender.EMPTY_RENDER; + } + + CachedTreeRender cachedRender = fLastTreeRenders.get(ss); + if (cachedRender != null && cachedRender.nbAttributes == ss.getNbAttributes()) { + /* The last render is still valid, we can re-use it */ + return cachedRender.treeRender; + } + + /* First generate the tree render context */ + List fullStateAtStart; + try { + fullStateAtStart = ss.queryFullState(ss.getStartTime()); + } catch (StateSystemDisposedException e) { + return TimeGraphTreeRender.EMPTY_RENDER; + } + + ITmfTrace trace = getTrace(); + String traceName = (trace == null ? "" : trace.getName()); //$NON-NLS-1$ + + TreeRenderContext treeContext = new TreeRenderContext(traceName, + ss, + getCurrentSortingMode(), + getActiveFilterModes(), + fullStateAtStart); + + /* Generate a new tree render */ + TimeGraphTreeRender treeRender = fTreeRenderFunction.apply(treeContext); + + fLastTreeRenders.put(ss, new CachedTreeRender(ss.getNbAttributes(), treeRender)); + return treeRender; + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/statesystem/StateSystemModelStateProvider.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/statesystem/StateSystemModelStateProvider.java new file mode 100644 index 0000000000..797a9f92d0 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/statesystem/StateSystemModelStateProvider.java @@ -0,0 +1,318 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + *******************************************************************************/ + +package org.lttng.scope.tmf2.views.core.timegraph.model.provider.statesystem; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.FutureTask; +import java.util.function.Function; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.lttng.scope.tmf2.views.core.MathUtils; +import org.lttng.scope.tmf2.views.core.TimeRange; +import org.lttng.scope.tmf2.views.core.config.ConfigOption; +import org.lttng.scope.tmf2.views.core.timegraph.model.provider.states.TimeGraphModelStateProvider; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.ColorDefinition; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.LineThickness; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.StateDefinition; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.states.BasicTimeGraphStateInterval; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.states.MultiStateInterval; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.states.TimeGraphStateInterval; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.states.TimeGraphStateRender; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeElement; + +import com.google.common.collect.Iterables; + +import ca.polymtl.dorsal.libdelorean.ITmfStateSystem; +import ca.polymtl.dorsal.libdelorean.exceptions.AttributeNotFoundException; +import ca.polymtl.dorsal.libdelorean.exceptions.StateSystemDisposedException; +import ca.polymtl.dorsal.libdelorean.interval.ITmfStateInterval; + +/** + * Basic implementation of a {@link TimeGraphModelStateProvider} backed by a state + * system. + * + * @author Alexandre Montplaisir + */ +public class StateSystemModelStateProvider extends TimeGraphModelStateProvider { + + /** + * The context of a single state interval. Should contain all the + * information required to generate the state interval in the render (name, + * color, etc.) + */ + protected static final class StateIntervalContext { + + /** State system */ + public final ITmfStateSystem ss; + /** Base tree element */ + public final StateSystemTimeGraphTreeElement baseTreeElement; + /** Source interval */ + public final ITmfStateInterval sourceInterval; + + /** + * Constructor + * + * @param ss + * State system + * @param baseTreeElement + * Tree element for which the data should be fetched. It may + * not correspond directly to the state's tree element, a + * relative path may be used, for example for additional data + * stored in a separate attribute. + * @param sourceInterval + * The state system interval which will be represented by the + * model state interval + */ + public StateIntervalContext(ITmfStateSystem ss, + StateSystemTimeGraphTreeElement baseTreeElement, + ITmfStateInterval sourceInterval) { + this.ss = ss; + this.baseTreeElement = baseTreeElement; + this.sourceInterval = sourceInterval; + } + } + + private final String fStateSystemModuleId; + private final Function fIntervalMappingFunction; + + /** + * This state system here is not necessarily the same as the one in the + * {@link StateSystemModelProvider}! + */ + private transient @Nullable ITmfStateSystem fStateSystem = null; + + /** + * Constructor + * + * TODO Maybe merge the various Functions into a single class? + * + * @param stateDefinitions + * The state definitions used in this provider + * @param stateSystemModuleId + * The ID of the state system from which to fetch the information + * @param stateNameMappingFunction + * Mapping function from state interval context to state name + * @param labelMappingFunction + * Mapping function from state interval context to state label + * @param colorMappingFunction + * Mapping function from state interval context to state color + * @param lineThicknessMappingFunction + * Mapping function from state interval context to line thickness + * @param propertiesMappingFunction + * Mapping function from state interval context to properties + */ + public StateSystemModelStateProvider( + List stateDefinitions, + String stateSystemModuleId, + Function stateNameMappingFunction, + Function labelMappingFunction, + Function> colorMappingFunction, + Function> lineThicknessMappingFunction, + Function> propertiesMappingFunction) { + + super(stateDefinitions); + + fStateSystemModuleId = stateSystemModuleId; + + fIntervalMappingFunction = ssCtx -> { + return new BasicTimeGraphStateInterval( + ssCtx.sourceInterval.getStartTime(), + ssCtx.sourceInterval.getEndTime(), + ssCtx.baseTreeElement, + stateNameMappingFunction.apply(ssCtx), + labelMappingFunction.apply(ssCtx), + colorMappingFunction.apply(ssCtx), + lineThicknessMappingFunction.apply(ssCtx), + propertiesMappingFunction.apply(ssCtx)); + }; + + /* + * Change listener which will take care of keeping the target state + * system up to date. + */ + traceProperty().addListener((obs, oldValue, newValue) -> { + ITmfTrace trace = newValue; + if (trace == null) { + fStateSystem = null; + return; + } + + // FIXME Remove the extra thread once we move to Jabberwocky + Thread thread = new Thread(() -> { + fStateSystem = TmfStateSystemAnalysisModule.getStateSystem(trace, fStateSystemModuleId); + }); + thread.start(); + }); + + } + + // ------------------------------------------------------------------------ + // Render generation methods + // ------------------------------------------------------------------------ + + @Override + public TimeGraphStateRender getStateRender(TimeGraphTreeElement treeElement, + TimeRange timeRange, long resolution, @Nullable FutureTask task) { + + ITmfStateSystem ss = fStateSystem; + /* + * Sometimes ss is null with uninitialized or empty views, just keep the model + * empty. + */ + if (ss == null + || (task != null && task.isCancelled()) + /* "Title" entries should be ignored */ + || !(treeElement instanceof StateSystemTimeGraphTreeElement)) { + + return TimeGraphStateRender.EMPTY_RENDER; + } + StateSystemTimeGraphTreeElement treeElem = (StateSystemTimeGraphTreeElement) treeElement; + + /* Prepare the state intervals */ + List intervals; + try { + intervals = queryHistoryRange(ss, treeElem, + timeRange.getStart(), timeRange.getEnd(), resolution, task); + } catch (AttributeNotFoundException | StateSystemDisposedException e) { + intervals = Collections.emptyList(); + } + + return new TimeGraphStateRender(timeRange, treeElement, intervals); + } + + private List queryHistoryRange(ITmfStateSystem ss, + StateSystemTimeGraphTreeElement treeElem, + final long t1, final long t2, final long resolution, + @Nullable FutureTask task) + throws AttributeNotFoundException, StateSystemDisposedException { + + /* Validate the parameters. */ + if (t2 < t1 || resolution <= 0) { + throw new IllegalArgumentException(ss.getSSID() + " Start:" + t1 + ", End:" + t2 + ", Resolution:" + resolution); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + + final List modelIntervals = new LinkedList<>(); + final int attributeQuark = treeElem.getSourceQuark(); + ITmfStateInterval lastAddedInterval = null; + + /* Actual valid start/end time of the range query. */ + long tStart = Math.max(t1, ss.getStartTime()); + long tEnd = Math.min(t2, ss.getCurrentEndTime()); + + /* + * First, iterate over the "resolution points" and keep all matching + * state intervals. + */ + for (long ts = tStart; ts <= tEnd - resolution; ts += resolution) { + /* + * Skip queries if the corresponding interval was already included + */ + if (lastAddedInterval != null && lastAddedInterval.getEndTime() >= ts) { + long nextTOffset = MathUtils.roundToClosestHigherMultiple(lastAddedInterval.getEndTime() - tStart, resolution); + long nextTs = tStart + nextTOffset; + if (nextTs == ts) { + /* + * The end time of the last interval happened to be exactly + * equal to the next resolution point. We will go to the + * resolution point after that then. + */ + ts = nextTs; + } else { + /* 'ts' will get incremented at next loop */ + ts = nextTs - resolution; + } + continue; + } + + ITmfStateInterval stateSystemInterval = ss.querySingleState(ts, attributeQuark); + + /* + * Only pick the interval if it fills the current resolution range, + * from 'ts' to 'ts + resolution' (or 'ts2'). + */ + long ts2 = ts + resolution; + if (stateSystemInterval.getStartTime() <= ts && stateSystemInterval.getEndTime() >= ts2) { + TimeGraphStateInterval interval = ssIntervalToModelInterval(ss, treeElem, stateSystemInterval); + modelIntervals.add(interval); + lastAddedInterval = stateSystemInterval; + } + } + + /* + * For the very last interval, we'll use ['tEnd - resolution', 'tEnd'] + * as a range condition instead. + */ + long ts = Math.max(tStart, tEnd - resolution); + long ts2 = tEnd; + if (lastAddedInterval != null && lastAddedInterval.getEndTime() >= ts) { + /* Interval already included */ + } else { + ITmfStateInterval stateSystemInterval = ss.querySingleState(ts, attributeQuark); + if (stateSystemInterval.getStartTime() <= ts && stateSystemInterval.getEndTime() >= ts2) { + TimeGraphStateInterval interval = ssIntervalToModelInterval(ss, treeElem, stateSystemInterval); + modelIntervals.add(interval); + } + } + + /* + * 'modelIntervals' now contains all the "real" intervals we will want + * to display in the view. Poly-filla the holes in between each using + * multi-state intervals. + */ + if (modelIntervals.size() < 2) { + return modelIntervals; + } + + List filledIntervals = new LinkedList<>(); + /* + * Add the first real interval. There might be a multi-state at the + * beginning. + */ + long firstRealIntervalStartTime = modelIntervals.get(0).getStartTime(); + if (firstRealIntervalStartTime > tStart) { + filledIntervals.add(new MultiStateInterval(tStart, firstRealIntervalStartTime - 1, treeElem)); + } + filledIntervals.add(modelIntervals.get(0)); + + for (int i = 1; i < modelIntervals.size(); i++) { + TimeGraphStateInterval interval1 = modelIntervals.get(i - 1); + TimeGraphStateInterval interval2 = modelIntervals.get(i); + long bound1 = interval1.getEndTime(); + long bound2 = interval2.getStartTime(); + + /* (we've already inserted 'interval1' on the previous loop.) */ + if (bound1 + 1 != bound2) { + TimeGraphStateInterval multiStateInterval = new MultiStateInterval(bound1 + 1, bound2 - 1, treeElem); + filledIntervals.add(multiStateInterval); + } + filledIntervals.add(interval2); + } + + /* Add a multi-state at the end too, if needed */ + long lastRealIntervalEndTime = Iterables.getLast(modelIntervals).getEndTime(); + if (lastRealIntervalEndTime < t2) { + filledIntervals.add(new MultiStateInterval(lastRealIntervalEndTime + 1, t2, treeElem)); + } + + return filledIntervals; + } + + private TimeGraphStateInterval ssIntervalToModelInterval(ITmfStateSystem ss, + StateSystemTimeGraphTreeElement treeElem, ITmfStateInterval interval) { + StateIntervalContext siCtx = new StateIntervalContext(ss, treeElem, interval); + return fIntervalMappingFunction.apply(siCtx); + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/statesystem/StateSystemTimeGraphTreeElement.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/statesystem/StateSystemTimeGraphTreeElement.java new file mode 100644 index 0000000000..b7a1cf7f99 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/statesystem/StateSystemTimeGraphTreeElement.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + *******************************************************************************/ + +package org.lttng.scope.tmf2.views.core.timegraph.model.provider.statesystem; + +import java.util.List; + +import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeElement; + +/** + * Implementation of a {@link TimeGraphTreeElement} specific for use by + * {@link StateSystemModelProvider}. It links a state system quark to the tree + * element. + * + * @author Alexandre Montplaisir + */ +public class StateSystemTimeGraphTreeElement extends TimeGraphTreeElement { + + private final int fSourceQuark; + + /** + * Constructor + * + * @param name + * The name this tree element should have. + * @param children + * The children tree elements. You can pass an empty list for no + * children. + * @param sourceQuark + * The state system quark wrapped by this tree element + */ + public StateSystemTimeGraphTreeElement(String name, + List children, + int sourceQuark) { + super(name, children); + fSourceQuark = sourceQuark; + } + + /** + * Get the quark wrapped by this tree element. + * + * @return The source quark + */ + public int getSourceQuark() { + return fSourceQuark; + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/statesystem/package-info.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/statesystem/package-info.java new file mode 100644 index 0000000000..1c01f45b91 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/provider/statesystem/package-info.java @@ -0,0 +1,11 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc. and others + * + * 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 + *******************************************************************************/ + +@org.eclipse.jdt.annotation.NonNullByDefault +package org.lttng.scope.tmf2.views.core.timegraph.model.provider.statesystem; diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/ColorDefinition.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/ColorDefinition.java new file mode 100644 index 0000000000..805bc6160d --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/ColorDefinition.java @@ -0,0 +1,113 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + *******************************************************************************/ + +package org.lttng.scope.tmf2.views.core.timegraph.model.render; + +import java.util.Objects; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.eclipse.jdt.annotation.Nullable; + +/** + * Basic headless color definition, using RGB(A) values. + * + * @author Alexandre Montplaisir + */ +public class ColorDefinition { + + /** Minimum value for the parameters */ + public static final int MIN = 0; + /** Maximum value for the parameters */ + public static final int MAX = 255; + + /** Red RGB component */ + public final int fRed; + /** Green RGB component */ + public final int fGreen; + /** Blue RGB component */ + public final int fBlue; + /** Alpha component */ + public final int fAlpha; + + /** + * Specify a color by RGB values, using maximum (full) alpha. + * + * @param red + * Red component, from 0 to 255 + * @param green + * Green component, from 0 to 255 + * @param blue + * Blue component, from 0 to 255 + */ + public ColorDefinition(int red, int green, int blue) { + this(red, green, blue, MAX); + } + + /** + * Specify a color by RGBA values. + * + * @param red + * Red component, from 0 to 255 + * @param green + * Green component, from 0 to 255 + * @param blue + * Blue component, from 0 to 255 + * @param alpha + * Alpha (opacity) component, from 0 to 255 + */ + public ColorDefinition(int red, int green, int blue, int alpha) { + checkValue(red); + checkValue(green); + checkValue(blue); + checkValue(alpha); + + fRed = red; + fGreen = green; + fBlue = blue; + fAlpha = alpha; + } + + private static void checkValue(int value) throws IllegalArgumentException { + if (value < MIN || value > MAX) { + throw new IllegalArgumentException(); + } + } + + @Override + public int hashCode() { + return Objects.hash(fRed, fGreen, fBlue, fAlpha); + } + + @Override + public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + ColorDefinition other = (ColorDefinition) obj; + return (fRed == other.fRed + && fGreen == other.fGreen + && fBlue == other.fBlue + && fAlpha == other.fAlpha); + } + + @Override + public String toString() { + return IntStream.of(fRed, fGreen, fBlue, fAlpha) + .mapToObj(String::valueOf) + .collect(Collectors.joining(", ", "[", "]")); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/FlatUIColors.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/FlatUIColors.java new file mode 100644 index 0000000000..9f79049b3c --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/FlatUIColors.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.lttng.scope.tmf2.views.core.timegraph.model.render; + +/** + * Definition of UI colors, from https://flatuicolors.com/ . + */ +@SuppressWarnings("javadoc") +public interface FlatUIColors { + + ColorDefinition TURQUOISE = new ColorDefinition( 26, 188, 156); + ColorDefinition DARK_TURQUOISE = new ColorDefinition( 22, 160, 133); + ColorDefinition GREEN = new ColorDefinition( 46, 204, 113); + ColorDefinition DARK_GREEN = new ColorDefinition( 39, 174, 96); + ColorDefinition BLUE = new ColorDefinition( 52, 152, 219); + ColorDefinition DARK_BLUE = new ColorDefinition( 41, 128, 185); + ColorDefinition PURPLE = new ColorDefinition(155, 89, 182); + ColorDefinition DARK_PURPLE = new ColorDefinition(142, 68, 173); + ColorDefinition BLUE_GRAY = new ColorDefinition( 52, 73, 94); + ColorDefinition DARK_BLUE_GRAY = new ColorDefinition( 44, 62, 80); + ColorDefinition YELLOW = new ColorDefinition(241, 196, 15); + ColorDefinition DARK_YELLOW = new ColorDefinition(243, 156, 18); + ColorDefinition ORANGE = new ColorDefinition(230, 126, 34); + ColorDefinition DARK_ORANGE = new ColorDefinition(211, 84, 0); + ColorDefinition RED = new ColorDefinition(231, 76, 60); + ColorDefinition DARK_RED = new ColorDefinition(192, 57, 43); + ColorDefinition VERY_LIGHT_GRAY = new ColorDefinition(236, 240, 241); + ColorDefinition LIGHT_GRAY = new ColorDefinition(189, 195, 199); + ColorDefinition GRAY = new ColorDefinition(149, 165, 166); + ColorDefinition DARK_GRAY = new ColorDefinition(127, 140, 141); + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/LineThickness.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/LineThickness.java new file mode 100644 index 0000000000..ea76856ac6 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/LineThickness.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.core.timegraph.model.render; + +/** + * Headless definitions of possible values of state interval line thicknesses + */ +public enum LineThickness { + + /** Normal, full thickness */ + NORMAL, + /** + * Small thickness, should be between {@link #NORMAL} and {@link #TINY} and + * distinguishable from those two. + */ + SMALL, + /** + * Tiny line thickness. The line should be as small as possible but still + * have the color distinguishable. + */ + TINY + +} \ No newline at end of file diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/StateDefinition.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/StateDefinition.java new file mode 100644 index 0000000000..830cf5423a --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/StateDefinition.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.core.timegraph.model.render; + +import org.lttng.scope.tmf2.views.core.config.ConfigOption; + +/** + * Class defining the UI reprsentation of a state, as well as default values for + * them. + * + * @author Alexandre Montplaisir + */ +public class StateDefinition { + + private final String fName; + private final ConfigOption fColor; + private final ConfigOption fLineThickness; + + /** + * Build a new state definition. Re-use the same object where the same + * definition apply, so that the same configuration property is used. + * + * @param name + * The name of the definition + * @param defaultColor + * The default color to use + * @param defaultLineThickness + * The default line thickness to use + */ + public StateDefinition(String name, ColorDefinition defaultColor, LineThickness defaultLineThickness) { + fName = name; + fColor = new ConfigOption<>(defaultColor); + fLineThickness = new ConfigOption<>(defaultLineThickness); + } + + /** + * Get the name of this definition. + * + * @return The name + */ + public String getName() { + return fName; + } + + /** + * Get the color property of this definition. + * + * @return The color property + */ + public ConfigOption getColor() { + return fColor; + } + + /** + * Get the line thickness property of this definition. + * + * @return The line thickness property + */ + public ConfigOption getLineThickness() { + return fLineThickness; + } +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/TimeGraphEvent.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/TimeGraphEvent.java new file mode 100644 index 0000000000..b552242721 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/TimeGraphEvent.java @@ -0,0 +1,82 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + *******************************************************************************/ + +package org.lttng.scope.tmf2.views.core.timegraph.model.render; + +import java.util.Objects; + +import org.eclipse.jdt.annotation.Nullable; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeElement; + +/** + * A time graph event is a virtual representation of a location on the time + * graph, defined by its timestamp and tree element. + * + * It does not have a directly corresponding UI representation, but is used as + * an intermediate construct in intervals and drawn events, for example. + * + * @author Alexandre Montplaisir + */ +public class TimeGraphEvent { + + private final long fTimestamp; + private final TimeGraphTreeElement fTreeElement; + + /** + * Constructor + * + * @param timestamp + * The timestamp of the event + * @param treeElement + * The tree element to which this even belong + */ + public TimeGraphEvent(long timestamp, TimeGraphTreeElement treeElement) { + fTimestamp = timestamp; + fTreeElement = treeElement; + } + + /** + * Get the timestamp of this event. + * + * @return The timestamp + */ + public long getTimestamp() { + return fTimestamp; + } + + /** + * Get the tree element of this event. + * + * @return The tree element + */ + public TimeGraphTreeElement getTreeElement() { + return fTreeElement; + } + + @Override + public int hashCode() { + return Objects.hash(fTimestamp, fTreeElement); + } + + @Override + public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + TimeGraphEvent other = (TimeGraphEvent) obj; + return (fTimestamp == other.fTimestamp + && Objects.equals(fTreeElement, other.fTreeElement)); + } +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/arrows/TimeGraphArrow.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/arrows/TimeGraphArrow.java new file mode 100644 index 0000000000..3601932f2a --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/arrows/TimeGraphArrow.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2016-2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.core.timegraph.model.render.arrows; + +import org.lttng.scope.tmf2.views.core.timegraph.model.render.TimeGraphEvent; + +/** + * Model representation of a timegraph arrow. + * + * An arrow links two {@link TimeGraphEvent}s, and has a direction (a start + * event and a end event). The two events can belong to different tree elements, + * or the same one. + * + * @author Alexandre Montplaisir + */ +public class TimeGraphArrow { + + private final TimeGraphEvent fStartEvent; + private final TimeGraphEvent fEndEvent; + private final TimeGraphArrowSeries fArrowSeries; + + /** + * Constructor + * + * @param startEvent + * The start event of this arrow + * @param endEvent + * The end event of this arrow. The drawn arrowhead should be on + * this side + * @param series + * The series to which the arrow belongs. This series contains + * all the styling information. + */ + public TimeGraphArrow(TimeGraphEvent startEvent, TimeGraphEvent endEvent, TimeGraphArrowSeries series) { + fStartEvent = startEvent; + fEndEvent = endEvent; + fArrowSeries = series; + } + + /** + * Get the start event of this arrow. + * + * @return The start event + */ + public TimeGraphEvent getStartEvent() { + return fStartEvent; + } + + /** + * Get the end event of this arrow. + * + * @return The end event + */ + public TimeGraphEvent getEndEvent() { + return fEndEvent; + } + + /** + * Get the series of this arrow. + * + * @return The arrow series + */ + public TimeGraphArrowSeries getArrowSeries() { + return fArrowSeries; + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/arrows/TimeGraphArrowRender.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/arrows/TimeGraphArrowRender.java new file mode 100644 index 0000000000..e01978449a --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/arrows/TimeGraphArrowRender.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2016-2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.core.timegraph.model.render.arrows; + +import java.util.Collection; +import java.util.Collections; + +import org.lttng.scope.tmf2.views.core.TimeRange; + +import com.google.common.collect.ImmutableList; + +/** + * Render of time graph arrows, containing all possible arrows of a single + * series for a given time range. + * + * @author Alexandre Montplaisir + */ +public class TimeGraphArrowRender { + + /** Empty arrow render, can be used instead of a null value */ + public static final TimeGraphArrowRender EMPTY_RENDER = + new TimeGraphArrowRender(TimeRange.of(0, 0), Collections.EMPTY_LIST); + + private final TimeRange fTimeRange; + private final Collection fArrows; + + /** + * Constructor + * + * @param range + * Time range of this arrow render. For reference only, should + * probably match the time range of the query that created this + * render. + * @param arrows + * The arrows contained in this render. + */ + public TimeGraphArrowRender(TimeRange range, Iterable arrows) { + fTimeRange = range; + fArrows = ImmutableList.copyOf(arrows); + } + + /** + * Get the time range of this arrow render. + * + * @return The time range + */ + public TimeRange getTimeRange() { + return fTimeRange; + } + + /** + * Get the arrows contained in this render. + * + * @return The arrows + */ + public Collection getArrows() { + return fArrows; + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/arrows/TimeGraphArrowSeries.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/arrows/TimeGraphArrowSeries.java new file mode 100644 index 0000000000..951bc1c8f9 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/arrows/TimeGraphArrowSeries.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2016-2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.core.timegraph.model.render.arrows; + +import org.lttng.scope.tmf2.views.core.timegraph.model.render.ColorDefinition; + +/** + * Definition of a time graph arrow series. + * + * It contains all the styling information (name, color, line type, etc.) for + * the arrows part of this series. It does not however contain the arrows + * themselves, it is just the definition. The arrows will keep reference of what + * series they belong to. + * + * @author Alexandre Montplaisir + */ +public class TimeGraphArrowSeries { + + /** + * Headless definition of the style of the arrow line. + */ + public enum LineStyle { + /** Full line */ + FULL, + /** Line composed of dotsf */ + DOTTED, + /** Line composed of dashes */ + DASHED; + } + + private final String fSeriesName; + private final ColorDefinition fColor; + private final LineStyle fLineStyle; + + /** + * Constructor + * + * @param seriesName + * Name of this series + * @param color + * Suggested color for arrows of this series + * @param lineStyle + * Suggested line style for arrows of this series + */ + public TimeGraphArrowSeries(String seriesName, ColorDefinition color, LineStyle lineStyle) { + fSeriesName = seriesName; + fColor = color; + fLineStyle = lineStyle; + } + + /** + * Get the name of this series. + * + * @return The series's name + */ + public String getSeriesName() { + return fSeriesName; + } + + /** + * Get the suggested color of this series. + * + * @return The series's color + */ + public ColorDefinition getColor() { + return fColor; + } + + /** + * Get the suggested line style of this series. + * + * @return The series's line style + */ + public LineStyle getLineStyle() { + return fLineStyle; + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/arrows/package-info.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/arrows/package-info.java new file mode 100644 index 0000000000..7ac3a8f075 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/arrows/package-info.java @@ -0,0 +1,11 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc. and others + * + * 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 + *******************************************************************************/ + +@org.eclipse.jdt.annotation.NonNullByDefault +package org.lttng.scope.tmf2.views.core.timegraph.model.render.arrows; diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/drawnevents/TimeGraphDrawnEvent.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/drawnevents/TimeGraphDrawnEvent.java new file mode 100644 index 0000000000..ffd3c465ac --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/drawnevents/TimeGraphDrawnEvent.java @@ -0,0 +1,86 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + *******************************************************************************/ + +package org.lttng.scope.tmf2.views.core.timegraph.model.render.drawnevents; + +import java.util.Collections; +import java.util.Map; +import java.util.function.Supplier; + +import org.eclipse.jdt.annotation.Nullable; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.TimeGraphEvent; + +/** + * Model representation of a drawn event. + * + * A drawn event is a UI representation of a single {@link TimeGraphEvent}, with + * a given style. + * + * Additional properties can also be part of the drawn event, for example to be + * shown on mouse-over. + * + * @author Alexandre Montplaisir + */ +public class TimeGraphDrawnEvent { + + private final TimeGraphEvent fTimeGraphEvent; + private final TimeGraphDrawnEventSeries fEventSeries; + private final @Nullable Supplier> fPropertySupplier; + + /** + * Constructor + * + * @param event + * Time graph event (location) + * @param eventSeries + * Series of this event, which contains all the styling + * information + * @param propertySupplier + * Supplier of additional properties, which can be accessed only + * the first time {@link #getProperties()} is called. + */ + public TimeGraphDrawnEvent(TimeGraphEvent event, + TimeGraphDrawnEventSeries eventSeries, + @Nullable Supplier> propertySupplier) { + fTimeGraphEvent = event; + fEventSeries = eventSeries; + fPropertySupplier = propertySupplier; + } + + /** + * Get the timegraph event wrapped by this drawn event. + * + * @return The time graph event + */ + public TimeGraphEvent getEvent() { + return fTimeGraphEvent; + } + + /** + * Get the event series of this drawn event. + * + * @return The event's series + */ + public TimeGraphDrawnEventSeries getEventSeries() { + return fEventSeries; + } + + /** + * Get the additional properties of this drawn event. + * + * @return The event's properties + */ + public Map getProperties() { + Supplier> supplier = fPropertySupplier; + if (supplier == null) { + return Collections.EMPTY_MAP; + } + return supplier.get(); + } +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/drawnevents/TimeGraphDrawnEventRender.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/drawnevents/TimeGraphDrawnEventRender.java new file mode 100644 index 0000000000..afa3515384 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/drawnevents/TimeGraphDrawnEventRender.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + *******************************************************************************/ + +package org.lttng.scope.tmf2.views.core.timegraph.model.render.drawnevents; + +import java.util.Collection; + +import org.lttng.scope.tmf2.views.core.TimeRange; + +import com.google.common.collect.ImmutableList; + +/** + * Render of time graph drawn events. It can cover several (usually all) tree + * elements, unlike the TimeGraphStateRender which covers only a single element. + * + * @author Alexandre Montplaisir + */ +public class TimeGraphDrawnEventRender { + + private final TimeRange fTimeRange; + private final Collection fEvents; + + /** + * Constructor + * + * @param timeRange + * The time range of this draw event render. Should usually match + * the time range of the query that created this render. + * @param events + * The drawn events contained in this render + */ + public TimeGraphDrawnEventRender(TimeRange timeRange, + Iterable events) { + + fTimeRange = timeRange; + fEvents = ImmutableList.copyOf(events); + } + + /** + * Get the time range of this render + * + * @return The time range + */ + public TimeRange getTimeRange() { + return fTimeRange; + } + + /** + * Get the drawn events that are part of this render. + * + * @return The drawn events + */ + public Collection getEvents() { + return fEvents; + } +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/drawnevents/TimeGraphDrawnEventSeries.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/drawnevents/TimeGraphDrawnEventSeries.java new file mode 100644 index 0000000000..c5c46f1f8f --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/drawnevents/TimeGraphDrawnEventSeries.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2016-2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.core.timegraph.model.render.drawnevents; + +import org.lttng.scope.tmf2.views.core.config.ConfigOption; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.ColorDefinition; + +/** + * Definition of a time graph arrow series. + * + * It contains all the styling information (symbols, color, etc.) for the events + * that are part of this series. It does not contain the events themselves, the + * events will keep a reference to their series instead. + * + * @author Alexandre Montplaisir + */ +public class TimeGraphDrawnEventSeries { + + /** + * Headless symbol style definitions + */ + public enum SymbolStyle { + /** Circle */ + CIRCLE, + /** Cross */ + CROSS, + /** Star */ + STAR, + /** Square */ + SQUARE, + /** Diamond */ + DIAMOND, + /** Triangle */ + TRIANGLE; + } + + private final String fSeriesName; + private final ConfigOption fColor; + private final ConfigOption fSymbolStyle; + + /** + * Constructor. + * + * The parameters passed as {@link ConfigOption}s can be modified at + * runtime. + * + * @param seriesName + * Name of this event series + * @param color + * Color for this event series. + * @param symbolStyle + * Symbol style for this series + */ + public TimeGraphDrawnEventSeries(String seriesName, + ConfigOption color, + ConfigOption symbolStyle) { + + fSeriesName = seriesName; + fColor = color; + fSymbolStyle = symbolStyle; + } + + /** + * Get the name of this series + * + * @return This series's name + */ + public String getSeriesName() { + return fSeriesName; + } + + /** + * Get the configurable color of this series. + * + * @return This series's color + */ + public ConfigOption getColor() { + return fColor; + } + + /** + * Get the configurable symbol style of this series. + * + * @return This series's symbol style + */ + public ConfigOption getSymbolStyle() { + return fSymbolStyle; + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/drawnevents/package-info.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/drawnevents/package-info.java new file mode 100644 index 0000000000..772894a010 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/drawnevents/package-info.java @@ -0,0 +1,11 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc. and others + * + * 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 + *******************************************************************************/ + +@org.eclipse.jdt.annotation.NonNullByDefault +package org.lttng.scope.tmf2.views.core.timegraph.model.render.drawnevents; diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/package-info.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/package-info.java new file mode 100644 index 0000000000..9006109e9a --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/package-info.java @@ -0,0 +1,11 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc. and others + * + * 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 + *******************************************************************************/ + +@org.eclipse.jdt.annotation.NonNullByDefault +package org.lttng.scope.tmf2.views.core.timegraph.model.render; diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/states/BasicTimeGraphStateInterval.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/states/BasicTimeGraphStateInterval.java new file mode 100644 index 0000000000..82bdac4d24 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/states/BasicTimeGraphStateInterval.java @@ -0,0 +1,161 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + *******************************************************************************/ + +package org.lttng.scope.tmf2.views.core.timegraph.model.render.states; + +import java.util.Map; +import java.util.Objects; + +import org.eclipse.jdt.annotation.Nullable; +import org.lttng.scope.tmf2.views.core.config.ConfigOption; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.ColorDefinition; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.LineThickness; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.TimeGraphEvent; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeElement; + +import com.google.common.base.MoreObjects; + +/** + * Basic implementation of {@link TimeGraphStateInterval}. + * + * @author Alexandre Montplaisir + */ +public class BasicTimeGraphStateInterval implements TimeGraphStateInterval { + + private final TimeGraphEvent fStartEvent; + private final TimeGraphEvent fEndEvent; + + private final String fStateName; + private final @Nullable String fLabel; + private final ConfigOption fColor; + private final ConfigOption fLineThickness; + + private final Map fProperties; + + /** + * Constructor. + * + * It requires supplying the start time, end time, and tree element. The + * corresponding {@link TimeGraphEvent} will be created from those. + * + * @param start + * Start time + * @param end + * End time + * @param treeElement + * Tree element of this interval + * @param stateName + * State name + * @param label + * Label, see {@link #getLabel()} + * @param color + * Color + * @param lineThickness + * Line thickness + * @param properties + * Properties + */ + public BasicTimeGraphStateInterval(long start, + long end, + TimeGraphTreeElement treeElement, + String stateName, + @Nullable String label, + ConfigOption color, + ConfigOption lineThickness, + Map properties) { + + if (start > end || start < 0 || end < 0) { + throw new IllegalArgumentException(); + } + + fStartEvent = new TimeGraphEvent(start, treeElement); + fEndEvent = new TimeGraphEvent(end, treeElement); + + fStateName = stateName; + fLabel = label; + fColor = color; + fLineThickness = lineThickness; + fProperties = properties; + } + + @Override + public TimeGraphEvent getStartEvent() { + return fStartEvent; + } + + @Override + public TimeGraphEvent getEndEvent() { + return fEndEvent; + } + + @Override + public String getStateName() { + return fStateName; + } + + @Override + public @Nullable String getLabel() { + return fLabel; + } + + @Override + public ConfigOption getColorDefinition() { + return fColor; + } + + @Override + public ConfigOption getLineThickness() { + return fLineThickness; + } + + @Override + public boolean isMultiState() { + return false; + } + + @Override + public Map getProperties() { + return fProperties; + } + + @Override + public int hashCode() { + return Objects.hash(fStartEvent, fEndEvent, fStateName, fLabel, fColor, fLineThickness); + } + + @Override + public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + BasicTimeGraphStateInterval other = (BasicTimeGraphStateInterval) obj; + return (Objects.equals(fStartEvent, other.fStartEvent) + && Objects.equals(fEndEvent, other.fEndEvent) + && Objects.equals(fStateName, other.fStateName) + && Objects.equals(fLabel, other.fLabel) + && Objects.equals(fColor, other.fColor) + && fLineThickness == other.fLineThickness); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("start", fStartEvent.getTimestamp()) //$NON-NLS-1$ + .add("end", fEndEvent.getTimestamp()) //$NON-NLS-1$ + .add("name", fStateName) //$NON-NLS-1$ + .toString(); + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/states/MultiStateInterval.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/states/MultiStateInterval.java new file mode 100644 index 0000000000..4610fc01de --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/states/MultiStateInterval.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.core.timegraph.model.render.states; + +import java.util.Collections; + +import org.lttng.scope.tmf2.views.core.config.ConfigOption; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.ColorDefinition; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.LineThickness; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeElement; + +/** + * Dummy interval model object representing a "multi-state", which means a case + * where more than one state exists for a given pixel. + * + * @author Alexandre Montplaisir + */ +public final class MultiStateInterval extends BasicTimeGraphStateInterval { + + /** Configuration option for the line thickness of multi-state intervals */ + public static final ConfigOption MULTI_STATE_THICKNESS_OPTION = new ConfigOption<>(LineThickness.NORMAL); + + private static final String MULTI_STATE_NAME = "Multi-state"; //$NON-NLS-1$ + private static final ColorDefinition MULTI_STATE_COLOR = new ColorDefinition(0, 0, 0); + private static final ConfigOption MULTI_STATE_COLOR_OPTION = new ConfigOption<>(MULTI_STATE_COLOR); + + /** + * Constructor + * + * @param startTime + * Start time + * @param endTime + * End time + * @param treeElement + * The tree element to which this interval is associated + */ + public MultiStateInterval(long startTime, long endTime, TimeGraphTreeElement treeElement) { + super(startTime, + endTime, + treeElement, + MULTI_STATE_NAME, + /* Label */ + null, + MULTI_STATE_COLOR_OPTION, + MULTI_STATE_THICKNESS_OPTION, + Collections.emptyMap()); + } + + @Override + public boolean isMultiState() { + return true; + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/states/TimeGraphStateInterval.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/states/TimeGraphStateInterval.java new file mode 100644 index 0000000000..dccb595225 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/states/TimeGraphStateInterval.java @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.core.timegraph.model.render.states; + +import java.util.Map; + +import org.eclipse.jdt.annotation.Nullable; +import org.lttng.scope.tmf2.views.core.config.ConfigOption; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.ColorDefinition; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.LineThickness; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.TimeGraphEvent; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeElement; + +/** + * Base interface for time graph state interval, which is defined by a start + * time, end time, and a state. + * + * @author Alexandre Montplaisir + */ +public interface TimeGraphStateInterval { + + /** + * Return the start event of this interval. + * + * @return The start event + */ + TimeGraphEvent getStartEvent(); + + /** + * Return the end event of this interval. + * + * @return The end event + */ + TimeGraphEvent getEndEvent(); + + /** + * Get the name of the state represented by this interval. + * + * @return The state name + */ + String getStateName(); + + /** + * Get the label of this interval. This means the text that is meant to be + * displayed alongside the interval's color. It may or may not be the same + * as the {@link #getStateName()}. + * + * @return The optional label of this interval + */ + @Nullable String getLabel(); + + /** + * Get the color suggested for this interval. + * + * @return The color of this interval + */ + ConfigOption getColorDefinition(); + + /** + * Get the suggested line thickness of this interval. + * + * @return The line thickness + */ + ConfigOption getLineThickness(); + + /** + * Indicate if this interval represents multiple states, or a single one. + * + * @return If this interval is a multi-state one + */ + boolean isMultiState(); + + /** + * Get the properties associated with this state interval. This is extra, + * generic data that can be attached to the interval. Views can display + * those in a tooltip, for example. + * + * @return The additional properties. + */ + Map getProperties(); + + /** + * Get the start time of this interval, which is effectively the timestamp + * of the start event. + * + * @return The start time + */ + default long getStartTime() { + return getStartEvent().getTimestamp(); + } + + /** + * Get the end time of this interval, which is effectively the timestamp of + * the end event. + * + * @return The end time + */ + default long getEndTime() { + return getEndEvent().getTimestamp(); + } + + /** + * Get the duration of this interval, effectively end time minus start time. + * + * @return The duration + */ + default long getDuration() { + return (getEndTime() - getStartTime()); + } + + /** + * Get the tree element of this interval's start and end events. + * + * @return The tree element + */ + default TimeGraphTreeElement getTreeElement() { + return getStartEvent().getTreeElement(); + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/states/TimeGraphStateRender.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/states/TimeGraphStateRender.java new file mode 100644 index 0000000000..bd174130ea --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/states/TimeGraphStateRender.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + *******************************************************************************/ + +package org.lttng.scope.tmf2.views.core.timegraph.model.render.states; + +import java.util.Collections; +import java.util.List; + +import org.lttng.scope.tmf2.views.core.TimeRange; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeElement; + +import com.google.common.collect.ImmutableList; + +/** + * "Segment" of a time graph, representing the states of a single tree element + * for a given time range. + * + * @author Alexandre Montplaisir + */ +public class TimeGraphStateRender { + + /** Non-null reference to a dummy/empty render */ + public static final TimeGraphStateRender EMPTY_RENDER = new TimeGraphStateRender(TimeRange.of(0, 0), TimeGraphTreeElement.DUMMY_ELEMENT, Collections.emptyList()); + + private final TimeRange fTimeRange; + private final TimeGraphTreeElement fTreeElement; + private final List fStateIntervals; + + /** + * Constructor + * + * @param timeRange + * The time range of this state render. This is for informative + * use mostly, and usually matches the time range that was + * requested for the query that generated this render. + * @param treeElement + * This render contains state intervals of this single tree + * element + * @param stateIntervals + * The state intervals that are part of this render. Their range + * should normally match the 'timeRange' parameter. + */ + public TimeGraphStateRender(TimeRange timeRange, + TimeGraphTreeElement treeElement, + List stateIntervals) { + + fTimeRange = timeRange; + fTreeElement = treeElement; + fStateIntervals = ImmutableList.copyOf(stateIntervals); + } + + /** + * Get the time range of this interval. + * + * @return The time range + */ + public TimeRange getTimeRange() { + return fTimeRange; + } + + /** + * Get the tree element to which the intervals of this render belongs. + * + * @return The tree element + */ + public TimeGraphTreeElement getTreeElement() { + return fTreeElement; + } + + /** + * Get the state intervals that are part of this state render + * + * @return The state intervals + */ + public List getStateIntervals() { + return fStateIntervals; + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/states/package-info.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/states/package-info.java new file mode 100644 index 0000000000..945c684621 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/states/package-info.java @@ -0,0 +1,11 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc. and others + * + * 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 + *******************************************************************************/ + +@org.eclipse.jdt.annotation.NonNullByDefault +package org.lttng.scope.tmf2.views.core.timegraph.model.render.states; diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/tree/TimeGraphTreeElement.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/tree/TimeGraphTreeElement.java new file mode 100644 index 0000000000..1488135d7d --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/tree/TimeGraphTreeElement.java @@ -0,0 +1,122 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + *******************************************************************************/ + +package org.lttng.scope.tmf2.views.core.timegraph.model.render.tree; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.function.Predicate; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.tmf.core.event.ITmfEvent; + +import com.google.common.base.MoreObjects; +import com.google.common.collect.ImmutableList; + +/** + * The "tree element" is the unit of a timegraph represented by a single line. + * State intervals are aligned with tree elements to represent the states of the + * attribute represented by its tree element. + * + * Tree elements can have children, which allows representing them as a tree + * structure. At the visualization layer, sub-trees could be allowed to be + * expanded/collapsed, which can then change the number of visible tree elements + * in the timegraph. + * + * @author Alexandre Montplaisir + */ +public class TimeGraphTreeElement { + + /** Non-null reference to a dummy element */ + public static final TimeGraphTreeElement DUMMY_ELEMENT = new TimeGraphTreeElement("Dummy", Collections.emptyList()); //$NON-NLS-1$ + + private final String fName; + private final List fChildElements; + + /** + * Constructor, build a tree element by specifying its name and children + * elements. + * + * @param name + * The name this tree element should have. + * @param children + * The children tree elements. You can pass an empty list for no + * children. + */ + public TimeGraphTreeElement(String name, List children) { + fName = name; + fChildElements = ImmutableList.copyOf(children); + } + + /** + * Get the name of this tree element. + * + * @return The element's name + */ + public String getName() { + return fName; + } + + /** + * Get the child elements of this tree element. + * + * @return The child elements + */ + public List getChildElements() { + return fChildElements; + } + + /** + * Determine if and how this tree element corresponds to a component of a + * trace event. + * + * For example, if this tree element represents "CPU #2", then the predicate + * should return true for all trace events belonging to CPU #2. + * + * The method returns null if this tree element does not correspond to a + * particular aspect of trace events. + * + * @return The event matching predicate, if there is one + */ + public @Nullable Predicate getEventMatching() { + /* Sub-classes can override */ + return null; + } + + @Override + public int hashCode() { + return Objects.hash(fName, fChildElements); + } + + @Override + public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + TimeGraphTreeElement other = (TimeGraphTreeElement) obj; + return Objects.equals(fName, other.fName) + && Objects.equals(fChildElements, other.fChildElements); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("fName", fName) //$NON-NLS-1$ + .add("fChildElements", fChildElements.toString()) //$NON-NLS-1$ + .toString(); + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/tree/TimeGraphTreeRender.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/tree/TimeGraphTreeRender.java new file mode 100644 index 0000000000..4be4991705 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/tree/TimeGraphTreeRender.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + *******************************************************************************/ + +package org.lttng.scope.tmf2.views.core.timegraph.model.render.tree; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.eclipse.jdt.annotation.Nullable; +import org.lttng.scope.common.core.StreamUtils.StreamFlattener; + +/** + * Render of a tree of the timegraph. Contains the tree elements that compose + * the current tree. + * + * In a timegraph, the "tree" part is usually shown on the left-hand side, and + * lists the tree elements, which represent attributes of a model. A tree render + * is a "snapshot" of this tree that is valid for a given timestamp or + * timerange. + * + * Some timegraphs may use a tree that is valid for the whole time range of a + * trace. Other timegraphs may display a different tree for different parts of + * the trace. + * + * @author Alexandre Montplaisir + */ +public class TimeGraphTreeRender { + + /** + * A static reference to an empty render, which can be used to represent an + * uninitialized state for example (by comparing with ==). + */ + public static final TimeGraphTreeRender EMPTY_RENDER = new TimeGraphTreeRender(TimeGraphTreeElement.DUMMY_ELEMENT); + + private final TimeGraphTreeElement fRootElement; + + /** + * Constructor + * + * @param rootElement + * The root element of the tree + */ + public TimeGraphTreeRender(TimeGraphTreeElement rootElement) { + fRootElement = rootElement; + } + + /** + * Return the root element of this tree. + * + * @return The root element + */ + public TimeGraphTreeElement getRootElement() { + return fRootElement; + } + + /** + * Get a flattened view of all the tree elements in this render. + * + * This should also contains all the child elements that are also contained + * in each element's {@link TimeGraphTreeElement#getChildElements()}. It can + * be used to run an action on all elements of a render. + * + * @return A list of all the tree elements + */ + public List getAllTreeElements() { + StreamFlattener flattener = new StreamFlattener<>(i -> i.getChildElements().stream()); + return flattener.flatten(getRootElement()).collect(Collectors.toList()); + } + + @Override + public int hashCode() { + return Objects.hash(fRootElement); + } + + @Override + public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + TimeGraphTreeRender other = (TimeGraphTreeRender) obj; + return (Objects.equals(fRootElement, other.fRootElement)); + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/tree/package-info.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/tree/package-info.java new file mode 100644 index 0000000000..16722c7114 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/model/render/tree/package-info.java @@ -0,0 +1,11 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc. and others + * + * 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 + *******************************************************************************/ + +@org.eclipse.jdt.annotation.NonNullByDefault +package org.lttng.scope.tmf2.views.core.timegraph.model.render.tree; diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/view/TimeGraphModelView.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/view/TimeGraphModelView.java new file mode 100644 index 0000000000..f8c36dce9b --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/view/TimeGraphModelView.java @@ -0,0 +1,102 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + *******************************************************************************/ + +package org.lttng.scope.tmf2.views.core.timegraph.view; + +import org.lttng.scope.tmf2.views.core.TimeRange; +import org.lttng.scope.tmf2.views.core.context.ViewGroupContext; +import org.lttng.scope.tmf2.views.core.timegraph.control.TimeGraphModelControl; + +/** + * Base class for time graph view objects. + * + * A view is attached to a {@link TimeGraphModelControl} (passed at the + * constructor), which will then call the view's method accordingly to + * reposition, repaint, etc. the timegraph according to actions taken elsewhere + * in the framework. + * + * @author Alexandre Montplaisir + */ +public abstract class TimeGraphModelView { + + private final TimeGraphModelControl fControl; + + /** + * Constructor. Build a new view by specifying its corresponding control. + * You will most probably want to call + * {@link TimeGraphModelControl#attachView} afterwards, this is not done + * automatically! + * + * @param control + * The control that will manage this view + */ + public TimeGraphModelView(TimeGraphModelControl control) { + fControl = control; + } + + /** + * Retrieve the control managing this view. + * + * @return The model control + */ + public final TimeGraphModelControl getControl() { + return fControl; + } + + /** + * Dispose this view + */ + public final void dispose() { + disposeImpl(); + } + + /** + * Get the view context of this view/control. + * + * @return The current view context + */ + public final ViewGroupContext getViewContext() { + return getControl().getViewContext(); + } + + // ------------------------------------------------------------------------ + // Template methods + // ------------------------------------------------------------------------ + + /** + * Abstract implementation of a dispose method. Sub-classes should clean up + * the state they add to the base view class. + */ + protected abstract void disposeImpl(); + + /** + * Request the timegraph to be completely cleared of its contents, for + * example when no trace is opened at all. + */ + public abstract void clear(); + + /** + * This should be called whenever the visible window moves, including zoom + * level changes. + * + * @param newVisibleRange + * The range to where the view should be seeked + */ + public abstract void seekVisibleRange(TimeRange newVisibleRange); + + /** + * Draw a new selection rectangle. The previous one, if any, will be + * removed. + * + * @param selectionRange + * The selection that should be drawn + */ + public abstract void drawSelection(TimeRange selectionRange); + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/view/json/RenderToJson.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/view/json/RenderToJson.java new file mode 100644 index 0000000000..e8038246b0 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/view/json/RenderToJson.java @@ -0,0 +1,97 @@ +package org.lttng.scope.tmf2.views.core.timegraph.view.json; + +import java.io.IOException; +import java.io.Writer; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.states.TimeGraphStateRender; + +import com.google.common.base.Charsets; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +final class RenderToJson { + + private RenderToJson() {} + + private static final boolean PRETTY_PRINT = true; + private static final int VERSION = 1; + + private static final String VERSION_KEY = "version"; //$NON-NLS-1$ + private static final String INTERVALS_KEY = "intervals"; //$NON-NLS-1$ + + private static final String TREE_ELEMENT_KEY = "elem"; //$NON-NLS-1$ + private static final String START_TIME_KEY = "start"; //$NON-NLS-1$ + private static final String END_TIME_KEY = "end"; //$NON-NLS-1$ + private static final String STATE_NAME_KEY = "state"; //$NON-NLS-1$ + private static final String COLOR_KEY = "color"; //$NON-NLS-1$ + + private static final Path OUTPUT_FILE = Paths.get("/home/alexandre/json-output"); //$NON-NLS-1$ + static { + try { + if (Files.exists(OUTPUT_FILE)) { + Files.delete(OUTPUT_FILE); + } + Files.createFile(OUTPUT_FILE); + } catch (IOException e) { + } + } + + private static final Gson GSON; + static { + if (PRETTY_PRINT) { + GSON = new GsonBuilder().setPrettyPrinting().create(); + } else { + GSON = new Gson(); + } + } + + public static void printRenderTo1(List renders) { + String json = GSON.toJson(renders); + try (Writer bw = Files.newBufferedWriter(OUTPUT_FILE, Charsets.UTF_8)) { + bw.write(json); + bw.flush(); + } catch (IOException e1) { + } + } + + public static void printRenderTo(List renders) { + try (Writer bw = Files.newBufferedWriter(OUTPUT_FILE, Charsets.UTF_8)) { + JSONObject root = new JSONObject(); + root.put(VERSION_KEY, VERSION); + + JSONArray intervalsRoot = new JSONArray(); + root.put(INTERVALS_KEY, intervalsRoot); + + renders.stream() + .flatMap(render -> render.getStateIntervals().stream()) + .forEach(interval -> { + try { + JSONObject intervalObject = new JSONObject(); + intervalObject.put(TREE_ELEMENT_KEY, interval.getStartEvent().getTreeElement().getName()); + intervalObject.put(START_TIME_KEY, interval.getStartEvent().getTimestamp()); + intervalObject.put(END_TIME_KEY, interval.getEndEvent().getTimestamp()); + intervalObject.put(STATE_NAME_KEY, interval.getStateName()); + intervalObject.put(COLOR_KEY, interval.getColorDefinition().toString()); + + intervalsRoot.put(intervalObject); + } catch (JSONException e) { + /* Skip this interval */ + } + }); + + String json = (PRETTY_PRINT ? root.toString(1) : root.toString()); + bw.write(json); + bw.flush(); + + } catch (JSONException | IOException e) { + } + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/view/json/TimeGraphJsonOutput.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/view/json/TimeGraphJsonOutput.java new file mode 100644 index 0000000000..51c02c403e --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/view/json/TimeGraphJsonOutput.java @@ -0,0 +1,44 @@ +package org.lttng.scope.tmf2.views.core.timegraph.view.json; + +import java.util.List; + +import org.lttng.scope.tmf2.views.core.TimeRange; +import org.lttng.scope.tmf2.views.core.timegraph.control.TimeGraphModelControl; +import org.lttng.scope.tmf2.views.core.timegraph.model.provider.ITimeGraphModelProvider; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.states.TimeGraphStateRender; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeRender; +import org.lttng.scope.tmf2.views.core.timegraph.view.TimeGraphModelView; + +public class TimeGraphJsonOutput extends TimeGraphModelView { + + public TimeGraphJsonOutput(TimeGraphModelControl control) { + super(control); + } + + @Override + public void disposeImpl() { + } + + @Override + public void clear() { + // TODO + } + + @Override + public void seekVisibleRange(TimeRange newVisibleRange) { + /* Generate JSON for the visible area */ + ITimeGraphModelProvider provider = getControl().getModelRenderProvider(); + + TimeGraphTreeRender treeRender = provider.getTreeRender(); + List stateRenders = provider.getStateProvider().getStateRenders(treeRender, + newVisibleRange, 1, null); + + RenderToJson.printRenderTo(stateRenders); + } + + @Override + public void drawSelection(TimeRange selectionRange) { + // TODO NYI + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/view/json/package-info.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/view/json/package-info.java new file mode 100644 index 0000000000..babd29aad8 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/view/json/package-info.java @@ -0,0 +1,11 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc. and others + * + * 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 + *******************************************************************************/ + +@org.eclipse.jdt.annotation.NonNullByDefault +package org.lttng.scope.tmf2.views.core.timegraph.view.json; diff --git a/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/view/package-info.java b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/view/package-info.java new file mode 100644 index 0000000000..278940dc49 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.core/src/org/lttng/scope/tmf2/views/core/timegraph/view/package-info.java @@ -0,0 +1,11 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc. and others + * + * 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 + *******************************************************************************/ + +@org.eclipse.jdt.annotation.NonNullByDefault +package org.lttng.scope.tmf2.views.core.timegraph.view; diff --git a/tmf/org.lttng.scope.tmf2.views.ui/.classpath b/tmf/org.lttng.scope.tmf2.views.ui/.classpath new file mode 100644 index 0000000000..0be7b35db4 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/.classpath @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/tmf/org.lttng.scope.tmf2.views.ui/.project b/tmf/org.lttng.scope.tmf2.views.ui/.project new file mode 100644 index 0000000000..f37a15180a --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/.project @@ -0,0 +1,34 @@ + + + org.lttng.scope.tmf2.views.ui + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.pde.api.tools.apiAnalysisBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + org.eclipse.pde.api.tools.apiAnalysisNature + + diff --git a/tmf/org.lttng.scope.tmf2.views.ui/.settings/org.eclipse.core.resources.prefs b/tmf/org.lttng.scope.tmf2.views.ui/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000000..99f26c0203 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/tmf/org.lttng.scope.tmf2.views.ui/.settings/org.eclipse.core.runtime.prefs b/tmf/org.lttng.scope.tmf2.views.ui/.settings/org.eclipse.core.runtime.prefs new file mode 100644 index 0000000000..5a0ad22d2a --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/.settings/org.eclipse.core.runtime.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +line.separator=\n diff --git a/tmf/org.lttng.scope.tmf2.views.ui/.settings/org.eclipse.jdt.core.prefs b/tmf/org.lttng.scope.tmf2.views.ui/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..bf5f566b99 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,436 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.codeComplete.argumentPrefixes= +org.eclipse.jdt.core.codeComplete.argumentSuffixes= +org.eclipse.jdt.core.codeComplete.fieldPrefixes=f +org.eclipse.jdt.core.codeComplete.fieldSuffixes= +org.eclipse.jdt.core.codeComplete.localPrefixes= +org.eclipse.jdt.core.codeComplete.localSuffixes= +org.eclipse.jdt.core.codeComplete.staticFieldPrefixes= +org.eclipse.jdt.core.codeComplete.staticFieldSuffixes= +org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes= +org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes= +org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=enabled +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=info +org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnull.secondary= +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary= +org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable +org.eclipse.jdt.core.compiler.annotation.nullable.secondary= +org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.doc.comment.support=enabled +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=error +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=error +org.eclipse.jdt.core.compiler.problem.deadCode=error +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=error +org.eclipse.jdt.core.compiler.problem.fallthroughCase=error +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=error +org.eclipse.jdt.core.compiler.problem.finalParameterBound=error +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=error +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=error +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=error +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=error +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=error +org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning +org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=protected +org.eclipse.jdt.core.compiler.problem.localVariableHiding=error +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error +org.eclipse.jdt.core.compiler.problem.missingDefaultCase=error +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=error +org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=enabled +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=error +org.eclipse.jdt.core.compiler.problem.missingJavadocComments=warning +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=protected +org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=all_standard_tags +org.eclipse.jdt.core.compiler.problem.missingJavadocTags=warning +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=protected +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=error +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=error +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=error +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=error +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning +org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning +org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=info +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=warning +org.eclipse.jdt.core.compiler.problem.nullReference=error +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=error +org.eclipse.jdt.core.compiler.problem.parameterAssignment=error +org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error +org.eclipse.jdt.core.compiler.problem.potentialNullReference=error +org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=error +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=error +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=error +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=error +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=error +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unclosedCloseable=error +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=error +org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning +org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled +org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=error +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=error +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=disabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=disabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=error +org.eclipse.jdt.core.compiler.problem.unusedLocal=error +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameter=warning +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=warning +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error +org.eclipse.jdt.core.compiler.source=1.8 +org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header=0 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_type_arguments=0 +org.eclipse.jdt.core.formatter.alignment_for_type_parameters=0 +org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=true +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert +org.eclipse.jdt.core.formatter.comment.line_length=80 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=2 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false +org.eclipse.jdt.core.formatter.indentation.size=4 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=true +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=250 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause=common_lines +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_on_off_tags=false +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_assignment_operator=false +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_before_conditional_operator=true +org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true +org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter diff --git a/tmf/org.lttng.scope.tmf2.views.ui/.settings/org.eclipse.jdt.ui.prefs b/tmf/org.lttng.scope.tmf2.views.ui/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 0000000000..2591ac9163 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,65 @@ +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +formatter_profile=_tmf-style +formatter_settings_version=12 +org.eclipse.jdt.ui.exception.name=e +org.eclipse.jdt.ui.gettersetter.use.is=true +org.eclipse.jdt.ui.keywordthis=false +org.eclipse.jdt.ui.overrideannotation=true +sp_cleanup.add_default_serial_version_id=true +sp_cleanup.add_generated_serial_version_id=false +sp_cleanup.add_missing_annotations=false +sp_cleanup.add_missing_deprecated_annotations=true +sp_cleanup.add_missing_methods=false +sp_cleanup.add_missing_nls_tags=false +sp_cleanup.add_missing_override_annotations=true +sp_cleanup.add_missing_override_annotations_interface_methods=true +sp_cleanup.add_serial_version_id=false +sp_cleanup.always_use_blocks=true +sp_cleanup.always_use_parentheses_in_expressions=false +sp_cleanup.always_use_this_for_non_static_field_access=false +sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.convert_functional_interfaces=false +sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.correct_indentation=false +sp_cleanup.format_source_code=false +sp_cleanup.format_source_code_changes_only=false +sp_cleanup.insert_inferred_type_arguments=false +sp_cleanup.make_local_variable_final=false +sp_cleanup.make_parameters_final=false +sp_cleanup.make_private_fields_final=true +sp_cleanup.make_type_abstract_if_missing_method=false +sp_cleanup.make_variable_declarations_final=false +sp_cleanup.never_use_blocks=false +sp_cleanup.never_use_parentheses_in_expressions=true +sp_cleanup.on_save_use_additional_actions=true +sp_cleanup.organize_imports=true +sp_cleanup.qualify_static_field_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_redundant_type_arguments=false +sp_cleanup.remove_trailing_whitespaces=true +sp_cleanup.remove_trailing_whitespaces_all=true +sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +sp_cleanup.remove_unnecessary_casts=false +sp_cleanup.remove_unnecessary_nls_tags=false +sp_cleanup.remove_unused_imports=false +sp_cleanup.remove_unused_local_variables=false +sp_cleanup.remove_unused_private_fields=true +sp_cleanup.remove_unused_private_members=false +sp_cleanup.remove_unused_private_methods=true +sp_cleanup.remove_unused_private_types=true +sp_cleanup.sort_members=false +sp_cleanup.sort_members_all=false +sp_cleanup.use_anonymous_class_creation=false +sp_cleanup.use_blocks=true +sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_lambda=true +sp_cleanup.use_parentheses_in_expressions=false +sp_cleanup.use_this_for_non_static_field_access=false +sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true +sp_cleanup.use_this_for_non_static_method_access=false +sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/tmf/org.lttng.scope.tmf2.views.ui/.settings/org.eclipse.pde.api.tools.prefs b/tmf/org.lttng.scope.tmf2.views.ui/.settings/org.eclipse.pde.api.tools.prefs new file mode 100644 index 0000000000..ce92bf3ae1 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/.settings/org.eclipse.pde.api.tools.prefs @@ -0,0 +1,102 @@ +ANNOTATION_ELEMENT_TYPE_ADDED_METHOD_WITHOUT_DEFAULT_VALUE=Error +ANNOTATION_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error +ANNOTATION_ELEMENT_TYPE_REMOVED_FIELD=Error +ANNOTATION_ELEMENT_TYPE_REMOVED_METHOD=Error +ANNOTATION_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error +API_COMPONENT_ELEMENT_TYPE_REMOVED_API_TYPE=Error +API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_API_TYPE=Error +API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_TYPE=Error +API_COMPONENT_ELEMENT_TYPE_REMOVED_TYPE=Error +API_USE_SCAN_FIELD_SEVERITY=Error +API_USE_SCAN_METHOD_SEVERITY=Error +API_USE_SCAN_TYPE_SEVERITY=Error +CLASS_ELEMENT_TYPE_ADDED_METHOD=Error +CLASS_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error +CLASS_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error +CLASS_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error +CLASS_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error +CLASS_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error +CLASS_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error +CLASS_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error +CLASS_ELEMENT_TYPE_REMOVED_CONSTRUCTOR=Error +CLASS_ELEMENT_TYPE_REMOVED_FIELD=Error +CLASS_ELEMENT_TYPE_REMOVED_METHOD=Error +CLASS_ELEMENT_TYPE_REMOVED_SUPERCLASS=Error +CLASS_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error +CLASS_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error +CONSTRUCTOR_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error +CONSTRUCTOR_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error +CONSTRUCTOR_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error +CONSTRUCTOR_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error +ENUM_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error +ENUM_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error +ENUM_ELEMENT_TYPE_REMOVED_ENUM_CONSTANT=Error +ENUM_ELEMENT_TYPE_REMOVED_FIELD=Error +ENUM_ELEMENT_TYPE_REMOVED_METHOD=Error +ENUM_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error +FIELD_ELEMENT_TYPE_ADDED_VALUE=Error +FIELD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error +FIELD_ELEMENT_TYPE_CHANGED_FINAL_TO_NON_FINAL_STATIC_CONSTANT=Error +FIELD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error +FIELD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error +FIELD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error +FIELD_ELEMENT_TYPE_CHANGED_TYPE=Error +FIELD_ELEMENT_TYPE_CHANGED_VALUE=Error +FIELD_ELEMENT_TYPE_REMOVED_TYPE_ARGUMENT=Error +FIELD_ELEMENT_TYPE_REMOVED_VALUE=Error +ILLEGAL_EXTEND=Warning +ILLEGAL_IMPLEMENT=Warning +ILLEGAL_INSTANTIATE=Warning +ILLEGAL_OVERRIDE=Warning +ILLEGAL_REFERENCE=Warning +INTERFACE_ELEMENT_TYPE_ADDED_DEFAULT_METHOD=Ignore +INTERFACE_ELEMENT_TYPE_ADDED_FIELD=Error +INTERFACE_ELEMENT_TYPE_ADDED_METHOD=Error +INTERFACE_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error +INTERFACE_ELEMENT_TYPE_ADDED_SUPER_INTERFACE_WITH_METHODS=Error +INTERFACE_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error +INTERFACE_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error +INTERFACE_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error +INTERFACE_ELEMENT_TYPE_REMOVED_FIELD=Error +INTERFACE_ELEMENT_TYPE_REMOVED_METHOD=Error +INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error +INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error +INVALID_ANNOTATION=Warning +INVALID_JAVADOC_TAG=Warning +INVALID_REFERENCE_IN_SYSTEM_LIBRARIES=Warning +LEAK_EXTEND=Warning +LEAK_FIELD_DECL=Warning +LEAK_IMPLEMENT=Warning +LEAK_METHOD_PARAM=Warning +LEAK_METHOD_RETURN_TYPE=Warning +METHOD_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error +METHOD_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error +METHOD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error +METHOD_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error +METHOD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error +METHOD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error +METHOD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error +METHOD_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error +METHOD_ELEMENT_TYPE_REMOVED_ANNOTATION_DEFAULT_VALUE=Error +METHOD_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error +MISSING_EE_DESCRIPTIONS=Ignore +TYPE_PARAMETER_ELEMENT_TYPE_ADDED_CLASS_BOUND=Error +TYPE_PARAMETER_ELEMENT_TYPE_ADDED_INTERFACE_BOUND=Error +TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_CLASS_BOUND=Error +TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_INTERFACE_BOUND=Error +TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_CLASS_BOUND=Error +TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_INTERFACE_BOUND=Error +UNUSED_PROBLEM_FILTERS=Warning +automatically_removed_unused_problem_filters=false +changed_execution_env=Error +eclipse.preferences.version=1 +incompatible_api_component_version=Error +incompatible_api_component_version_include_major_without_breaking_change=Disabled +incompatible_api_component_version_include_minor_without_api_change=Disabled +incompatible_api_component_version_report_major_without_breaking_change=Warning +incompatible_api_component_version_report_minor_without_api_change=Warning +invalid_since_tag_version=Error +malformed_since_tag=Error +missing_since_tag=Error +report_api_breakage_when_major_version_incremented=Disabled +report_resolution_errors_api_component=Warning diff --git a/tmf/org.lttng.scope.tmf2.views.ui/.settings/org.eclipse.pde.prefs b/tmf/org.lttng.scope.tmf2.views.ui/.settings/org.eclipse.pde.prefs new file mode 100644 index 0000000000..01d624df11 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/.settings/org.eclipse.pde.prefs @@ -0,0 +1,32 @@ +compilers.f.unresolved-features=1 +compilers.f.unresolved-plugins=1 +compilers.incompatible-environment=1 +compilers.p.build=1 +compilers.p.build.bin.includes=0 +compilers.p.build.encodings=2 +compilers.p.build.java.compiler=2 +compilers.p.build.java.compliance=1 +compilers.p.build.missing.output=2 +compilers.p.build.output.library=1 +compilers.p.build.source.library=0 +compilers.p.build.src.includes=0 +compilers.p.deprecated=1 +compilers.p.discouraged-class=1 +compilers.p.internal=1 +compilers.p.missing-packages=1 +compilers.p.missing-version-export-package=2 +compilers.p.missing-version-import-package=2 +compilers.p.missing-version-require-bundle=2 +compilers.p.no-required-att=0 +compilers.p.not-externalized-att=1 +compilers.p.unknown-attribute=1 +compilers.p.unknown-class=1 +compilers.p.unknown-element=1 +compilers.p.unknown-identifier=1 +compilers.p.unknown-resource=1 +compilers.p.unresolved-ex-points=0 +compilers.p.unresolved-import=0 +compilers.s.create-docs=false +compilers.s.doc-folder=doc +compilers.s.open-tags=1 +eclipse.preferences.version=1 diff --git a/tmf/org.lttng.scope.tmf2.views.ui/META-INF/MANIFEST.MF b/tmf/org.lttng.scope.tmf2.views.ui/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..4503ded772 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/META-INF/MANIFEST.MF @@ -0,0 +1,29 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %Bundle-Name +Bundle-Vendor: %Bundle-Vendor +Bundle-Version: 0.2.0.qualifier +Bundle-Localization: plugin +Bundle-SymbolicName: org.lttng.scope.tmf2.views.ui;singleton:=true +Bundle-Activator: org.lttng.scope.tmf2.views.ui.activator.internal.Activator +Bundle-ActivationPolicy: lazy +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Require-Bundle: org.eclipse.core.runtime, + org.eclipse.ui, + org.lttng.scope.common.core, + org.lttng.scope.common.ui, + org.lttng.scope.tmf2.views.core, + org.eclipse.tracecompass.tmf.core, + org.eclipse.tracecompass.tmf.ui, + org.eclipse.core.resources +Export-Package: org.lttng.scope.tmf2.views.ui.activator.internal;x-internal:=true, + org.lttng.scope.tmf2.views.ui.jfx, + org.lttng.scope.tmf2.views.ui.jfx.examples, + org.lttng.scope.tmf2.views.ui.timeline, + org.lttng.scope.tmf2.views.ui.timeline.widgets.timegraph, + org.lttng.scope.tmf2.views.ui.timeline.widgets.timegraph.toolbar, + org.lttng.scope.tmf2.views.ui.timeline.widgets.timegraph.toolbar.nav +Import-Package: com.google.common.annotations, + com.google.common.base, + com.google.common.collect, + com.google.common.primitives diff --git a/tmf/org.lttng.scope.tmf2.views.ui/about.html b/tmf/org.lttng.scope.tmf2.views.ui/about.html new file mode 100644 index 0000000000..c258ef55d8 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/about.html @@ -0,0 +1,28 @@ + + + + +About + + +

About This Content

+ +

June 5, 2006

+

License

+ +

The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise +indicated below, the Content is provided to you under the terms and conditions of the +Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available +at http://www.eclipse.org/legal/epl-v10.html. +For purposes of the EPL, "Program" will mean the Content.

+ +

If you did not receive this Content directly from the Eclipse Foundation, the Content is +being redistributed by another party ("Redistributor") and different terms and conditions may +apply to your use of any object code in the Content. Check the Redistributor's license that was +provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise +indicated below, the terms and conditions of the EPL still apply to any source code in the Content +and such source code may be obtained at http://www.eclipse.org.

+ + + \ No newline at end of file diff --git a/tmf/org.lttng.scope.tmf2.views.ui/build.properties b/tmf/org.lttng.scope.tmf2.views.ui/build.properties new file mode 100644 index 0000000000..4e8d15efd7 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/build.properties @@ -0,0 +1,20 @@ +############################################################################### +# Copyright (C) 2017 EfficiOS Inc. +# +# 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 +############################################################################### + +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + icons/,\ + .,\ + about.html,\ + plugin.properties,\ + plugin.xml +src.includes = about.html +additional.bundles = org.eclipse.jdt.annotation +jars.extra.classpath = platform:/plugin/org.eclipse.jdt.annotation diff --git a/tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/config.gif b/tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/config.gif new file mode 100755 index 0000000000000000000000000000000000000000..cade7851226b52f5f551e0c53d04b5982bcfab85 GIT binary patch literal 538 zcmZ?wbhEHb6krfwc*el+@BhYs|2O~txB377Ex*66{P%UmzptzQeqHtL<*aWnXaD>2 z;r)${54U?h-s<^qv-iub314pXZCKX(=0w%oleO!Y^sQUmzjn#w$D2}L?aqC*EAROJ zO(za)ezH0J@y3kTyYgP`D(Eis=`IdDwtwsK{ad;V1G)->dkTZQ3xZGW+i-S9N^e2X z>HV8e?Avl`&*rj((9*<+l7#TJZKWI9%GS4*u4}I-PlzZ@j4DZp+|X9BvAuF_d)3C) zicM{mo7$>3wpNuVM3u!ymc&Pu$3>RMN0-G#{r~@;VMqbRpDc_F46Y11AXkIpgn_-h z!L_NmrM0cSquJ2jy3^IjMZ=oOM90*wU7u0ijM-k5!K__bft{U=g;hnV&DzMBQ&eA! z!@=0L)qq=oPoK-4ho4uk)xy$ISj0?F$jri|O-fN-QbJx%O}E`%R?A$*UR~Uv-O5SZ VMAKT@+@{asT;He9Upg8YtN}+3r}h8< literal 0 HcmV?d00001 diff --git a/tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/help.gif b/tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/help.gif new file mode 100644 index 0000000000000000000000000000000000000000..9d70301dae38843e0ad0ea28a42710f4c920ea9f GIT binary patch literal 259 zcmV+e0sQ_)Nk%w1VGsZi0K@U5T+@im_^v zw``QSd7ZwMvdp5p(@=n__51(&{r~9j_4NDy_x%6u^7Z!o|LpSh`ThU={{Qv-|M>m? z_x=C-{{Qy<|NsC0A^8LW0018VEC2ui01yBW000Gm;3tk`X+Do(pr)8Mgb)zTT0U^W z?HoWqBm<#9IH-g~!w8q*Bn*q1fs<(fKMz8r<6!JkoDSh?xL`1m9m0T!L@LTpc|+%{ z6&U&@o~2NBDm#AzS2%uu4h|L`78F(^LK+$zDjF6V1aU4f5IhhQKQ{(25)w2vEhs81 JEv+RX06QZIfSmvU literal 0 HcmV?d00001 diff --git a/tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/legend.gif b/tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/legend.gif new file mode 100644 index 0000000000000000000000000000000000000000..f40ce6b1796b2283b981d46894f0861edefe3401 GIT binary patch literal 200 zcmZ?wbhEHb6krfwI3mrk<-~^v*>UDG5-cnCt~j^-eRW=N?u_b*JFh?fGHdt!qK=Ij z^((6<>};5_r>K2nc;W2$ibdhQCo<|+#g{K^n7X%N%HEnCweRLl4lkG!U%oiJaL)h# z{~3^g;!hSv1_o&c9grBvP6k%j2WovOne)_z6fbY>*nTqMJ5`9|r%|AuJ=!5S=W uiw-^AVVI$|&ABxtg{j^{#L?jdmk!fSW~D*{jU~C|#a~nJe+cGaum%9=Hd5ID literal 0 HcmV?d00001 diff --git a/tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/nav_arrow_back.gif b/tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/nav_arrow_back.gif new file mode 100644 index 0000000000000000000000000000000000000000..04b5a0525b396b93d528ba68d7ccf9f85104147e GIT binary patch literal 204 zcmZ?wbhEHb6krfwXpv%AmMyR%4~PU;<_WAV653QQys<)fSEJ~zMzOsuV!!V;|GwAy z`+nQ+2c5qkcK&`m;rHW-zn@I_{bb^w_j~?)*z@=Mt-n8R{rmeq1q}XU0L7myj9d)z z3_1)z0J4*T)$@URUrOe@j8*H>CvAu?+M68|nOCP2;_tifFvn+22RZ&u6(L6{ml-eG oFBC*bhq6Buep|=J-KL#j9d)z3_1)z0P+(9Tj+uQ0uLRjetG^&FEaJo&#t)mP(!P~&rj4V zM`s_;xwM0#T1Jw*Y`uOQ>*ZOFI_;0qn8KxGY2%|(FWe-==FZH@%)%llz~b-3#Lw98 P#K16R#>`nxjttfSrq#L# literal 0 HcmV?d00001 diff --git a/tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/nav_bookmark_back.gif b/tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/nav_bookmark_back.gif new file mode 100644 index 0000000000000000000000000000000000000000..ed3e7c26eeda82c0dec1a9ca0776df484a740cb9 GIT binary patch literal 554 zcmZ?wbhEHb6krfwc*el+=lkM6Kezq;Qu^=v-2cB0{QLX<|7-jI@1y^}OZfk}`Tws= zjg{Vif808?#lNw__u%%nzu#}2+T?e7vww4i_n!}Yj_;d#`SkKBO)ec(o~;$$zaLNd z{ba)L#}j`)nb=h3b7*tTksW=1-tYN+ul4u+w%-pre?RQpxisU1_**ej7 zOTXQgiS}!{?bi0#ukLo5*W$jnMQme*@UBMDU5#QZ^8{9akl@-Pp-tt&%d!Rj|NqZ0 zh=Jly7DfgJZw4KZ8$ofxz~0{A-PGLD+Qe_I(bg?$q;F+uY17>#reMRs$zi8yuP@l9 zZotCK#Lng*)NLxx#mH-HGR50mPEweAbF(2|i=*Qd9f@W~)&t#Y+D(oEJp0eL$ZL7K zh+GpE&b4`+0544Lq+wy$~#q$ZdWB`cQ^Ono4s_sc5!GjdT0nR GSOWmYUAo)= literal 0 HcmV?d00001 diff --git a/tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/nav_bookmark_fwd.gif b/tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/nav_bookmark_fwd.gif new file mode 100644 index 0000000000000000000000000000000000000000..da6c4b66f68e22891fa54f9aef87b1e37efae22a GIT binary patch literal 556 zcmZ?wbhEHb6krfwc*el+=lkM6Kezq;Qu^=v-2cB0{QLX<|7-jI@1y^}OZfk}`Tws= zjg{Vif808?#lNw__u%%nzu#}2+T?e7vww4i_n!}Yj_;fL=fmF1r&hOx ziFIxpXNCQ~+k9s4lr0miR`fWno8+;e-E~5Z`@~w0OGg)9Kegi4*|qmBZn}Mb)Ah4k zwoI_uI?;AZzulIJ_G^3WS9d$jYjNM*B)YdnY-hd5o+cnEy1PkiMXtc=0>RaVf~yJy zSL6wCM5XhhdauFy_7}z@-0-Ks!TATQ7HQTyH zjr47-t?jy-#1-urI63UK9P|a-Gz?gnnb_GJg}O~8xEOhjO{N5z%S#D!Z*Df^Yjt++ z){)%DdZ1NZJJ8kXj608jQ>%iNn}~>*(zRJ;pxB&HM;>8vy-!e{Z4rOu8F)&O(kaa;fZ literal 0 HcmV?d00001 diff --git a/tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/nav_event_fwd.gif b/tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/nav_event_fwd.gif new file mode 100644 index 0000000000000000000000000000000000000000..c39cf62bbca0ba8464a3fc81aaf7602dab464694 GIT binary patch literal 328 zcmZ?wbhEHb6krfwxXQqg+r2ZUX63)X@BjX|_4oU&-!B*Z`LO5DhrPcaPx$?0!tciu ze?OV{=f#3QK=Bs~f4^Ap`^CaP@Av$^*ZTW@+wTXRzaMt~zT3RJNpx?E*v@*9t<@rX znt%+^-A!UEas^fw2(B&^TvZ^rB2RE#vCz5_q16RKo63ckWefcO|DS;xK=CIFBLjm5 zgAT|rke?XXQXQrgc<4y=pHSfvut+j+T^7tB>lHZL`}rbS0ljN##~tikPCV%eSk<^g zy5H&W!HSG&zQRfe{dL4RIJnd*G*m=IL^?!!M3l3AH53(873JlHh2#_6mBi#+!d=zX P11EY-Sh32}k--`OoA`AT literal 0 HcmV?d00001 diff --git a/tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/nav_statechange_back.gif b/tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/nav_statechange_back.gif new file mode 100644 index 0000000000000000000000000000000000000000..69c57a934ab30520c1cbfd60fb2168d405d8d976 GIT binary patch literal 218 zcmZ?wbhEHb6krfwXpv!HVECVwmbNTgU_~Af39if&SX(5tsa$wth48LM(Or#Vdt1ad zZQAtvZu9SZt-tTL{eIB-`(fwr#}j@(p7{I8gx^mlK7IQ1&-*=pKJ5AX{npG$2{-}hR7-*5Z5=-}?LG*1x~+|I-X8{$yd~Vz6h>0r~{!BLM~mw&Vlz3p{kB`j0deoy=h~ zyRf2!c}3Xrh}WXpSDBO^Y_NFr)J;)ftt1!c((RYrlixAaN?lc3eEDO+j~Z@9S1xhM rb}1=waS1M0PBGDmVpBvp+*#RK+1Nyc**siWgqRn)Ffq9}GFSruMQgs! literal 0 HcmV?d00001 diff --git a/tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/zoom_full.gif b/tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/zoom_full.gif new file mode 100644 index 0000000000000000000000000000000000000000..fd0c66950972e9fd6b4eee2a45293db7b0402a95 GIT binary patch literal 583 zcmZ?wbhEHb6krfwc*ek>=hf;IH{B?(Il6LneC_)9y7e)Ys}kzgCpT_NZrqsBx;3M1 zYfjfr^Oy#Un1=ILZ(q4_=gaqB7ao7P|N7gr_usES|9bEBw__J?ox6Jb!jmu8UwnP~ z{`vgb@~XsXFsG`()# z)P`jC{<4g|#s1N)K&pC%tK(wV?&6UV6I0Yt5EGW+>Ef1>5|vq# o@xi~D$(7S6WrD(k7KT7G<>+Wmo$< z^%Q3Hl;+RvX#Vl#^T)Sux(ajJOAG)1|Nr~Fz1UmpySorVO4JkL7CJ0C{u=27pF<1it6s-XG literal 0 HcmV?d00001 diff --git a/tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/zoom_out.gif b/tmf/org.lttng.scope.tmf2.views.ui/icons/toolbar/zoom_out.gif new file mode 100644 index 0000000000000000000000000000000000000000..1f874009adf2835898ea0dd034adcbe41777815b GIT binary patch literal 560 zcmZ?wbhEHb6krfwc*elcnv?(H+4KMZ{y%;E?8Cdy{rxjvzxnv{*T2tSe!P19{?X&- z+jk%9pSJAD^LI;DZQFnJ;-A0&fBpXZ^VgrxU%owi{<3H4vKOyEJbC`+(bHG!w;yWi znQ`m>(@i@MPMW>w>aBZ^pTD~M@X4)v4;k||FlMY|Oj*iMx|OkX8)N?Z14mEXe(;!~ za@X$t2VTB?_u|dl$IoBfdGN5ItNZfJn=jtI`}zCVw;$g>fBmw3-}bHBw@jHn;qtZ9 z8@J4yzhK6{e}67rx^VI0`MrBq?b$JP-SXna^C}k3Z8~*q<+3GHx2~vB!>pOp|Nr~*`O}BFGpEh#s;>;ND-Uq&EXryt z%C7cz>M6|XDb1hT(fs4f=Z|mSbQR{bmlpp2|Nr;z-$0Uq+CcFq3nK$V3WE;FU{IVe zu=h5kG&Q%hwzxaG`FgsvH9Pn*2b&7}d-wTxFfs|)1SQ8iwK*pV8Vd=r3z=AXwYny$ zs3 + + + + + + + + diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/activator/internal/Activator.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/activator/internal/Activator.java new file mode 100644 index 0000000000..ec33727fa7 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/activator/internal/Activator.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.ui.activator.internal; + +import org.lttng.scope.common.ui.ScopeUIActivator; + +import javafx.application.Platform; + +/** + * The activator class controls the plug-in life cycle + * + * @noreference This class should not be accessed outside of this plugin. + */ +public class Activator extends ScopeUIActivator { + + /** + * Return the singleton instance of this activator. + * + * @return The singleton instance + */ + public static Activator instance() { + return ScopeUIActivator.getInstance(Activator.class); + } + + @Override + protected void startActions() { + Platform.setImplicitExit(false); + } + + @Override + protected void stopActions() { + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/activator/internal/package-info.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/activator/internal/package-info.java new file mode 100644 index 0000000000..6df2667a34 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/activator/internal/package-info.java @@ -0,0 +1,11 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +@org.eclipse.jdt.annotation.NonNullByDefault +package org.lttng.scope.tmf2.views.ui.activator.internal; diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/Arrow.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/Arrow.java new file mode 100644 index 0000000000..8f312aa05a --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/Arrow.java @@ -0,0 +1,251 @@ +/* + * This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 + * Unported License. To view a copy of this license, visit + * https://creativecommons.org/licenses/by-sa/3.0/. + */ + +package org.lttng.scope.tmf2.views.ui.jfx; + +import org.eclipse.jdt.annotation.Nullable; + +import javafx.beans.InvalidationListener; +import javafx.beans.property.DoubleProperty; +import javafx.beans.property.ObjectProperty; +import javafx.scene.Group; +import javafx.scene.paint.Paint; +import javafx.scene.shape.Line; + +/** + * JavaFX node representing a line with an arrow head at the end point. + * + * Initially inspired from http://stackoverflow.com/a/41353991/4227853. + */ +public class Arrow extends Group { + + private static final double ARROW_HEAD_LENGTH = 5; + private static final double ARROW_HEAD_WIDTH = 3; + + private final Line line; + + /** + * Constructor specifying the initial coordinates of the arrow. The arrow + * head is drawn at the end point. + * + * @param startX + * X of start point + * @param startY + * Y of end point + * @param endX + * X of end point + * @param endY + * Y of end point. + */ + public Arrow(double startX, double startY, double endX, double endY) { + this(); + setStartX(startX); + setStartY(startY); + setEndX(endX); + setEndY(endY); + } + + /** + * Constructor with default coordinates (usually (0,0)). + */ + public Arrow() { + this(new Line(), new Line(), new Line()); + } + + private Arrow(Line line, Line arrow1, Line arrow2) { + super(line, arrow1, arrow2); + this.line = line; + + /* The color of the arrow should follow the color of the main line. */ + arrow1.strokeProperty().bind(line.strokeProperty()); + arrow2.strokeProperty().bind(line.strokeProperty()); + + /* Listener to redraw the arrow parts when the line position changes. */ + InvalidationListener updater = o -> { + double ex = getEndX(); + double ey = getEndY(); + double sx = getStartX(); + double sy = getStartY(); + + arrow1.setEndX(ex); + arrow1.setEndY(ey); + arrow2.setEndX(ex); + arrow2.setEndY(ey); + + if (ex == sx && ey == sy) { + /* The line is just a point. Don't draw the arrowhead. */ + arrow1.setStartX(ex); + arrow1.setStartY(ey); + arrow2.setStartX(ex); + arrow2.setStartY(ey); + } else { + double factor = ARROW_HEAD_LENGTH / Math.hypot(sx-ex, sy-ey); + double factorO = ARROW_HEAD_WIDTH / Math.hypot(sx-ex, sy-ey); + + // part in direction of main line + double dx = (sx - ex) * factor; + double dy = (sy - ey) * factor; + + // part ortogonal to main line + double ox = (sx - ex) * factorO; + double oy = (sy - ey) * factorO; + + arrow1.setStartX(ex + dx - oy); + arrow1.setStartY(ey + dy + ox); + arrow2.setStartX(ex + dx + oy); + arrow2.setStartY(ey + dy - ox); + } + }; + + /* Attach updater to properties */ + startXProperty().addListener(updater); + startYProperty().addListener(updater); + endXProperty().addListener(updater); + endYProperty().addListener(updater); + updater.invalidated(null); + } + + /** + * Set the value of the property startX. + * + * @param value + * The new value + */ + public final void setStartX(double value) { + line.setStartX(value); + } + + /** + * Get the value of the property startX. + * + * @return The current value + */ + public final double getStartX() { + return line.getStartX(); + } + + /** + * The startX property + * + * @return The startX property + */ + public final DoubleProperty startXProperty() { + return line.startXProperty(); + } + + /** + * Set the value of the property startY. + * + * @param value + * The new value + */ + public final void setStartY(double value) { + line.setStartY(value); + } + + /** + * Get the value of the property startY. + * + * @return The current value + */ + public final double getStartY() { + return line.getStartY(); + } + + /** + * The startY property + * + * @return The startY property + */ + public final DoubleProperty startYProperty() { + return line.startYProperty(); + } + + /** + * Set the value of the property endX. + * + * @param value + * The new value + */ + public final void setEndX(double value) { + line.setEndX(value); + } + + /** + * Get the value of the property endX. + * + * @return The current value + */ + public final double getEndX() { + return line.getEndX(); + } + + /** + * The endX property + * + * @return The endX property + */ + public final DoubleProperty endXProperty() { + return line.endXProperty(); + } + + /** + * Set the value of the property endY. + * + * @param value + * The new value + */ + public final void setEndY(double value) { + line.setEndY(value); + } + + /** + * Get the value of the property endY. + * + * @return The current value + */ + public final double getEndY() { + return line.getEndY(); + } + + /** + * The endY property + * + * @return The endY property + */ + public final DoubleProperty endYProperty() { + return line.endYProperty(); + } + + /** + * Set the value of the stroke property. + * + * @param value + * The new value + */ + public final void setStroke(@Nullable Paint value) { + line.setStroke(value); + } + + /** + * Get the value of the stroke property. + * + * @return The current value + */ + public final @Nullable Paint getStroke() { + return line.getStroke(); + } + + /** + * The stroke property, which determines the lines' color. + * + * @return The stroke property + */ + public final ObjectProperty<@Nullable Paint> strokeProperty() { + return line.strokeProperty(); + } + +} \ No newline at end of file diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/CountingGridPane.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/CountingGridPane.java new file mode 100644 index 0000000000..8ed93eabb8 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/CountingGridPane.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.ui.jfx; + +import javafx.scene.Node; +import javafx.scene.layout.GridPane; + +/** + * Extension of a {@link GridPane} which tracks the number of inserted rows. + * + * Make sure you only add rows to the pane using {@link #appendRow(Node...)} or + * else it will give weird results! + * + * @author Alexandre Montplaisir + */ +public class CountingGridPane extends GridPane { + + private int fNbRows = 0; + + /** + * Add a row of nodes to this grid pane. Not thread-safe! + * + * @param children + * The contents of the row + */ + public void appendRow(Node... children) { + addRow(fNbRows++, children); + } +} diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/JfxColorFactory.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/JfxColorFactory.java new file mode 100644 index 0000000000..422de49d4c --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/JfxColorFactory.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + *******************************************************************************/ + +package org.lttng.scope.tmf2.views.ui.jfx; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.lttng.scope.tmf2.views.core.timegraph.model.render.ColorDefinition; + +import javafx.scene.paint.Color; + +public final class JfxColorFactory { + + private JfxColorFactory() {} + + private static final Map COLOR_MAP = new ConcurrentHashMap<>(); + private static final Map DERIVED_COLOR_MAP = new ConcurrentHashMap<>(); + + /** + * Instantiate a {@link Color} from a {@link ColorDefinition} object. + * + * @param colorDef + * The ColorDefinition + * @return The Color object + */ + public static synchronized Color getColorFromDef(ColorDefinition colorDef) { + Color color = COLOR_MAP.get(colorDef); + if (color == null) { + color = Color.rgb(colorDef.fRed, colorDef.fGreen, colorDef.fBlue, (double) colorDef.fAlpha / (double) ColorDefinition.MAX); + COLOR_MAP.put(colorDef, color); + } + return color; + } + + public static synchronized Color getDerivedColorFromDef(ColorDefinition colorDef) { + Color color = DERIVED_COLOR_MAP.get(colorDef); + if (color == null) { + color = getColorFromDef(colorDef); + color = color.desaturate().darker(); + DERIVED_COLOR_MAP.put(colorDef, color); + } + return color; + } + + /** + * Convert a JavaFX {@link Color} to its equivalent {@link ColorDefinition}. + * + * @param color + * The color to convert + * @return A corresponding ColorDefinition + */ + public static ColorDefinition colorToColorDef(Color color) { + /* + * ColorDefintion works with integer values 0 to 255, but JavaFX colors + * works with doubles 0.0 to 0.1 + */ + int red = (int) Math.round(color.getRed() * 255); + int green = (int) Math.round(color.getGreen() * 255); + int blue = (int) Math.round(color.getBlue() * 255); + int opacity = (int) Math.round(color.getOpacity() * 255); + return new ColorDefinition(red, green, blue, opacity); + } +} diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/JfxImageFactory.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/JfxImageFactory.java new file mode 100644 index 0000000000..c42d66d6a8 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/JfxImageFactory.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.ui.jfx; + +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.jdt.annotation.Nullable; + +import javafx.scene.image.Image; + +/** + * Factory for JavaFX {@link Image}s. This will allow caching the Image objects, + * allowing any class to re-use already read images. + * + * @author Alexandre Montplaisir + * @noreference This cache is only valid for classes within the same jar/plugin. + * The resource paths would not work from different plugins. + */ +public final class JfxImageFactory { + + private static final JfxImageFactory INSTANCE = new JfxImageFactory(); + + private JfxImageFactory() {} + + /** + * Get the singleton instance of this factory. + * + * @return The instance + */ + public static JfxImageFactory instance() { + return INSTANCE; + } + + private final Map fImages = new HashMap<>(); + + /** + * Get the {@link Image} for a given path within the jar's resources. + * + * @param resourcePath + * The path to the image resource. It should be a standard + * .gif/.png/.jpg etc. file. + * @return The corresponding Image. + */ + public synchronized @Nullable Image getImageFromResource(String resourcePath) { + Image image = fImages.get(resourcePath); + if (image == null) { + try (InputStream is = getClass().getResourceAsStream(resourcePath)) { + if (is == null) { + /* The image was not found, the path is invalid */ + return null; + } + image = new Image(is); + } catch (IOException e) { + return null; + } + fImages.put(resourcePath, image); + } + return image; + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/JfxUtils.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/JfxUtils.java new file mode 100644 index 0000000000..f0556eaac2 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/JfxUtils.java @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.ui.jfx; + +import static java.util.Objects.requireNonNull; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.reflect.Method; +import java.util.List; + +import javafx.application.Platform; +import javafx.beans.property.ReadOnlyDoubleProperty; +import javafx.beans.property.SimpleDoubleProperty; +import javafx.geometry.Rectangle2D; +import javafx.scene.Node; +import javafx.scene.control.Dialog; +import javafx.scene.control.OverrunStyle; +import javafx.scene.text.Font; +import javafx.stage.Screen; +import javafx.stage.Window; + +/** + * JavaFX-related utilities + * + * @author Alexandre Montplaisir + */ +public final class JfxUtils { + + /** + * Double property with a non-modifiable value of 0. For things that should + * remain at 0. + */ + public static final ReadOnlyDoubleProperty ZERO_PROPERTY = new SimpleDoubleProperty(0); + + + private static final MethodHandles.Lookup LOOKUP = requireNonNull(MethodHandles.lookup()); + private static final MethodHandle COMPUTE_CLIPPED_TEXT_HANDLE; + static { + MethodHandle handle = null; + try { + Class c = Class.forName("com.sun.javafx.scene.control.skin.Utils"); //$NON-NLS-1$ + Method method = c.getDeclaredMethod("computeClippedText", //$NON-NLS-1$ + Font.class, String.class, double.class, OverrunStyle.class, String.class); + method.setAccessible(true); + handle = LOOKUP.unreflect(method); + } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | IllegalAccessException e) { + /* Should not fail if we did everything correctly. */ + } + COMPUTE_CLIPPED_TEXT_HANDLE = requireNonNull(handle); + } + + /** + * Accessor for the + * com.sun.javafx.scene.control.skin.Utils.computeClippedText() method. + * + * This method implements the logic to clip Label strings. It can be useful + * for other types, like Text. Unfortunately it is not public, but this + * accessor allows calling it through reflection. It makes use of + * {@link MethodHandle#invokeExact}, which should be close to just as fast + * as a standard compiled method call. + * + * @param font + * The font of the text that will be used + * @param text + * The string to clip + * @param width + * The maximum width we want to limit the string to + * @param type + * The {@link OverrunStyle} + * @param ellipsisString + * The string to use as ellipsis + * @return The clipped string, or "ERROR" if an error happened. + * Unfortunately we lose the exception typing due to the reflection + * call, so we do not want to throw "Throwable" here. + */ + public static String computeClippedText(Font font, String text, double width, + OverrunStyle type, String ellipsisString) { + try { + String str = (String) COMPUTE_CLIPPED_TEXT_HANDLE.invokeExact(font, text, width, type, ellipsisString); + return requireNonNull(str); + } catch (Throwable e) { + return "ERROR"; //$NON-NLS-1$ + } + } + + /** + * Run the given {@link Runnable} on the UI/main/application thread. + * + * If you know for sure you are *not* on the main thread, you should use + * {@link Platform#runLater} to queue the runnable for the main thread. + * + * If you are not sure, you can use this method. The difference with + * {@link Platform#runLater} is that if you are actually already on the UI + * thread, the runnable will be run immediately. Whereas calling runLater + * from the UI will just queue the runnable at the end of the queue. + * + * @param r + * The runnable to run on the main thread + */ + public static void runOnMainThread(Runnable r) { + if (Platform.isFxApplicationThread()) { + r.run(); + } else { + Platform.runLater(r); + } + } + + /** + * Utility method to center a Dialog/Alert on the middle of the current + * screen. Used to workaround a "bug" with the current version of JavaFX (or + * the SWT/JavaFX embedding?) where alerts always show on the primary + * screen, not necessarily the current one. + * + * @param dialog + * The dialog to reposition. It must be already shown, or else + * this will do nothing. + * @param referenceNode + * The dialog should be moved to the same screen as this node's + * window. + */ + public static void centerDialogOnScreen(Dialog dialog, Node referenceNode) { + Window window = referenceNode.getScene().getWindow(); + Rectangle2D windowRectangle = new Rectangle2D(window.getX(), window.getY(), window.getWidth(), window.getHeight()); + + List screens = Screen.getScreensForRectangle(windowRectangle); + Screen screen = screens.stream() + .findFirst() + .orElse(Screen.getPrimary()); + + Rectangle2D screenBounds = screen.getBounds(); + dialog.setX((screenBounds.getWidth() - dialog.getWidth()) / 2 + screenBounds.getMinX()); +// dialog.setY((screenBounds.getHeight() - dialog.getHeight()) / 2 + screenBounds.getMinY()); + } +} diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/Logo.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/Logo.java new file mode 100644 index 0000000000..242b67fffb --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/Logo.java @@ -0,0 +1,76 @@ +package org.lttng.scope.tmf2.views.ui.jfx; + +import org.eclipse.jdt.annotation.Nullable; + +import javafx.animation.Animation; +import javafx.animation.Interpolator; +import javafx.animation.RotateTransition; +import javafx.application.Application; +import javafx.scene.Group; +import javafx.scene.Scene; +import javafx.scene.layout.Pane; +import javafx.scene.paint.Color; +import javafx.scene.shape.Circle; +import javafx.scene.shape.Rectangle; +import javafx.stage.Stage; +import javafx.util.Duration; + +public class Logo extends Application { + + private static final String BACKGROUND_STYLE = "-fx-background-color: rgba(255, 255, 255, 255);"; //$NON-NLS-1$ + + private static final Color LTTNG_PURPLE = Color.web("#996ABC"); //$NON-NLS-1$ + private static final Color LTTNG_LIGHT_BLUE = Color.web("#C3DEF4"); //$NON-NLS-1$ + + @Override + public void start(@Nullable Stage stage) throws Exception { + if (stage == null) { + return; + } + + Rectangle clipRect1 = new Rectangle(-130, -130, 115, 115); + Rectangle clipRect2 = new Rectangle(15, -130, 115, 115); + Rectangle clipRect3 = new Rectangle(-130, 15, 115, 115); + Rectangle clipRect4 = new Rectangle(15, 15, 115, 115); + Group clip = new Group(clipRect1, clipRect2, clipRect3, clipRect4); + + Circle spinnanCircle = new Circle(100); + spinnanCircle.setFill(null); + spinnanCircle.setStrokeWidth(30); + spinnanCircle.setStroke(LTTNG_PURPLE); + spinnanCircle.setClip(clip); + + Circle magCircle = new Circle(60); + magCircle.setFill(null); + magCircle.setStrokeWidth(25); + magCircle.setStroke(LTTNG_LIGHT_BLUE); + + Rectangle magHandle = new Rectangle(-12.5, 60, 25, 110); + magHandle.setFill(LTTNG_LIGHT_BLUE); + + Group mag = new Group(magCircle, magHandle); + + Group root = new Group(spinnanCircle, mag); + root.setRotate(30); + root.relocate(0, 0); + + Pane pane = new Pane(root); + pane.setStyle(BACKGROUND_STYLE); + + RotateTransition spinnan = new RotateTransition(Duration.seconds(4), spinnanCircle); + spinnan.setByAngle(360); + spinnan.setCycleCount(Animation.INDEFINITE); + spinnan.setInterpolator(Interpolator.LINEAR); + + Scene scene = new Scene(pane); + stage.setScene(scene); + stage.show(); + + spinnan.play(); + } + + public static void main(String[] args) { + launch(args); + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/ArrowExample.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/ArrowExample.java new file mode 100644 index 0000000000..898af02cfc --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/ArrowExample.java @@ -0,0 +1,54 @@ +package org.lttng.scope.tmf2.views.ui.jfx.examples; + +import org.eclipse.jdt.annotation.Nullable; +import org.lttng.scope.tmf2.views.ui.jfx.Arrow; + +import javafx.application.Application; +import javafx.scene.Scene; +import javafx.scene.layout.Pane; +import javafx.scene.paint.Color; +import javafx.stage.Stage; + +public class ArrowExample extends Application { + + public static void main(String[] args) { + launch(args); + } + + @Override + public void start(@Nullable Stage primaryStage) throws Exception { + if (primaryStage == null) { + return; + } + + Pane root = new Pane(); + Arrow arrow = new Arrow(); + arrow.setStroke(Color.GREEN); + root.getChildren().add(arrow); + + root.setOnMouseClicked(evt -> { + switch (evt.getButton()) { + case PRIMARY: + // set pos of end with arrow head + arrow.setEndX(evt.getX()); + arrow.setEndY(evt.getY()); + break; + case SECONDARY: + // set pos of end without arrow head + arrow.setStartX(evt.getX()); + arrow.setStartY(evt.getY()); + break; + case MIDDLE: + case NONE: + default: + break; + } + }); + + Scene scene = new Scene(root, 400, 400); + + primaryStage.setScene(scene); + primaryStage.show(); + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/Example.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/Example.java new file mode 100644 index 0000000000..ea464811b7 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/Example.java @@ -0,0 +1,61 @@ +package org.lttng.scope.tmf2.views.ui.jfx.examples; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +import javafx.application.Application; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; +import javafx.scene.Node; +import javafx.scene.Scene; +import javafx.scene.control.ScrollPane; +import javafx.scene.paint.Color; +import javafx.scene.shape.Rectangle; +import javafx.stage.Stage; + +@NonNullByDefault({}) +public class Example extends Application { + @Override + public void start(Stage stage) { + Node content = new Rectangle(1000, 700, Color.GREEN); + ScrollPane scrollPane = new ScrollPane(content); + scrollPane.setPrefSize(500, 300); + + ChangeListener changeListener = new ChangeListener() { + @Override + public void changed(ObservableValue observable, Object oldValue, Object newValue) { + double hmin = scrollPane.getHmin(); + double hmax = scrollPane.getHmax(); + double hvalue = scrollPane.getHvalue(); + double contentWidth = content.getLayoutBounds().getWidth(); + double viewportWidth = scrollPane.getViewportBounds().getWidth(); + + double hoffset = + Math.max(0, contentWidth - viewportWidth) * (hvalue - hmin) / (hmax - hmin); + + double vmin = scrollPane.getVmin(); + double vmax = scrollPane.getVmax(); + double vvalue = scrollPane.getVvalue(); + double contentHeight = content.getLayoutBounds().getHeight(); + double viewportHeight = scrollPane.getViewportBounds().getHeight(); + + double voffset = + Math.max(0, contentHeight - viewportHeight) * (vvalue - vmin) / (vmax - vmin); + + System.out.printf("Offset: [%.1f, %.1f] width: %.1f height: %.1f %n", + hoffset, voffset, viewportWidth, viewportHeight); + } + }; + scrollPane.viewportBoundsProperty().addListener(changeListener); + scrollPane.hvalueProperty().addListener(changeListener); + scrollPane.vvalueProperty().addListener(changeListener); + + Scene scene = new Scene(scrollPane, 640, 480); + stage.setScene(scene); + + stage.show(); + } + + public static void main(String[] args) { + launch(args); + } +} \ No newline at end of file diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/Example2.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/Example2.java new file mode 100644 index 0000000000..c15f98ef7d --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/Example2.java @@ -0,0 +1,79 @@ +package org.lttng.scope.tmf2.views.ui.jfx.examples; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +import javafx.application.Application; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; +import javafx.scene.Scene; +import javafx.scene.canvas.Canvas; +import javafx.scene.control.ScrollPane; +import javafx.scene.layout.Pane; +import javafx.stage.Stage; + +@NonNullByDefault({}) +public class Example2 extends Application { + + private static final double TEN_BILLIONS = 10000000000.0; + + @Override + public void start(Stage stage) { +// Node content = new Rectangle(1000, 700, Color.GREEN); + Pane pane = new Pane(); + pane.setPrefSize(TEN_BILLIONS, TEN_BILLIONS); + ScrollPane scrollPane = new ScrollPane(pane); + scrollPane.setPrefSize(500, 300); + + ChangeListener changeListener = new ChangeListener() { + @Override + public void changed(ObservableValue observable, Object oldValue, Object newValue) { + System.out.println("source=" + observable.toString()); + + double hmin = scrollPane.getHmin(); + double hmax = scrollPane.getHmax(); + double hvalue = scrollPane.getHvalue(); + double contentWidth = pane.getLayoutBounds().getWidth(); + double viewportWidth = scrollPane.getViewportBounds().getWidth(); + + double hoffset = + Math.max(0, contentWidth - viewportWidth) * (hvalue - hmin) / (hmax - hmin); + + double vmin = scrollPane.getVmin(); + double vmax = scrollPane.getVmax(); + double vvalue = scrollPane.getVvalue(); + double contentHeight = pane.getLayoutBounds().getHeight(); + double viewportHeight = scrollPane.getViewportBounds().getHeight(); + + double voffset = + Math.max(0, contentHeight - viewportHeight) * (vvalue - vmin) / (vmax - vmin); + + System.out.printf("Offset: [%.1f, %.1f] width: %.1f height: %.1f %n", + hoffset, voffset, viewportWidth, viewportHeight); + } + }; + scrollPane.viewportBoundsProperty().addListener(changeListener); + scrollPane.hvalueProperty().addListener(changeListener); + scrollPane.vvalueProperty().addListener(changeListener); + + /* Drawing on the region */ + Canvas canvas1 = new Canvas(100, 100); + canvas1.relocate(TEN_BILLIONS - 100, 0); + canvas1.getGraphicsContext2D().strokeOval(60, 60, 30, 30); + + Canvas canvas2 = new Canvas(100, 100); + canvas2.relocate(TEN_BILLIONS - 100, TEN_BILLIONS - 100); + canvas2.getGraphicsContext2D().fillOval(60, 60, 30, 30); + + pane.getChildren().addAll(canvas1, canvas2); + + /* Showing the scene */ + Scene scene = new Scene(scrollPane, 640, 480); + stage.setScene(scene); + + stage.show(); + } + + public static void main(String[] args) { + launch(args); + } +} \ No newline at end of file diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/ExampleCanvas.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/ExampleCanvas.java new file mode 100644 index 0000000000..496090c38e --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/ExampleCanvas.java @@ -0,0 +1,55 @@ +package org.lttng.scope.tmf2.views.ui.jfx.examples; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +import javafx.application.Application; +import javafx.scene.Group; +import javafx.scene.Scene; +import javafx.scene.canvas.Canvas; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.paint.Color; +import javafx.scene.shape.ArcType; +import javafx.stage.Stage; + +@NonNullByDefault({}) +public class ExampleCanvas extends Application { + + public static void main(String[] args) { + launch(args); + } + + @Override + public void start(Stage primaryStage) { + primaryStage.setTitle("Drawing Operations Test"); + Group root = new Group(); + Canvas canvas = new Canvas(300, 250); + GraphicsContext gc = canvas.getGraphicsContext2D(); + drawShapes(gc); + root.getChildren().add(canvas); + primaryStage.setScene(new Scene(root)); + primaryStage.show(); + } + + private static void drawShapes(GraphicsContext gc) { + gc.setFill(Color.GREEN); + gc.setStroke(Color.BLUE); + gc.setLineWidth(5); + gc.strokeLine(40, 10, 10, 40); + gc.fillOval(10, 60, 30, 30); + gc.strokeOval(60, 60, 30, 30); + gc.fillRoundRect(110, 60, 30, 30, 10, 10); + gc.strokeRoundRect(160, 60, 30, 30, 10, 10); + gc.fillArc(10, 110, 30, 30, 45, 240, ArcType.OPEN); + gc.fillArc(60, 110, 30, 30, 45, 240, ArcType.CHORD); + gc.fillArc(110, 110, 30, 30, 45, 240, ArcType.ROUND); + gc.strokeArc(10, 160, 30, 30, 45, 240, ArcType.OPEN); + gc.strokeArc(60, 160, 30, 30, 45, 240, ArcType.CHORD); + gc.strokeArc(110, 160, 30, 30, 45, 240, ArcType.ROUND); + gc.fillPolygon(new double[]{10, 40, 10, 40}, + new double[]{210, 210, 240, 240}, 4); + gc.strokePolygon(new double[]{60, 90, 60, 90}, + new double[]{210, 210, 240, 240}, 4); + gc.strokePolyline(new double[]{110, 140, 110, 140}, + new double[]{210, 210, 240, 240}, 4); + } +} \ No newline at end of file diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/ExampleMouseDrag.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/ExampleMouseDrag.java new file mode 100644 index 0000000000..ced9162d57 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/ExampleMouseDrag.java @@ -0,0 +1,85 @@ +package org.lttng.scope.tmf2.views.ui.jfx.examples; + +import org.eclipse.jdt.annotation.Nullable; + +import javafx.application.Application; +import javafx.event.EventHandler; +import javafx.scene.Cursor; +import javafx.scene.Group; +import javafx.scene.Scene; +import javafx.scene.input.MouseEvent; +import javafx.scene.paint.Color; +import javafx.scene.shape.Circle; +import javafx.stage.Stage; + +/** + * @web http://java-buddy.blogspot.com/ + */ +public class ExampleMouseDrag extends Application { + + private double orgSceneX, orgSceneY; + private double orgTranslateX, orgTranslateY; + + @Override + public void start(@Nullable Stage primaryStage) { + if (primaryStage == null) { + return; + } + + //Create Circles + Circle circleRed = new Circle(50.0, Color.RED); + circleRed.setCursor(Cursor.HAND); + circleRed.setOnMousePressed(circleOnMousePressedEventHandler); + circleRed.setOnMouseDragged(circleOnMouseDraggedEventHandler); + + Circle circleGreen = new Circle(50.0, Color.GREEN); + circleGreen.setCursor(Cursor.MOVE); + circleGreen.setCenterX(150); + circleGreen.setCenterY(150); + circleGreen.setOnMousePressed(circleOnMousePressedEventHandler); + circleGreen.setOnMouseDragged(circleOnMouseDraggedEventHandler); + + Circle circleBlue = new Circle(50.0, Color.BLUE); + circleBlue.setCursor(Cursor.CROSSHAIR); + circleBlue.setTranslateX(300); + circleBlue.setTranslateY(100); + circleBlue.setOnMousePressed(circleOnMousePressedEventHandler); + circleBlue.setOnMouseDragged(circleOnMouseDraggedEventHandler); + + Group root = new Group(); + root.getChildren().addAll(circleRed, circleGreen, circleBlue); + + primaryStage.setResizable(false); + primaryStage.setScene(new Scene(root, 400,350)); + + primaryStage.setTitle("java-buddy"); + primaryStage.show(); + } + + public static void main(String[] args) { + launch(args); + } + + private EventHandler circleOnMousePressedEventHandler = new EventHandler() { + @Override + public void handle(MouseEvent t) { + orgSceneX = t.getSceneX(); + orgSceneY = t.getSceneY(); + orgTranslateX = ((Circle)(t.getSource())).getTranslateX(); + orgTranslateY = ((Circle)(t.getSource())).getTranslateY(); + } + }; + + private EventHandler circleOnMouseDraggedEventHandler = new EventHandler() { + @Override + public void handle(MouseEvent t) { + double offsetX = t.getSceneX() - orgSceneX; + double offsetY = t.getSceneY() - orgSceneY; + double newTranslateX = orgTranslateX + offsetX; + double newTranslateY = orgTranslateY + offsetY; + + ((Circle)(t.getSource())).setTranslateX(newTranslateX); + ((Circle)(t.getSource())).setTranslateY(newTranslateY); + } + }; +} \ No newline at end of file diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/ExampleMouseDrag2.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/ExampleMouseDrag2.java new file mode 100644 index 0000000000..6421fa654e --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/ExampleMouseDrag2.java @@ -0,0 +1,382 @@ +package org.lttng.scope.tmf2.views.ui.jfx.examples; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Random; +import java.util.Set; + +import org.eclipse.jdt.annotation.Nullable; + +import javafx.application.Application; +import javafx.event.EventHandler; +import javafx.scene.Node; +import javafx.scene.Scene; +import javafx.scene.control.Label; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.input.MouseEvent; +import javafx.scene.layout.Pane; +import javafx.scene.layout.Region; +import javafx.scene.paint.Color; +import javafx.scene.shape.Rectangle; +import javafx.scene.shape.StrokeLineCap; +import javafx.stage.Stage; + +public class ExampleMouseDrag2 extends Application { + +// public static Image image = new Image("http://upload.wikimedia.org/wikipedia/commons/thumb/4/41/Siberischer_tiger_de_edit02.jpg/320px-Siberischer_tiger_de_edit02.jpg"); + public Image image = new Image("file:///home/alexandre/Desktop/tiger.jpg"); +// public Image image = new Image( getClass().getResource( "/home/alexandre/Desktop/tiger.jpg").toExternalForm()); + + SelectionModel selectionModel = new SelectionModel(); + + DragMouseGestures dragMouseGestures = new DragMouseGestures(); + + static Random rnd = new Random(); + + @Override + public void start(@Nullable Stage primaryStage) { + if (primaryStage == null) { + return; + } + + Pane pane = new Pane(); + pane.setStyle("-fx-background-color:white"); + + new RubberBandSelection( pane); + + double width = 200; + double height = 160; + + double padding = 20; + for( int row=0; row < 4; row++) { + for( int col=0; col < 4; col++) { + + Selectable selectable = new Selectable( width, height); + selectable.relocate( padding * (col+1) + width * col, padding * (row + 1) + height * row); + + pane.getChildren().add(selectable); + + dragMouseGestures.makeDraggable(selectable); + + } + } + + Label infoLabel = new Label( "Drag on scene for Rubberband Selection. Shift+Click to add to selection, CTRL+Click to toggle selection. Drag selected nodes for multi-dragging."); + pane.getChildren().add( infoLabel); + + Scene scene = new Scene( pane, 1600, 900); + scene.getStylesheets().add( getClass().getResource("application.css").toExternalForm()); + + primaryStage.setScene( scene); + primaryStage.show(); + + + + } + + private class Selectable extends Region { + + ImageView view; + + public Selectable( double width, double height) { + + view = new ImageView( image); + view.setFitWidth(width); + view.setFitHeight(height); + + getChildren().add( view); + + this.setPrefSize(width, height); + } + + } + + private class SelectionModel { + + Set selection = new HashSet<>(); + + public void add( Node node) { + + if( !node.getStyleClass().contains("highlight")) { + node.getStyleClass().add( "highlight"); + } + + selection.add( node); + } + + public void remove( Node node) { + node.getStyleClass().remove( "highlight"); + selection.remove( node); + } + + public void clear() { + + while( !selection.isEmpty()) { + remove( selection.iterator().next()); + } + + } + + public boolean contains( Node node) { + return selection.contains(node); + } + +// public int size() { +// return selection.size(); +// } + + public void log() { + System.out.println( "Items in model: " + Arrays.asList( selection.toArray())); + } + + } + + private class DragMouseGestures { + + final DragContext dragContext = new DragContext(); + + private boolean enabled = false; + + public void makeDraggable(final Node node) { + + node.setOnMousePressed(onMousePressedEventHandler); + node.setOnMouseDragged(onMouseDraggedEventHandler); + node.setOnMouseReleased(onMouseReleasedEventHandler); + + } + + EventHandler onMousePressedEventHandler = new EventHandler() { + + @Override + public void handle(MouseEvent event) { + + // don't do anything if the user is in the process of adding to the selection model + if( event.isControlDown() || event.isShiftDown()) { + return; + } + + Node node = (Node) event.getSource(); + + dragContext.x = node.getTranslateX() - event.getSceneX(); + dragContext.y = node.getTranslateY() - event.getSceneY(); + + // clear the model if the current node isn't in the selection => new selection + if( !selectionModel.contains(node)) { + selectionModel.clear(); + selectionModel.add( node); + } + + // flag that the mouse released handler should consume the event, so it won't bubble up to the pane which has a rubberband selection mouse released handler + enabled = true; + + // prevent rubberband selection handler + event.consume(); + } + }; + + EventHandler onMouseDraggedEventHandler = new EventHandler() { + + @Override + public void handle(MouseEvent event) { + + if( !enabled) { + return; + } + + // all in selection + for( Node node: selectionModel.selection) { + node.setTranslateX( dragContext.x + event.getSceneX()); + node.setTranslateY( dragContext.y + event.getSceneY()); + } + + } + }; + + EventHandler onMouseReleasedEventHandler = new EventHandler() { + + @Override + public void handle(MouseEvent event) { + + // prevent rubberband selection handler + if( enabled) { + + // set node's layout position to current position,remove translate coordinates + for( Node node: selectionModel.selection) { + fixPosition(node); + } + + enabled = false; + + event.consume(); + } + } + }; + + /** + * Set node's layout position to current position, remove translate coordinates. + * @param node + */ + private void fixPosition( Node node) { + + double x = node.getTranslateX(); + double y = node.getTranslateY(); + + node.relocate(node.getLayoutX() + x, node.getLayoutY() + y); + + node.setTranslateX(0); + node.setTranslateY(0); + + } + + class DragContext { + + double x; + double y; + + } + + } + + private class RubberBandSelection { + + final DragContext dragContext = new DragContext(); + final Rectangle rect; + + Pane group; + boolean enabled = false; + + public RubberBandSelection( Pane group) { + + this.group = group; + + rect = new Rectangle( 0,0,0,0); + rect.setStroke(Color.BLUE); + rect.setStrokeWidth(1); + rect.setStrokeLineCap(StrokeLineCap.ROUND); + rect.setFill(Color.LIGHTBLUE.deriveColor(0, 1.2, 1, 0.6)); + + group.addEventHandler(MouseEvent.MOUSE_PRESSED, onMousePressedEventHandler); + group.addEventHandler(MouseEvent.MOUSE_DRAGGED, onMouseDraggedEventHandler); + group.addEventHandler(MouseEvent.MOUSE_RELEASED, onMouseReleasedEventHandler); + + } + + EventHandler onMousePressedEventHandler = new EventHandler() { + + @Override + public void handle(MouseEvent event) { + + // simple flag to prevent multiple handling of this event or we'd get an exception because rect is already on the scene + // eg if you drag with left mouse button and while doing that click the right mouse button + if( enabled) { + return; + } + + dragContext.mouseAnchorX = event.getSceneX(); + dragContext.mouseAnchorY = event.getSceneY(); + + rect.setX(dragContext.mouseAnchorX); + rect.setY(dragContext.mouseAnchorY); + rect.setWidth(0); + rect.setHeight(0); + + group.getChildren().add( rect); + + event.consume(); + + enabled = true; + } + }; + + EventHandler onMouseReleasedEventHandler = new EventHandler() { + + @Override + public void handle(MouseEvent event) { + + if( !event.isShiftDown() && !event.isControlDown()) { + selectionModel.clear(); + } + + for( Node node: group.getChildren()) { + + if( node instanceof Selectable) { + if( node.getBoundsInParent().intersects( rect.getBoundsInParent())) { + + if( event.isShiftDown()) { + + selectionModel.add( node); + + } else if( event.isControlDown()) { + + if( selectionModel.contains( node)) { + selectionModel.remove( node); + } else { + selectionModel.add( node); + } + } else { + selectionModel.add( node); + } + + } + } + + } + + selectionModel.log(); + + rect.setX(0); + rect.setY(0); + rect.setWidth(0); + rect.setHeight(0); + + group.getChildren().remove( rect); + + event.consume(); + + enabled = false; + } + }; + + EventHandler onMouseDraggedEventHandler = new EventHandler() { + + @Override + public void handle(MouseEvent event) { + + double offsetX = event.getSceneX() - dragContext.mouseAnchorX; + double offsetY = event.getSceneY() - dragContext.mouseAnchorY; + + if( offsetX > 0) { + rect.setWidth( offsetX); + } else { + rect.setX(event.getSceneX()); + rect.setWidth(dragContext.mouseAnchorX - rect.getX()); + } + + if( offsetY > 0) { + rect.setHeight( offsetY); + } else { + rect.setY(event.getSceneY()); + rect.setHeight(dragContext.mouseAnchorY - rect.getY()); + } + + event.consume(); + + } + }; + + private final class DragContext { + + public double mouseAnchorX; + public double mouseAnchorY; + + + } + } + + + public static void main(String[] args) { + launch(args); + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/FadeTransitionEx.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/FadeTransitionEx.java new file mode 100644 index 0000000000..8bb8d30767 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/FadeTransitionEx.java @@ -0,0 +1,39 @@ +package org.lttng.scope.tmf2.views.ui.jfx.examples; + +import org.eclipse.jdt.annotation.Nullable; + +import javafx.animation.FadeTransition; +import javafx.application.Application; +import javafx.scene.Group; +import javafx.scene.Scene; +import javafx.scene.shape.Rectangle; +import javafx.stage.Stage; +import javafx.util.Duration; + +public class FadeTransitionEx extends Application { + + public static void main(String[] args) { + Application.launch(args); + } + + @Override + public void start(@Nullable Stage primaryStage) { + if (primaryStage == null) { + return; + } + + Group group = new Group(); + Rectangle rect = new Rectangle(20,20,200,200); + + FadeTransition ft = new FadeTransition(Duration.millis(5000), rect); + ft.setFromValue(1.0); + ft.setToValue(0.0); + ft.play(); + + group.getChildren().add(rect); + + Scene scene = new Scene(group, 300, 200); + primaryStage.setScene(scene); + primaryStage.show(); + } +} diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/ParallelTransitionExample.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/ParallelTransitionExample.java new file mode 100644 index 0000000000..548786186d --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/ParallelTransitionExample.java @@ -0,0 +1,74 @@ +package org.lttng.scope.tmf2.views.ui.jfx.examples; + +import org.eclipse.jdt.annotation.Nullable; + +import javafx.animation.Animation; +import javafx.animation.FadeTransition; +import javafx.animation.ParallelTransition; +import javafx.animation.RotateTransition; +import javafx.animation.ScaleTransition; +import javafx.animation.TranslateTransition; +import javafx.application.Application; +import javafx.scene.Group; +import javafx.scene.Scene; +import javafx.scene.shape.Rectangle; +import javafx.stage.Stage; +import javafx.util.Duration; + +public class ParallelTransitionExample extends Application { + + public static void main(String[] args) { + Application.launch(args); + } + + @Override + public void start(@Nullable Stage primaryStage) { + if (primaryStage == null) { + return; + } + + Group group = new Group(); + Rectangle rectParallel = new Rectangle(20, 20, 200, 200); + + FadeTransition fadeTransition = new FadeTransition(Duration.millis(3000), + rectParallel); + fadeTransition.setFromValue(1.0f); + fadeTransition.setToValue(0.3f); + fadeTransition.setCycleCount(2); + fadeTransition.setAutoReverse(true); + + TranslateTransition translateTransition = new TranslateTransition( + Duration.millis(2000), rectParallel); + translateTransition.setFromX(50); + translateTransition.setToX(350); + translateTransition.setCycleCount(2); + translateTransition.setAutoReverse(true); + + RotateTransition rotateTransition = new RotateTransition( + Duration.millis(3000), rectParallel); + rotateTransition.setByAngle(180f); + rotateTransition.setCycleCount(4); + rotateTransition.setAutoReverse(true); + + ScaleTransition scaleTransition = new ScaleTransition( + Duration.millis(2000), rectParallel); + scaleTransition.setToX(2f); + scaleTransition.setToY(2f); + scaleTransition.setCycleCount(2); + scaleTransition.setAutoReverse(true); + + ParallelTransition parallelTransition = new ParallelTransition(); + parallelTransition.getChildren().addAll(fadeTransition, + translateTransition, + rotateTransition, + scaleTransition); + parallelTransition.setCycleCount(Animation.INDEFINITE); + parallelTransition.play(); + + group.getChildren().add(rectParallel); + + Scene scene = new Scene(group, 300, 200); + primaryStage.setScene(scene); + primaryStage.show(); + } +} diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/SwtToobar2.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/SwtToobar2.java new file mode 100644 index 0000000000..13772998aa --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/SwtToobar2.java @@ -0,0 +1,78 @@ +package org.lttng.scope.tmf2.views.ui.jfx.examples; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.MenuItem; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.ToolBar; +import org.eclipse.swt.widgets.ToolItem; + +@NonNullByDefault({}) +public class SwtToobar2 { + + private Shell shell; + + public SwtToobar2() { + Display display = new Display(); + shell = new Shell(display, SWT.SHELL_TRIM); + shell.setLayout(new FillLayout(SWT.VERTICAL)); + shell.setSize(50, 100); + + ToolBar toolbar = new ToolBar(shell, SWT.FLAT); + ToolItem itemDrop = new ToolItem(toolbar, SWT.DROP_DOWN); + itemDrop.setText("drop menu"); + + itemDrop.addSelectionListener(new SelectionAdapter() { + + Menu dropMenu = null; + + @Override + public void widgetSelected(SelectionEvent e) { + if (dropMenu == null) { + dropMenu = new Menu(shell, SWT.POP_UP); + shell.setMenu(dropMenu); + MenuItem itemCheck = new MenuItem(dropMenu, SWT.CHECK); + itemCheck.setText("checkbox"); + MenuItem itemRadio = new MenuItem(dropMenu, SWT.RADIO); + itemRadio.setText("radio1"); + MenuItem itemRadio2 = new MenuItem(dropMenu, SWT.RADIO); + itemRadio2.setText("radio2"); + } + + if (e.detail == SWT.ARROW) { + // Position the menu below and vertically aligned with the + // the drop down tool button. + final ToolItem toolItem = (ToolItem) e.widget; + final ToolBar toolBar = toolItem.getParent(); + + Point point = toolBar.toDisplay(new Point(e.x, e.y)); + dropMenu.setLocation(point.x, point.y); + dropMenu.setVisible(true); + } + + } + + }); + + shell.open(); + + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + + display.dispose(); + } + + public static void main(String[] args) { + new SwtToobar2(); + } + +} \ No newline at end of file diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/TestSwtToolbar.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/TestSwtToolbar.java new file mode 100644 index 0000000000..c4f77be980 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/TestSwtToolbar.java @@ -0,0 +1,62 @@ +package org.lttng.scope.tmf2.views.ui.jfx.examples; + +/******************************************************************************* + * Copyright (c) 2000, 2016 IBM Corporation and others. + * 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +/* + * ToolBar example snippet: place a drop down menu in a tool bar + * + * For a list of all SWT example snippets see + * http://www.eclipse.org/swt/snippets/ + */ +import org.eclipse.swt.*; +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.widgets.*; + +public class TestSwtToolbar { + + public static void main(String[] args) { + final Display display = new Display(); + final Shell shell = new Shell(display); + + final ToolBar toolBar = new ToolBar(shell, SWT.NONE); + Rectangle clientArea = shell.getClientArea(); + toolBar.setLocation(clientArea.x, clientArea.y); + + final Menu menu = new Menu(shell, SWT.POP_UP); + for (int i = 0; i < 8; i++) { + MenuItem item = new MenuItem(menu, SWT.PUSH); + item.setText("Item " + i); + } + + final ToolItem item = new ToolItem(toolBar, SWT.DROP_DOWN); + item.addListener(SWT.Selection, event -> { + if (event.detail == SWT.ARROW) { + Rectangle rect = item.getBounds(); + Point pt = new Point(rect.x, rect.y + rect.height); + pt = toolBar.toDisplay(pt); + menu.setLocation(pt.x, pt.y); + menu.setVisible(true); + } + }); + + toolBar.pack(); + shell.pack(); + shell.open(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + menu.dispose(); + display.dispose(); + } +} \ No newline at end of file diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/ZoomExample.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/ZoomExample.java new file mode 100644 index 0000000000..0409003c64 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/ZoomExample.java @@ -0,0 +1,194 @@ +package org.lttng.scope.tmf2.views.ui.jfx.examples; + +import java.net.MalformedURLException; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +import javafx.application.Application; +import javafx.geometry.Bounds; +import javafx.geometry.Point2D; +import javafx.geometry.Pos; +import javafx.scene.Group; +import javafx.scene.Node; +import javafx.scene.Scene; +import javafx.scene.canvas.Canvas; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.control.Label; +import javafx.scene.control.ScrollPane; +import javafx.scene.control.SplitPane; +import javafx.scene.layout.Pane; +import javafx.scene.layout.Region; +import javafx.scene.layout.StackPane; +import javafx.scene.paint.Color; +import javafx.scene.shape.Circle; +import javafx.stage.Stage; + +@NonNullByDefault({}) +public class ZoomExample extends Application { + + public static Region createContent() { + double width = 1000; + double height = 1000; + + Canvas canvas = new Canvas(width, height); + GraphicsContext gc = canvas.getGraphicsContext2D(); + + gc.setFill(Color.LIGHTGREY); + gc.fillRect(0, 0, width, height); + + gc.setStroke(Color.BLUE); + gc.beginPath(); + + for (int i = 50; i < width; i += 50) { + gc.moveTo(i, 0); + gc.lineTo(i, height); + } + + for (int i = 50; i < height; i += 50) { + gc.moveTo(0, i); + gc.lineTo(width, i); + } + gc.stroke(); + + Pane content = new Pane( + new Circle(50, 50, 20), + new Circle(120, 90, 20, Color.RED), + new Circle(200, 70, 20, Color.GREEN) + ); + + StackPane result = new StackPane(canvas, content); + result.setAlignment(Pos.TOP_LEFT); + + class DragData { + + double startX; + double startY; + double startLayoutX; + double startLayoutY; + Node dragTarget; + } + + DragData dragData = new DragData(); + + content.setOnMousePressed(evt -> { + if (evt.getTarget() != content) { + // initiate drag gesture, if a child of content receives the + // event to prevent ScrollPane from panning. + evt.consume(); + evt.setDragDetect(true); + } + }); + + content.setOnDragDetected(evt -> { + Node n = (Node) evt.getTarget(); + if (n != content) { + // set start paremeters + while (n.getParent() != content) { + n = n.getParent(); + } + dragData.startX = evt.getX(); + dragData.startY = evt.getY(); + dragData.startLayoutX = n.getLayoutX(); + dragData.startLayoutY = n.getLayoutY(); + dragData.dragTarget = n; + n.startFullDrag(); + evt.consume(); + } + }); + + // stop dragging when mouse is released + content.setOnMouseReleased(evt -> dragData.dragTarget = null); + + content.setOnMouseDragged(evt -> { + if (dragData.dragTarget != null) { + // move dragged node + dragData.dragTarget.setLayoutX(evt.getX() + dragData.startLayoutX - dragData.startX); + dragData.dragTarget.setLayoutY(evt.getY() + dragData.startLayoutY - dragData.startY); +// Point2D p = new Point2D(evt.getX(), evt.getY()); + evt.consume(); + } + }); + + return result; + } + + @Override + public void start(Stage primaryStage) throws MalformedURLException { + Region zoomTarget = createContent(); + zoomTarget.setPrefSize(1000, 1000); + zoomTarget.setOnDragDetected(evt -> { + Node target = (Node) evt.getTarget(); + while (target != zoomTarget && target != null) { + target = target.getParent(); + } + if (target != null) { + target.startFullDrag(); + } + }); + + Group group = new Group(zoomTarget); + + // stackpane for centering the content, in case the ScrollPane viewport + // is larget than zoomTarget + StackPane content = new StackPane(group); + group.layoutBoundsProperty().addListener((observable, oldBounds, newBounds) -> { + // keep it at least as large as the content + content.setMinWidth(newBounds.getWidth()); + content.setMinHeight(newBounds.getHeight()); + }); + + ScrollPane scrollPane = new ScrollPane(content); + scrollPane.setPannable(true); + scrollPane.viewportBoundsProperty().addListener((observable, oldBounds, newBounds) -> { + // use vieport size, if not too small for zoomTarget + content.setPrefSize(newBounds.getWidth(), newBounds.getHeight()); + }); + + content.setOnScroll(evt -> { + if (evt.isControlDown()) { + evt.consume(); + + final double zoomFactor = evt.getDeltaY() > 0 ? 1.2 : 1 / 1.2; + + Bounds groupBounds = group.getLayoutBounds(); + final Bounds viewportBounds = scrollPane.getViewportBounds(); + + // calculate pixel offsets from [0, 1] range + double valX = scrollPane.getHvalue() * (groupBounds.getWidth() - viewportBounds.getWidth()); + double valY = scrollPane.getVvalue() * (groupBounds.getHeight() - viewportBounds.getHeight()); + + // convert content coordinates to zoomTarget coordinates + Point2D posInZoomTarget = zoomTarget.parentToLocal(group.parentToLocal(new Point2D(evt.getX(), evt.getY()))); + + // calculate adjustment of scroll position (pixels) + Point2D adjustment = zoomTarget.getLocalToParentTransform().deltaTransform(posInZoomTarget.multiply(zoomFactor - 1)); + + // do the resizing + zoomTarget.setScaleX(zoomFactor * zoomTarget.getScaleX()); + zoomTarget.setScaleY(zoomFactor * zoomTarget.getScaleY()); + + // refresh ScrollPane scroll positions & content bounds + scrollPane.layout(); + + // convert back to [0, 1] range + // (too large/small values are automatically corrected by ScrollPane) + groupBounds = group.getLayoutBounds(); + scrollPane.setHvalue((valX + adjustment.getX()) / (groupBounds.getWidth() - viewportBounds.getWidth())); + scrollPane.setVvalue((valY + adjustment.getY()) / (groupBounds.getHeight() - viewportBounds.getHeight())); + } + }); + + StackPane left = new StackPane(new Label("Left Menu")); + SplitPane root = new SplitPane(left, scrollPane); + + Scene scene = new Scene(root, 800, 600); + + primaryStage.setScene(scene); + primaryStage.show(); + } + + public static void main(String[] args) { + launch(args); + } + +} \ No newline at end of file diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/application.css b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/application.css new file mode 100644 index 0000000000..517666bace --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/application.css @@ -0,0 +1,3 @@ +.highlight { + -fx-effect: dropshadow(three-pass-box, red, 4, 4, 0, 0); +} \ No newline at end of file diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/package-info.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/package-info.java new file mode 100644 index 0000000000..13083e2885 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/examples/package-info.java @@ -0,0 +1,11 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc. and others + * + * 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 + *******************************************************************************/ + +@org.eclipse.jdt.annotation.NonNullByDefault +package org.lttng.scope.tmf2.views.ui.jfx.examples; diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/package-info.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/package-info.java new file mode 100644 index 0000000000..975f25db6c --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/package-info.java @@ -0,0 +1,11 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +@org.eclipse.jdt.annotation.NonNullByDefault +package org.lttng.scope.tmf2.views.ui.jfx; diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/DummyTrace.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/DummyTrace.java new file mode 100644 index 0000000000..f4197a9adf --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/DummyTrace.java @@ -0,0 +1,71 @@ +package org.lttng.scope.tmf2.views.ui.jfx.testapp; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.tmf.core.event.ITmfEvent; +import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp; +import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp; +import org.eclipse.tracecompass.tmf.core.trace.ITmfContext; +import org.eclipse.tracecompass.tmf.core.trace.TmfTrace; +import org.eclipse.tracecompass.tmf.core.trace.location.ITmfLocation; +import org.lttng.scope.tmf2.views.core.TimeRange; + +public class DummyTrace extends TmfTrace { + +// private static final long START_TIME = 100000; +// private static final long END_TIME = 200000; + + private static final long START_TIME = 1332170682440133097L; + private static final long END_TIME = 1332170692664579801L; + + public DummyTrace() { + setTimeRange(TimeRange.of(START_TIME, END_TIME).toTmfTimeRange()); + } + + @Override + public ITmfTimestamp getInitialRangeOffset() { + return TmfTimestamp.fromNanos((long) ((END_TIME - START_TIME) * 0.1)); + } + + // ------------------------------------------------------------------------ + // Stuff we don't use + // ------------------------------------------------------------------------ + + @Override + public @Nullable IStatus validate(@Nullable IProject project, @Nullable String path) { + return null; + } + + @Override + public @Nullable IResource getResource() { + return null; + } + + @Override + public @Nullable ITmfLocation getCurrentLocation() { + return null; + } + + @Override + public double getLocationRatio(@Nullable ITmfLocation location) { + return 0; + } + + @Override + public @Nullable ITmfContext seekEvent(@Nullable ITmfLocation location) { + return null; + } + + @Override + public @Nullable ITmfContext seekEvent(double ratio) { + return null; + } + + @Override + public @Nullable ITmfEvent parseEvent(@Nullable ITmfContext context) { + return null; + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/LttngScopeApplication.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/LttngScopeApplication.java new file mode 100644 index 0000000000..1dee67bd45 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/LttngScopeApplication.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.ui.jfx.testapp; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.lttng.scope.tmf2.views.core.NestingBoolean; +import org.lttng.scope.tmf2.views.core.context.ViewGroupContext; +import org.lttng.scope.tmf2.views.core.timegraph.control.TimeGraphModelControl; +import org.lttng.scope.tmf2.views.core.timegraph.model.provider.ITimeGraphModelProvider; +import org.lttng.scope.tmf2.views.ui.timeline.widgets.timegraph.TimeGraphWidget; + +import javafx.application.Application; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.stage.Stage; + +public class LttngScopeApplication extends Application { + + public static void main(String[] args) { + launch(args); + } + + @Override + public void start(@Nullable Stage primaryStage) throws Exception { + if (primaryStage == null) { + return; + } + + /* Set up the view context */ + ViewGroupContext viewCtx = ViewGroupContext.getCurrent(); + ITmfTrace trace = new DummyTrace(); + + ITimeGraphModelProvider modelProvider = new TestModelProvider(); + TimeGraphModelControl control = new TimeGraphModelControl(viewCtx, modelProvider); + TimeGraphWidget widget = new TimeGraphWidget(control, new NestingBoolean()); + control.attachView(widget); + Parent root = widget.getRootNode(); + + primaryStage.setScene(new Scene(root)); + primaryStage.show(); + + viewCtx.setCurrentTrace(trace); + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/TestModelArrowProvider1.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/TestModelArrowProvider1.java new file mode 100644 index 0000000000..a02bbf52ff --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/TestModelArrowProvider1.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.ui.jfx.testapp; + +import java.util.List; +import java.util.concurrent.FutureTask; + +import org.eclipse.jdt.annotation.Nullable; +import org.lttng.scope.tmf2.views.core.TimeRange; +import org.lttng.scope.tmf2.views.core.timegraph.model.provider.arrows.TimeGraphModelArrowProvider; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.ColorDefinition; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.TimeGraphEvent; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.arrows.TimeGraphArrow; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.arrows.TimeGraphArrowRender; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.arrows.TimeGraphArrowSeries; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.arrows.TimeGraphArrowSeries.LineStyle; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeElement; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeRender; + +import com.google.common.collect.ImmutableList; + +class TestModelArrowProvider1 extends TimeGraphModelArrowProvider { + + public static final String SERIES_NAME = "Red"; + + private static final TimeGraphArrowSeries ARROW_SERIES = new TimeGraphArrowSeries( + SERIES_NAME, + new ColorDefinition(255, 0, 0), + LineStyle.FULL); + + public TestModelArrowProvider1() { + super(ARROW_SERIES); + } + + @Override + public TimeGraphArrowRender getArrowRender(TimeGraphTreeRender treeRender, TimeRange timeRange, @Nullable FutureTask task) { + TimeGraphArrowSeries series = getArrowSeries(); + List treeElems = treeRender.getAllTreeElements(); + + /* Draw 3 arrows total */ + TimeGraphEvent startEvent = new TimeGraphEvent(ts(timeRange, 0.1), treeElems.get(0)); + TimeGraphEvent endEvent = new TimeGraphEvent(ts(timeRange, 0.3), treeElems.get(5)); + TimeGraphArrow arrow1 = new TimeGraphArrow(startEvent, endEvent, series); + + startEvent = new TimeGraphEvent(ts(timeRange, 0.2), treeElems.get(3)); + endEvent = new TimeGraphEvent(ts(timeRange, 0.5), treeElems.get(12)); + TimeGraphArrow arrow2 = new TimeGraphArrow(startEvent, endEvent, series); + + startEvent = new TimeGraphEvent(ts(timeRange, 0.6), treeElems.get(15)); + endEvent = new TimeGraphEvent(ts(timeRange, 0.8), treeElems.get(2)); + TimeGraphArrow arrow3 = new TimeGraphArrow(startEvent, endEvent, series); + + List arrows = ImmutableList.of(arrow1, arrow2, arrow3); + return new TimeGraphArrowRender(timeRange, arrows); + } + + private static long ts(TimeRange range, double ratio) { + return (long) (range.getDuration() * ratio + range.getStart()); + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/TestModelArrowProvider2.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/TestModelArrowProvider2.java new file mode 100644 index 0000000000..d383c00457 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/TestModelArrowProvider2.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.ui.jfx.testapp; + +import java.util.List; +import java.util.concurrent.FutureTask; + +import org.eclipse.jdt.annotation.Nullable; +import org.lttng.scope.tmf2.views.core.TimeRange; +import org.lttng.scope.tmf2.views.core.timegraph.model.provider.arrows.TimeGraphModelArrowProvider; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.ColorDefinition; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.TimeGraphEvent; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.arrows.TimeGraphArrow; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.arrows.TimeGraphArrowRender; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.arrows.TimeGraphArrowSeries; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.arrows.TimeGraphArrowSeries.LineStyle; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeElement; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeRender; + +import com.google.common.collect.ImmutableList; + +class TestModelArrowProvider2 extends TimeGraphModelArrowProvider { + + public static final String SERIES_NAME = "Green"; + + private static final TimeGraphArrowSeries ARROW_SERIES = new TimeGraphArrowSeries( + SERIES_NAME, + new ColorDefinition(0, 255, 0), + LineStyle.FULL); + + public TestModelArrowProvider2() { + super(ARROW_SERIES); + } + + @Override + public TimeGraphArrowRender getArrowRender(TimeGraphTreeRender treeRender, TimeRange timeRange, @Nullable FutureTask task) { + TimeGraphArrowSeries series = getArrowSeries(); + List treeElems = treeRender.getAllTreeElements(); + + /* Draw 2 arrows total */ + TimeGraphEvent startEvent = new TimeGraphEvent(ts(timeRange, 0.3), treeElems.get(6)); + TimeGraphEvent endEvent = new TimeGraphEvent(ts(timeRange, 0.8), treeElems.get(4)); + TimeGraphArrow arrow1 = new TimeGraphArrow(startEvent, endEvent, series); + + startEvent = new TimeGraphEvent(ts(timeRange, 0.5), treeElems.get(10)); + endEvent = new TimeGraphEvent(ts(timeRange, 0.6), treeElems.get(7)); + TimeGraphArrow arrow2 = new TimeGraphArrow(startEvent, endEvent, series); + + List arrows = ImmutableList.of(arrow1, arrow2); + return new TimeGraphArrowRender(timeRange, arrows); + } + + private static long ts(TimeRange range, double ratio) { + return (long) (range.getDuration() * ratio + range.getStart()); + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/TestModelProvider.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/TestModelProvider.java new file mode 100644 index 0000000000..bef8c6dd19 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/TestModelProvider.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2016-2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.ui.jfx.testapp; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.lttng.scope.tmf2.views.core.timegraph.model.provider.TimeGraphModelProvider; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeElement; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeRender; + +import com.google.common.collect.ImmutableList; + +class TestModelProvider extends TimeGraphModelProvider { + + public static final String ENTRY_NAME_PREFIX = "Entry #"; + + private static final int NB_ENTRIES = 20; + + private static final TimeGraphTreeRender TREE_RENDER; + + static { + List treeElements = IntStream.range(1, NB_ENTRIES) + .mapToObj(i -> new TimeGraphTreeElement(ENTRY_NAME_PREFIX + i, Collections.emptyList())) + .collect(Collectors.toList()); + TimeGraphTreeElement rootElement = new TimeGraphTreeElement("Test", treeElements); + TREE_RENDER = new TimeGraphTreeRender(rootElement); + } + + protected TestModelProvider() { + super("Test", + /* Sorting modes */ + null, + /* Filter modes */ + null, + /* State provider */ + new TestModelStateProvider(), + /* Arrow providers */ + ImmutableList.of(new TestModelArrowProvider1(), new TestModelArrowProvider2())); + } + + @Override + public TimeGraphTreeRender getTreeRender() { + return TREE_RENDER; + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/TestModelStateProvider.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/TestModelStateProvider.java new file mode 100644 index 0000000000..11c5e7ca8b --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/TestModelStateProvider.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2016-2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.ui.jfx.testapp; + +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.FutureTask; +import java.util.stream.Collectors; +import java.util.stream.LongStream; + +import org.eclipse.jdt.annotation.Nullable; +import org.lttng.scope.tmf2.views.core.TimeRange; +import org.lttng.scope.tmf2.views.core.config.ConfigOption; +import org.lttng.scope.tmf2.views.core.timegraph.model.provider.states.TimeGraphModelStateProvider; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.ColorDefinition; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.LineThickness; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.states.BasicTimeGraphStateInterval; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.states.TimeGraphStateInterval; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.states.TimeGraphStateRender; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeElement; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterators; + +class TestModelStateProvider extends TimeGraphModelStateProvider { + + /** + * The duration of each state is equal to its tree element index, multiplied + * by this factor. + */ + public static final long DURATION_FACTOR = 100000000L; + + public TestModelStateProvider() { + super(ImmutableList.of()); + } + + @Override + public TimeGraphStateRender getStateRender(TimeGraphTreeElement treeElement, + TimeRange timeRange, long resolution, @Nullable FutureTask task) { + + int entryIndex = Integer.valueOf(treeElement.getName().substring(TestModelProvider.ENTRY_NAME_PREFIX.length())); + long stateLength = entryIndex * DURATION_FACTOR; + + List intervals = LongStream.iterate(timeRange.getStart(), i -> i + stateLength) + .limit((timeRange.getDuration() / stateLength) + 1) + .mapToObj(startTime -> { + long endTime = startTime + stateLength - 1; + String name = getNextStateName(); + ConfigOption color = getnextStateColor(); + return new BasicTimeGraphStateInterval(startTime, endTime, treeElement, name, name, color, LINE_THICKNESS, Collections.emptyMap()); + }) + .collect(Collectors.toList()); + + return new TimeGraphStateRender(timeRange, treeElement, intervals); + } + + private static final ConfigOption LINE_THICKNESS = new ConfigOption<>(LineThickness.NORMAL); + private static final Iterator STATE_NAMES = Iterators.cycle("State 1", "State 2"); + private static final Iterator> STATE_COLORS = Iterators.cycle( + new ConfigOption<>(new ColorDefinition(128, 0, 0)), + new ConfigOption<>(new ColorDefinition(0, 0, 128))); + + private static synchronized String getNextStateName() { + return STATE_NAMES.next(); + } + + private static synchronized ConfigOption getnextStateColor() { + return STATE_COLORS.next(); + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/UiModelApp.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/UiModelApp.java new file mode 100644 index 0000000000..ee708f7ebe --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/UiModelApp.java @@ -0,0 +1,157 @@ +package org.lttng.scope.tmf2.views.ui.jfx.testapp; + +import static java.util.Objects.requireNonNull; + +import java.util.stream.DoubleStream; +import java.util.stream.Stream; + +import org.eclipse.jdt.annotation.Nullable; +import org.lttng.scope.tmf2.views.ui.jfx.JfxUtils; + +import javafx.application.Application; +import javafx.scene.Group; +import javafx.scene.Scene; +import javafx.scene.control.ScrollPane; +import javafx.scene.control.ScrollPane.ScrollBarPolicy; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.Pane; +import javafx.scene.paint.Color; +import javafx.scene.shape.Line; +import javafx.scene.shape.Rectangle; +import javafx.scene.shape.StrokeLineCap; +import javafx.stage.Stage; + +public class UiModelApp extends Application { + + /* Value where a raw Pane starts breaking down */ + private static final double PANE_WIDTH = 1000000000.0; + /* Maximum pane width (roughly a 1-year trace at 0.01 nanos/pixel) */ +// private static final double PANE_WIDTH = 1e16; + + private static final double MAX_WIDTH = 1000000.0; + + private static final double ENTRY_HEIGHT = 20; + private static final Color BACKGROUD_LINES_COLOR = requireNonNull(Color.LIGHTBLUE); + private static final String BACKGROUND_STYLE = "-fx-background-color: rgba(255, 255, 255, 255);"; //$NON-NLS-1$ + + private static final double SELECTION_STROKE_WIDTH = 1; + private static final Color SELECTION_STROKE_COLOR = requireNonNull(Color.BLUE); + private static final Color SELECTION_FILL_COLOR = requireNonNull(Color.LIGHTBLUE.deriveColor(0, 1.2, 1, 0.4)); + + public static void main(String[] args) { + launch(args); + } + + @Override + public void start(@Nullable Stage primaryStage) throws Exception { + if (primaryStage == null) { + return; + } + + /* Layers */ + Group backgroundLayer = new Group(); + Group statesLayer = new Group(); + Group selectionLayer = new Group(); + + /* Top-level */ + Pane contentPane = new Pane(backgroundLayer, statesLayer, selectionLayer); + contentPane.minWidthProperty().bind(contentPane.prefWidthProperty()); + contentPane.maxWidthProperty().bind(contentPane.prefWidthProperty()); + contentPane.setStyle(BACKGROUND_STYLE); + + ScrollPane scrollPane = new ScrollPane(contentPane); + scrollPane.setVbarPolicy(ScrollBarPolicy.ALWAYS); + scrollPane.setHbarPolicy(ScrollBarPolicy.ALWAYS); + scrollPane.setFitToHeight(true); + scrollPane.setFitToWidth(true); + scrollPane.setPannable(true); + + BorderPane borderPane = new BorderPane(scrollPane); + + primaryStage.setScene(new Scene(borderPane)); + primaryStage.show(); + primaryStage.setHeight(500); + primaryStage.setWidth(500); + + contentPane.setPrefHeight(200); + contentPane.setPrefWidth(PANE_WIDTH); + + drawBackground(backgroundLayer, contentPane); + drawRectangles(statesLayer); + drawSelection(selectionLayer, contentPane); + } + + private static void drawBackground(Group parent, Pane content) { + DoubleStream.iterate(ENTRY_HEIGHT / 2, i -> i + ENTRY_HEIGHT).limit(10) + .mapToObj(y -> { + Line line = new Line(); + line.setStartX(0); + line.endXProperty().bind(content.widthProperty()); +// line.setEndX(MAX_WIDTH); + line.setStartY(y); + line.setEndY(y); + + line.setStroke(BACKGROUD_LINES_COLOR); + line.setStrokeWidth(1.0); + return line; + }) + .forEach(parent.getChildren()::add); + } + + private static void drawRectangles(Group target) { + DrawnRectangle rectangle1 = new DrawnRectangle(1, PANE_WIDTH - 20, 2); + rectangle1.setFill(Color.GREEN); + + DrawnRectangle rectangle2 = new DrawnRectangle(20, 2000, 5); + rectangle2.setFill(Color.RED); + + DrawnRectangle rectangle3 = new DrawnRectangle(PANE_WIDTH - 2000, PANE_WIDTH - 100, 6); + rectangle3.setFill(Color.ORANGE); + + target.getChildren().addAll(rectangle1, rectangle2, rectangle3); + } + + + private static class DrawnRectangle extends Rectangle { + + private static final double THICKNESS = 10; + + public DrawnRectangle(double startX, double endX, int entryIndex) { + double y0 = entryIndex * ENTRY_HEIGHT; + double yOffset = (ENTRY_HEIGHT - THICKNESS) / 2; + +// double width = endX - startX; + double width = Math.min(endX - startX, MAX_WIDTH); + + setX(startX); + setY(y0 + yOffset); + setWidth(width); + setHeight(THICKNESS); + } + } + + private static void drawSelection(Group parent, Pane content) { + Rectangle selection1 = new Rectangle(); + Rectangle selection2 = new Rectangle(); + + Stream.of(selection1, selection2).forEach(rect -> { + rect.setMouseTransparent(true); + + rect.setStroke(SELECTION_STROKE_COLOR); + rect.setStrokeWidth(SELECTION_STROKE_WIDTH); + rect.setStrokeLineCap(StrokeLineCap.ROUND); + rect.setFill(SELECTION_FILL_COLOR); + + rect.yProperty().bind(JfxUtils.ZERO_PROPERTY); + rect.heightProperty().bind(content.heightProperty()); + }); + + selection1.setX(200); + selection1.setWidth(100); + + selection2.setX(PANE_WIDTH - 1000); + selection2.setWidth(500); + + parent.getChildren().addAll(selection1, selection2); + } +} diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/UiModelApp2.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/UiModelApp2.java new file mode 100644 index 0000000000..bdc5472890 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/UiModelApp2.java @@ -0,0 +1,175 @@ +package org.lttng.scope.tmf2.views.ui.jfx.testapp; + +import static java.util.Objects.requireNonNull; + +import java.util.stream.DoubleStream; +import java.util.stream.Stream; + +import org.eclipse.jdt.annotation.Nullable; +import org.lttng.scope.tmf2.views.ui.jfx.JfxUtils; + +import javafx.application.Application; +import javafx.scene.Group; +import javafx.scene.Scene; +import javafx.scene.control.ScrollPane; +import javafx.scene.control.ScrollPane.ScrollBarPolicy; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.Pane; +import javafx.scene.paint.Color; +import javafx.scene.shape.Line; +import javafx.scene.shape.Rectangle; +import javafx.scene.shape.StrokeLineCap; +import javafx.stage.Stage; + +public class UiModelApp2 extends Application { + + /* Value where a raw Pane starts breaking down */ +// private static final double PANE_WIDTH = 1000000000.0; + /* Maximum supportable width due to double precision */ + private static final double PANE_WIDTH = 1e16; + + private static final double MAX_WIDTH = 1000000.0; + + private static final double ENTRY_HEIGHT = 20; + private static final Color BACKGROUD_LINES_COLOR = requireNonNull(Color.LIGHTBLUE); + private static final String BACKGROUND_STYLE = "-fx-background-color: rgba(255, 255, 255, 255);"; //$NON-NLS-1$ + + private static final double SELECTION_STROKE_WIDTH = 1; + private static final Color SELECTION_STROKE_COLOR = requireNonNull(Color.BLUE); + private static final Color SELECTION_FILL_COLOR = requireNonNull(Color.LIGHTBLUE.deriveColor(0, 1.2, 1, 0.4)); + + public static void main(String[] args) { + launch(args); + } + + @Override + public void start(@Nullable Stage primaryStage) throws Exception { + if (primaryStage == null) { + return; + } + + /* Layers */ + Group backgroundLayer = new Group(); + Group statesLayer = new Group(); + Group selectionLayer = new Group(); + + Pane paintingPane = new Pane(backgroundLayer, statesLayer, selectionLayer); + paintingPane.setStyle(BACKGROUND_STYLE); + + /* Top-level */ + Pane contentPane = new Pane(paintingPane); + contentPane.minWidthProperty().bind(contentPane.prefWidthProperty()); + contentPane.maxWidthProperty().bind(contentPane.prefWidthProperty()); + + ScrollPane scrollPane = new ScrollPane(contentPane); + scrollPane.setVbarPolicy(ScrollBarPolicy.ALWAYS); + scrollPane.setHbarPolicy(ScrollBarPolicy.ALWAYS); + scrollPane.setFitToHeight(true); + scrollPane.setFitToWidth(true); + scrollPane.setPannable(true); + + BorderPane borderPane = new BorderPane(scrollPane); + + primaryStage.setScene(new Scene(borderPane)); + primaryStage.show(); + primaryStage.setHeight(500); + primaryStage.setWidth(500); + + contentPane.setPrefHeight(200); + contentPane.setPrefWidth(PANE_WIDTH); + + /* Bind painting pane's height to the content pane */ + paintingPane.minHeightProperty().bind(contentPane.minHeightProperty()); + paintingPane.prefHeightProperty().bind(contentPane.prefHeightProperty()); + paintingPane.maxHeightProperty().bind(contentPane.maxHeightProperty()); + + /* We set painting's pane width programmatically */ + paintingPane.minWidthProperty().bind(paintingPane.prefWidthProperty()); + paintingPane.maxWidthProperty().bind(paintingPane.prefWidthProperty()); + + paintingPane.setPrefWidth(2000); + double x = PANE_WIDTH - 2000; + System.out.println(x); + paintingPane.relocate(x, 0); + + drawBackground(backgroundLayer, paintingPane); + drawRectangles(statesLayer); + drawSelection(selectionLayer, paintingPane); + } + + private static void drawBackground(Group parent, Pane parentPane) { + DoubleStream.iterate(ENTRY_HEIGHT / 2, i -> i + ENTRY_HEIGHT).limit(10) + .mapToObj(y -> { + Line line = new Line(); + line.setStartX(0); + line.endXProperty().bind(parentPane.widthProperty()); +// line.setEndX(MAX_WIDTH); + line.setStartY(y); + line.setEndY(y); + + line.setStroke(BACKGROUD_LINES_COLOR); + line.setStrokeWidth(1.0); + return line; + }) + .forEach(parent.getChildren()::add); + } + + private static void drawRectangles(Group target) { +// DrawnRectangle rectangle1 = new DrawnRectangle(1, PANE_WIDTH - 20, 2); +// rectangle1.setFill(Color.GREEN); +// +// DrawnRectangle rectangle2 = new DrawnRectangle(20, 2000, 5); +// rectangle2.setFill(Color.RED); +// +// DrawnRectangle rectangle3 = new DrawnRectangle(PANE_WIDTH - 2000, PANE_WIDTH - 100, 6); + DrawnRectangle rectangle3 = new DrawnRectangle(100, 1900, 6); + rectangle3.setFill(Color.ORANGE); + +// target.getChildren().addAll(rectangle1, rectangle2, rectangle3); + target.getChildren().addAll(rectangle3); + } + + + private static class DrawnRectangle extends Rectangle { + + private static final double THICKNESS = 10; + + public DrawnRectangle(double startX, double endX, int entryIndex) { + double y0 = entryIndex * ENTRY_HEIGHT; + double yOffset = (ENTRY_HEIGHT - THICKNESS) / 2; + +// double width = endX - startX; + double width = Math.min(endX - startX, MAX_WIDTH); + + setX(startX); + setY(y0 + yOffset); + setWidth(width); + setHeight(THICKNESS); + } + } + + private static void drawSelection(Group parent, Pane content) { +// Rectangle selection1 = new Rectangle(); + Rectangle selection2 = new Rectangle(); + + Stream.of(selection2).forEach(rect -> { + rect.setMouseTransparent(true); + + rect.setStroke(SELECTION_STROKE_COLOR); + rect.setStrokeWidth(SELECTION_STROKE_WIDTH); + rect.setStrokeLineCap(StrokeLineCap.ROUND); + rect.setFill(SELECTION_FILL_COLOR); + + rect.yProperty().bind(JfxUtils.ZERO_PROPERTY); + rect.heightProperty().bind(content.heightProperty()); + }); +// +// selection1.setX(200); +// selection1.setWidth(100); + + selection2.setX(500); + selection2.setWidth(500); + + parent.getChildren().addAll(selection2); + } +} diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/package-info.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/package-info.java new file mode 100644 index 0000000000..62ed206744 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/jfx/testapp/package-info.java @@ -0,0 +1,11 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +@org.eclipse.jdt.annotation.NonNullByDefault +package org.lttng.scope.tmf2.views.ui.jfx.testapp; diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/DebugOptions.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/DebugOptions.java new file mode 100644 index 0000000000..a4fa48ac30 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/DebugOptions.java @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.ui.timeline; + +import static java.util.Objects.requireNonNull; + +import org.lttng.scope.tmf2.views.core.config.ConfigOption; +import org.lttng.scope.tmf2.views.ui.timeline.widgets.timegraph.TimeGraphWidget; + +import javafx.scene.paint.Color; +import javafx.scene.paint.CycleMethod; +import javafx.scene.paint.LinearGradient; +import javafx.scene.paint.Paint; +import javafx.scene.paint.Stop; +import javafx.scene.text.Font; +import javafx.scene.text.Text; + +/** + * Debug options for the {@link TimeGraphWidget}. Advanced users or unit + * tests might want to modify these. + * + * @author Alexandre Montplaisir + */ +public class DebugOptions { + + /** + * Constructor using the default options + */ + public DebugOptions() { + recomputeEllipsisWidth(); + } + + // ------------------------------------------------------------------------ + // General options + // ------------------------------------------------------------------------ + + /** + * Painting flag. Indicates if automatic redrawing of the view is enabled + */ + public final ConfigOption isPaintingEnabled = new ConfigOption<>(true); + + /** + * Entry padding. Number of tree elements to print above *and* below the + * visible range + */ + public final ConfigOption entryPadding = new ConfigOption<>(5); + + /** + * How much "padding" around the current visible window, on the left and + * right, should be pre-rendered. Expressed as a fraction of the current + * window (for example, 1.0 would render one "page" on each side). + */ + public final ConfigOption renderRangePadding = new ConfigOption<>(0.1); + + /** + * Time between UI updates, in milliseconds + */ + public final ConfigOption uiUpdateDelay = new ConfigOption<>(250); + + /** + * Whether the view should respond to vertical or horizontal scrolling + * actions. + */ + public final ConfigOption isScrollingListenersEnabled = new ConfigOption<>(true); + + // ------------------------------------------------------------------------ + // Loading overlay + // ------------------------------------------------------------------------ + + public final ConfigOption isLoadingOverlayEnabled = new ConfigOption<>(true); + + public final ConfigOption loadingOverlayColor = new ConfigOption<>(requireNonNull(Color.GRAY)); + + public final ConfigOption loadingOverlayFullOpacity = new ConfigOption<>(0.3); + public final ConfigOption loadingOverlayTransparentOpacity = new ConfigOption<>(0.0); + + public final ConfigOption loadingOverlayFadeInDuration = new ConfigOption<>(1000.0); + public final ConfigOption loadingOverlayFadeOutDuration = new ConfigOption<>(100.0); + + // ------------------------------------------------------------------------ + // Zoom animation + // ------------------------------------------------------------------------ + + /** + * The zoom animation duration, which is the amount of milliseconds it takes + * to complete the zoom animation (smaller number means a faster animation). + */ + public final ConfigOption zoomAnimationDuration = new ConfigOption<>(50); + + /** + * Each zoom action (typically, one mouse-scroll == one zoom action) will + * increase or decrease the current visible time range by this factor. + */ + public final ConfigOption zoomStep = new ConfigOption<>(0.08); + + /** + * Each zoom action will be centered on the center of the selection if it's + * currently visible. + */ + public final ConfigOption zoomPivotOnSelection = new ConfigOption<>(true); + + /** + * Each zoom action will be centered on the current mouse position if the + * zoom action originates from a mouse event. If zoomPivotOnSelection is + * enabled, it has priority. + */ + public final ConfigOption zoomPivotOnMousePosition = new ConfigOption<>(true); + + // ------------------------------------------------------------------------ + // State rectangles + // ------------------------------------------------------------------------ + + public final ConfigOption stateIntervalOpacity = new ConfigOption<>(1.0); + + public final ConfigOption multiStatePaint; + { + Stop[] stops = new Stop[] { new Stop(0, Color.BLACK), new Stop(1, Color.WHITE) }; + LinearGradient lg = new LinearGradient(0, 0, 0, 1, true, CycleMethod.NO_CYCLE, stops); + multiStatePaint = new ConfigOption<>(lg); + } + + // ------------------------------------------------------------------------ + // State labels + // ------------------------------------------------------------------------ + + public final ConfigOption stateLabelFont = new ConfigOption(requireNonNull(new Text().getFont())) { + @Override + public void set(Font value) { + super.set(value); + recomputeEllipsisWidth(); + } + }; + + public static final String ELLIPSIS_STRING = "..."; //$NON-NLS-1$ + + private transient double fEllipsisWidth; + + public double getEllipsisWidth() { + return fEllipsisWidth; + } + + private synchronized void recomputeEllipsisWidth() { + Text text = new Text(ELLIPSIS_STRING); + text.setFont(stateLabelFont.get()); + text.applyCss(); + fEllipsisWidth = text.getLayoutBounds().getWidth(); + } + + // ------------------------------------------------------------------------ + // Tooltips + // ------------------------------------------------------------------------ + + public final ConfigOption toolTipFont = new ConfigOption<>(Font.font(14)); + + public final ConfigOption toolTipFontFill = new ConfigOption<>(requireNonNull(Color.WHITE)); + +} diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/ITimelineWidget.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/ITimelineWidget.java new file mode 100644 index 0000000000..3885c67d5a --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/ITimelineWidget.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.ui.timeline; + +import org.eclipse.jdt.annotation.Nullable; + +import javafx.scene.Parent; +import javafx.scene.control.ScrollPane; +import javafx.scene.control.SplitPane; +import javafx.scene.shape.Rectangle; + +public interface ITimelineWidget { + + String getName(); + + Parent getRootNode(); + + void dispose(); + + /** + * Many widgets will use a SplitPane to separate a tree or info pane on the + * left, and a time-based pane on the right. This method is used to return + * this pane so the manager can apply common operations on them. + * + * @return The horizontal split pane, or 'null' if the widget doesn't use + * one and uses the full horizontal width of the view. + */ + @Nullable SplitPane getSplitPane(); + + @Nullable ScrollPane getTimeBasedScrollPane(); + + @Nullable Rectangle getSelectionRectangle(); + + @Nullable Rectangle getOngoingSelectionRectangle(); +} diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/Messages.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/Messages.java new file mode 100644 index 0000000000..992682f790 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/Messages.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.ui.timeline; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.osgi.util.NLS; + +/** + * Message bundle for the package + * + * @noreference Messages class + */ +@SuppressWarnings("javadoc") +@NonNullByDefault({}) +public class Messages extends NLS { + + private static final String BUNDLE_NAME = Messages.class.getPackage().getName() + ".messages"; //$NON-NLS-1$ + + public static String timelineViewName; + + static { + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() { + } +} diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/TimelineManager.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/TimelineManager.java new file mode 100644 index 0000000000..956ce4fa21 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/TimelineManager.java @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.ui.timeline; + +import java.util.HashSet; +import java.util.Set; + +import org.lttng.scope.tmf2.views.core.NestingBoolean; +import org.lttng.scope.tmf2.views.core.context.ViewGroupContext; +import org.lttng.scope.tmf2.views.core.timegraph.control.TimeGraphModelControl; +import org.lttng.scope.tmf2.views.core.timegraph.model.provider.ITimeGraphModelProvider; +import org.lttng.scope.tmf2.views.core.timegraph.model.provider.ITimeGraphModelProviderFactory; +import org.lttng.scope.tmf2.views.core.timegraph.model.provider.TimeGraphModelProviderManager; +import org.lttng.scope.tmf2.views.core.timegraph.model.provider.TimeGraphModelProviderManager.TimeGraphOutput; +import org.lttng.scope.tmf2.views.core.timegraph.view.TimeGraphModelView; +import org.lttng.scope.tmf2.views.ui.timeline.widgets.timegraph.TimeGraphWidget; + +import javafx.application.Platform; +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.DoubleProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleDoubleProperty; +import javafx.scene.control.ScrollPane; +import javafx.scene.control.SplitPane; +import javafx.scene.shape.Rectangle; + +public class TimelineManager implements TimeGraphOutput { + + private static final double INITIAL_DIVIDER_POSITION = 0.2; + + private final TimelineView fView; + private final ViewGroupContext fViewContext; + private final Set fWidgets = new HashSet<>(); + + private final NestingBoolean fHScrollListenerStatus = new NestingBoolean(); + + private final DoubleProperty fDividerPosition = new SimpleDoubleProperty(INITIAL_DIVIDER_POSITION); + private final DoubleProperty fHScrollValue = new SimpleDoubleProperty(0); + + /* Properties to sync ongoing selection rectangles */ + private final BooleanProperty fSelectionVisible = new SimpleBooleanProperty(true); + private final DoubleProperty fOngoingSelectionX = new SimpleDoubleProperty(); + private final DoubleProperty fOngoingSelectionWidth = new SimpleDoubleProperty(); + private final BooleanProperty fOngoingSelectionVisible = new SimpleBooleanProperty(false); + + public TimelineManager(TimelineView view, ViewGroupContext viewContext) { + fView = view; + fViewContext = viewContext; + TimeGraphModelProviderManager.instance().registerOutput(this); + } + + @Override + public void providerRegistered(ITimeGraphModelProviderFactory factory) { + /* Instantiate a widget for this provider type */ + ITimeGraphModelProvider provider = factory.get(); + TimeGraphModelControl control = new TimeGraphModelControl(fViewContext, provider); + TimeGraphWidget viewer = new TimeGraphWidget(control, fHScrollListenerStatus); + control.attachView(viewer); + + /* + * Bind properties in a runLater() statement, so that the UI views have + * already been initialized. The divider position, for instance, only + * has effect after the view is visible. + */ + Platform.runLater(() -> { + /* Bind divider position, if applicable */ + SplitPane splitPane = viewer.getSplitPane(); + splitPane.getDividers().get(0).positionProperty().bindBidirectional(fDividerPosition); + + /* Bind h-scrollbar position */ + ScrollPane scrollPane = viewer.getTimeBasedScrollPane(); + scrollPane.hvalueProperty().bindBidirectional(fHScrollValue); + + /* Bind the selection rectangles together */ + Rectangle selectionRect = viewer.getSelectionRectangle(); + if (selectionRect != null) { + selectionRect.visibleProperty().bindBidirectional(fSelectionVisible); + } + Rectangle ongoingSelectionRect = viewer.getOngoingSelectionRectangle(); + if (ongoingSelectionRect != null) { + ongoingSelectionRect.layoutXProperty().bindBidirectional(fOngoingSelectionX); + ongoingSelectionRect.widthProperty().bindBidirectional(fOngoingSelectionWidth); + ongoingSelectionRect.visibleProperty().bindBidirectional(fOngoingSelectionVisible); + } + }); + + fWidgets.add(viewer); + fView.addWidget(viewer.getRootNode()); + + } + + public void dispose() { + TimeGraphModelProviderManager.instance().unregisterOutput(this); + + fWidgets.forEach(w -> { + if (w instanceof TimeGraphModelView) { + /* + * TimeGraphModelView's are disposed via their control + * + * FIXME Do this better. + */ + ((TimeGraphModelView) w).getControl().dispose(); + } else { + w.dispose(); + } + }); + fWidgets.clear(); + } + + void resetInitialSeparatorPosition() { + fDividerPosition.set(INITIAL_DIVIDER_POSITION); + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/TimelineView.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/TimelineView.java new file mode 100644 index 0000000000..0a074ba4f0 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/TimelineView.java @@ -0,0 +1,82 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + *******************************************************************************/ + +package org.lttng.scope.tmf2.views.ui.timeline; + +import static java.util.Objects.requireNonNull; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.tracecompass.tmf.ui.views.TmfView; +import org.lttng.scope.tmf2.views.core.context.ViewGroupContext; +import org.lttng.scope.tmf2.views.ui.jfx.JfxUtils; + +import javafx.embed.swt.FXCanvas; +import javafx.geometry.Orientation; +import javafx.scene.Node; +import javafx.scene.Scene; +import javafx.scene.control.SplitPane; + +public class TimelineView extends TmfView { + + public static final String VIEW_ID = "org.lttng.scope.views.timeline"; //$NON-NLS-1$ + + private static final String VIEW_NAME = requireNonNull(Messages.timelineViewName); + + private @Nullable TimelineManager fManager; + private @Nullable SplitPane fSplitPane; + + public TimelineView() { + super(VIEW_NAME); + } + + @Override + public void createPartControl(@Nullable Composite parent) { + if (parent == null) { + return; + } + + FXCanvas fxCanvas = new FXCanvas(parent, SWT.NONE); + SplitPane sp = new SplitPane(); + sp.setOrientation(Orientation.VERTICAL); + fSplitPane = sp; + + TimelineManager manager = new TimelineManager(this, ViewGroupContext.getCurrent()); + fManager = manager; + + fxCanvas.setScene(new Scene(sp)); + + /* + * Set the initial divider positions. Has to be done *after* the + * Stage/Scene is initialized. + */ + manager.resetInitialSeparatorPosition(); + } + + void addWidget(Node node) { + SplitPane sp = requireNonNull(fSplitPane); + JfxUtils.runOnMainThread(() -> sp.getItems().add(node)); + } + + @Override + public void dispose() { + if (fManager != null) { + fManager.dispose(); + } + if (fSplitPane != null) { + fSplitPane.getItems().clear(); + } + } + + @Override + public void setFocus() { + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/messages.properties b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/messages.properties new file mode 100644 index 0000000000..dd76d916ac --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/messages.properties @@ -0,0 +1,10 @@ +############################################################################### +# Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir +# +# 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 +############################################################################### + +timelineViewName = Timeline diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/package-info.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/package-info.java new file mode 100644 index 0000000000..e5f2c74370 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/package-info.java @@ -0,0 +1,11 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +@org.eclipse.jdt.annotation.NonNullByDefault +package org.lttng.scope.tmf2.views.ui.timeline; diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/LatestTaskExecutor.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/LatestTaskExecutor.java new file mode 100644 index 0000000000..fc3d264280 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/LatestTaskExecutor.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + *******************************************************************************/ + +package org.lttng.scope.tmf2.views.ui.timeline.widgets.timegraph; + +import java.lang.ref.WeakReference; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import org.eclipse.jdt.annotation.Nullable; + +import javafx.concurrent.Task; + +public class LatestTaskExecutor { + + private static final ExecutorService EXECUTOR = Executors.newFixedThreadPool(2); +// private static final ExecutorService EXECUTOR = Executors.newSingleThreadExecutor(); + + /** + * The latest job that was schedule in this queue. + */ + private WeakReference<@Nullable Task> fLatestTask = new WeakReference<>(null); + + public LatestTaskExecutor() { + } + + public synchronized void schedule(Task newTask) { + Task latestJob = fLatestTask.get(); + if (latestJob != null) { + /* + * Cancel the existing task. Here's hoping it cooperates and ends + * quickly! + */ + latestJob.cancel(false); + } + + /* Start the new job */ + fLatestTask = new WeakReference<>(newTask); + EXECUTOR.submit(newTask); + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/LoadingOverlay.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/LoadingOverlay.java new file mode 100644 index 0000000000..8191cb84ae --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/LoadingOverlay.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.ui.timeline.widgets.timegraph; + +import org.eclipse.jdt.annotation.Nullable; +import org.lttng.scope.tmf2.views.ui.timeline.DebugOptions; + +import javafx.animation.FadeTransition; +import javafx.scene.shape.Rectangle; +import javafx.util.Duration; + +class LoadingOverlay extends Rectangle { + + private final DebugOptions fOpts; + + private @Nullable FadeTransition fCurrentFadeIn; + private @Nullable FadeTransition fCurrentFadeOut; + + public LoadingOverlay(DebugOptions opts) { + fOpts = opts; + + /* + * Set the fill (color) by binding the property to the corresponding + * config option. That way if the use changes the configured value, this + * overlay will follow. + */ + fillProperty().bind(fOpts.loadingOverlayColor); + + /* + * The opacity property on the other hand will change through normal + * operation of the overlay. We are just setting the initial value here, + * no permanent bind. + */ + setOpacity(fOpts.loadingOverlayTransparentOpacity.get()); + + /* + * The overlay should not catch mouse events. Note we could use + * .setPickOnBounds(false) if we wanted to handle events but also allow + * them to go "through". + */ + setMouseTransparent(true); + } + + public synchronized void fadeIn() { + if (fCurrentFadeIn != null) { + /* We're already fading in, let it continue. */ + return; + } + if (fCurrentFadeOut != null) { + /* + * Don't use stop() because that would revert to the initial opacity + * right away. + */ + fCurrentFadeOut.pause(); + fCurrentFadeOut = null; + } + + double fullOpacity = fOpts.loadingOverlayFullOpacity.get(); + double fullFadeInDuration = fOpts.loadingOverlayFadeInDuration.get(); + double startOpacity = getOpacity(); + + /* Do a rule-of-three to determine the duration of fade-in we need. */ + double neededDuration = ((fullOpacity - startOpacity) / fullOpacity) * fullFadeInDuration; + FadeTransition fadeIn = new FadeTransition(new Duration(neededDuration), this); + fadeIn.setFromValue(startOpacity); + fadeIn.setToValue(fullOpacity); + fadeIn.play(); + fCurrentFadeIn = fadeIn; + } + + public synchronized void fadeOut() { + if (fCurrentFadeOut != null) { + /* We're already fading out, let it continue. */ + return; + } + if (fCurrentFadeIn != null) { + fCurrentFadeIn.pause(); + fCurrentFadeIn = null; + } + + double fullOpacity = fOpts.loadingOverlayFullOpacity.get(); + double transparentOpacity = fOpts.loadingOverlayTransparentOpacity.get(); + double fullFadeOutDuration = fOpts.loadingOverlayFadeOutDuration.get(); + double startOpacity = getOpacity(); + + /* Do a rule-of-three to determine the duration of fade-in we need. */ + double neededDuration = (startOpacity / fullOpacity) * fullFadeOutDuration; + FadeTransition fadeOut = new FadeTransition(new Duration(neededDuration), this); + fadeOut.setFromValue(startOpacity); + fadeOut.setToValue(transparentOpacity); + fadeOut.play(); + fCurrentFadeOut = fadeOut; + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/Messages.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/Messages.java new file mode 100644 index 0000000000..ebbdffb1ee --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/Messages.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.ui.timeline.widgets.timegraph; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.osgi.util.NLS; + +/** + * Message bundle for the package + * + * @noreference Messages class + */ +@SuppressWarnings("javadoc") +@NonNullByDefault({}) +public class Messages extends NLS { + + private static final String BUNDLE_NAME = Messages.class.getPackage().getName() + ".messages"; //$NON-NLS-1$ + + public static String statePropertyElement; + public static String statePropertyStateName; + public static String statePropertyStartTime; + public static String statePropertyEndTime; + public static String statePropertyDuration; + + static { + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() { + } +} diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/PeriodicRedrawTask.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/PeriodicRedrawTask.java new file mode 100644 index 0000000000..5cc5894f60 --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/PeriodicRedrawTask.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.ui.timeline.widgets.timegraph; + +import java.util.TimerTask; +import java.util.concurrent.atomic.AtomicLong; + +import org.lttng.scope.tmf2.views.core.TimeRange; +import org.lttng.scope.tmf2.views.core.context.ViewGroupContext; + +/** + * It was quickly determined that having mouse listeners start repaint tasks + * directly is not a good solution, since simply enqueuing a job can potentially + * take time, and thus makes scrolling sluggish and annoying to use. + * + * Instead, a separate thread can look periodically if the current view's + * position has changed since its last check, and queue UI updates as needed. + * + * This class implements such thread, as a {@link TimerTask}. + * + * @author Alexandre Montplaisir + */ +class PeriodicRedrawTask extends TimerTask { + + /** + * Sequence number attached to each redraw operation. Can be used for + * tracing/analysis. + */ + private final AtomicLong fTaskSeq = new AtomicLong(); + private final TimeGraphWidget fViewer; + + private TimeRange fPreviousHorizontalPos = ViewGroupContext.UNINITIALIZED_RANGE; + private VerticalPosition fPreviousVerticalPosition = VerticalPosition.UNINITIALIZED_VP; + + private volatile boolean fForceRedraw = false; + + public PeriodicRedrawTask(TimeGraphWidget viewer) { + fViewer = viewer; + } + + @Override + public void run() { + if (!fViewer.getDebugOptions().isPaintingEnabled.get()) { + return; + } + + TimeRange currentHorizontalPos = fViewer.getControl().getViewContext().getCurrentVisibleTimeRange(); + VerticalPosition currentVerticalPos = fViewer.getCurrentVerticalPosition(); + + boolean movedHorizontally = !currentHorizontalPos.equals(fPreviousHorizontalPos); + boolean movedVertically = !currentVerticalPos.equals(fPreviousVerticalPosition); + + if (fForceRedraw) { + fForceRedraw = false; + /* Then skip the next checks */ + } else { + /* + * Skip painting if the previous position is the exact same as last + * time. Also skip if were not yet initialized. + */ + if (!movedHorizontally && !movedVertically) { + return; + } + if (currentHorizontalPos.equals(ViewGroupContext.UNINITIALIZED_RANGE) + || currentVerticalPos.equals(VerticalPosition.UNINITIALIZED_VP)) { + return; + } + } + + fPreviousHorizontalPos = currentHorizontalPos; + fPreviousVerticalPosition = currentVerticalPos; + + fViewer.paintArea(currentHorizontalPos, currentVerticalPos, + movedHorizontally, movedVertically, + fTaskSeq.getAndIncrement()); + } + + public void forceRedraw() { + fForceRedraw = true; + } + +} diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/StateRectangle.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/StateRectangle.java new file mode 100644 index 0000000000..8e5be376ed --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/StateRectangle.java @@ -0,0 +1,294 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.ui.timeline.widgets.timegraph; + +import static java.util.Objects.requireNonNull; + +import java.util.Arrays; +import java.util.Map; +import java.util.Objects; + +import org.eclipse.jdt.annotation.Nullable; +import org.lttng.scope.tmf2.views.core.TimeRange; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.LineThickness; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.states.TimeGraphStateInterval; +import org.lttng.scope.tmf2.views.ui.jfx.CountingGridPane; +import org.lttng.scope.tmf2.views.ui.jfx.JfxColorFactory; +import org.lttng.scope.tmf2.views.ui.timeline.DebugOptions; + +import com.google.common.base.MoreObjects; + +import javafx.application.Platform; +import javafx.geometry.Point2D; +import javafx.scene.Node; +import javafx.scene.control.Tooltip; +import javafx.scene.input.MouseButton; +import javafx.scene.paint.Paint; +import javafx.scene.shape.Rectangle; +import javafx.scene.text.Text; + +/** + * {@link Rectangle} object used to draw states in the timegraph. It attaches + * the {@link TimeGraphStateInterval} that represents this state. + * + * @author Alexandre Montplaisir + */ +public class StateRectangle extends Rectangle { + + private final TimeGraphWidget fWidget; + private final int fEntryIndex; + private final TimeGraphStateInterval fInterval; + + private @Nullable transient Paint fBaseColor; + private @Nullable transient Paint fSelectedColor; + + private @Nullable Tooltip fTooltip = null; + + /** + * Constructor + * + * @param viewer + * The viewer in which the rectangle will be placed + * @param interval + * The source interval model object + * @param entryIndex + * The index of the entry to which this state belongs. + */ + public StateRectangle(TimeGraphWidget viewer, TimeGraphStateInterval interval, int entryIndex) { + fWidget = viewer; + fEntryIndex = entryIndex; + fInterval = interval; + + /* + * It is possible, especially when re-opening already-indexed traces, + * that the indexer and the state system do not report the same + * start/end times. Make sure to clamp the interval's bounds to the + * valid values. + */ + TimeRange traceRange = viewer.getControl().getViewContext().getCurrentTraceFullRange(); + long traceStart = traceRange.getStart(); + long intervalStart = interval.getStartTime(); + double xStart = viewer.timestampToPaneXPos(Math.max(traceStart, intervalStart)); + + long traceEnd = traceRange.getEnd(); + long intervalEndTime = interval.getEndTime(); + double xEnd = viewer.timestampToPaneXPos(Math.min(traceEnd, intervalEndTime)); + + double width = Math.max(1.0, xEnd - xStart) + 1.0; + double height = getHeightFromThickness(interval.getLineThickness().get()); + double y = computeY(height); + + setX(0); + setLayoutX(xStart); + setY(y); + setWidth(width); + setHeight(height); + + double opacity = viewer.getDebugOptions().stateIntervalOpacity.get(); + setOpacity(opacity); + + updatePaint(); + + /* Set initial selection state and selection listener. */ + if (this.equals(viewer.getSelectedState())) { + setSelected(true); + viewer.setSelectedState(this, false); + } else { + setSelected(false); + } + + setOnMouseClicked(e -> { + if (e.getButton() != MouseButton.PRIMARY) { + return; + } + viewer.setSelectedState(this, true); + }); + + /* + * Initialize the tooltip when the mouse enters the rectangle, if it was + * not done previously. + */ + setOnMouseEntered(e -> generateTooltip()); + } + + private void generateTooltip() { + if (fTooltip != null) { + return; + } + TooltipContents ttContents = new TooltipContents(fWidget.getDebugOptions()); + ttContents.addTooltipRow(Messages.statePropertyElement, fInterval.getTreeElement().getName()); + ttContents.addTooltipRow(Messages.statePropertyStateName, fInterval.getStateName()); + ttContents.addTooltipRow(Messages.statePropertyStartTime, fInterval.getStartTime()); + ttContents.addTooltipRow(Messages.statePropertyEndTime, fInterval.getEndTime()); + ttContents.addTooltipRow(Messages.statePropertyDuration, fInterval.getDuration() + " ns"); //$NON-NLS-1$ + /* Add rows corresponding to the properties from the interval */ + Map properties = fInterval.getProperties(); + properties.forEach((k, v) -> ttContents.addTooltipRow(k, v)); + + Tooltip tt = new Tooltip(); + tt.setGraphic(ttContents); + Tooltip.install(this, tt); + fTooltip = tt; + } + + /** + * Return the model interval representing this state + * + * @return The interval model object + */ + public TimeGraphStateInterval getStateInterval() { + return fInterval; + } + + public void updatePaint() { + /* Update the color */ + /* Set a special paint for multi-state intervals */ + if (fInterval.isMultiState()) { + Paint multiStatePaint = fWidget.getDebugOptions().multiStatePaint.get(); + fBaseColor = multiStatePaint; + fSelectedColor = multiStatePaint; + } else { + fBaseColor = JfxColorFactory.getColorFromDef(fInterval.getColorDefinition().get()); + fSelectedColor = JfxColorFactory.getDerivedColorFromDef(fInterval.getColorDefinition().get()); + } + setFill(fBaseColor); + + /* Update the line thickness */ + LineThickness lt = fInterval.getLineThickness().get(); + double height = getHeightFromThickness(lt); + setHeight(height); + /* We need to adjust the y position too */ + setY(computeY(height)); + } + + /** + * Compute the Y property (the Y position of the *top* of the rectangle) + * this rectangle should have on its pane. This takes into consideration the + * entry it belongs to, as well as its target height. + * + * For example, if the line thickness of the rectangle changes, its Y has to + * be recomputed so that the rectangle remains centered on its entry line. + * + * This method does not change the yProperty of the rectangle. + */ + private double computeY(double height) { + double yOffset = (TimeGraphWidget.ENTRY_HEIGHT - height) / 2; + double y = fEntryIndex * TimeGraphWidget.ENTRY_HEIGHT + yOffset; + return y; + } + + public void setSelected(boolean isSelected) { + if (isSelected) { + setFill(fSelectedColor); + } else { + setFill(fBaseColor); + hideTooltip(); + } + } + + public void showTooltip(boolean beginning) { + generateTooltip(); + Tooltip tt = requireNonNull(fTooltip); + + /* + * Show the tooltip first, then move it to the correct location. It + * needs to be shown for its getWidth() etc. to be populated. + */ + tt.show(this, 0, 0); + + Point2D position; + if (beginning) { + /* Align to the bottom-left of the rectangle, left-aligned. */ + /* Yes, it needs to be getX() here (0), not getLayoutX(). */ + position = this.localToScreen(getX(), getY() + getHeight()); + } else { + /* Align to the bottom-right of the rectangle, right-aligned */ + position = this.localToScreen(getX() + getWidth() - tt.getWidth(), getY() + getHeight()); + } + + tt.setAnchorX(position.getX()); + tt.setAnchorY(position.getY()); + } + + public void hideTooltip() { + Tooltip tt = fTooltip; + if (tt != null) { + Platform.runLater(() -> { + tt.hide(); + }); + } + } + + @Override + protected void finalize() { + hideTooltip(); + } + + public static double getHeightFromThickness(LineThickness lt) { + switch (lt) { + case NORMAL: + default: + return TimeGraphWidget.ENTRY_HEIGHT - 4; + case SMALL: + return TimeGraphWidget.ENTRY_HEIGHT - 8; + case TINY: + return TimeGraphWidget.ENTRY_HEIGHT - 12; + } + } + + @Override + public int hashCode() { + return Objects.hash(fWidget, fInterval); + } + + @Override + public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + StateRectangle other = (StateRectangle) obj; + return Objects.equals(fWidget, other.fWidget) + && Objects.equals(fInterval, other.fInterval); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("interval", fInterval) //$NON-NLS-1$ + .toString(); + } + + private static class TooltipContents extends CountingGridPane { + + private final DebugOptions fOpts; + + public TooltipContents(DebugOptions opts) { + fOpts = opts; + } + + public void addTooltipRow(Object... objects) { + Node[] labels = Arrays.stream(objects) + .map(Object::toString) + .map(Text::new) + .peek(text -> { + text.fontProperty().bind(fOpts.toolTipFont); + text.fillProperty().bind(fOpts.toolTipFontFill); + }) + .toArray(Node[]::new); + appendRow(labels); + } + } +} diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/TimeGraphWidget.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/TimeGraphWidget.java new file mode 100644 index 0000000000..068d17a27d --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/TimeGraphWidget.java @@ -0,0 +1,946 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + *******************************************************************************/ + +package org.lttng.scope.tmf2.views.ui.timeline.widgets.timegraph; + +import static java.util.Objects.requireNonNull; + +import java.util.Collection; +import java.util.Timer; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import org.lttng.scope.tmf2.views.core.NestingBoolean; +import org.lttng.scope.tmf2.views.core.TimeRange; +import org.lttng.scope.tmf2.views.core.timegraph.control.TimeGraphModelControl; +import org.lttng.scope.tmf2.views.core.timegraph.model.provider.ITimeGraphModelProvider; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeRender; +import org.lttng.scope.tmf2.views.core.timegraph.view.TimeGraphModelView; +import org.lttng.scope.tmf2.views.ui.timeline.DebugOptions; +import org.lttng.scope.tmf2.views.ui.timeline.ITimelineWidget; +import org.lttng.scope.tmf2.views.ui.timeline.TimelineView; +import org.lttng.scope.tmf2.views.ui.timeline.widgets.timegraph.layer.TimeGraphArrowLayer; +import org.lttng.scope.tmf2.views.ui.timeline.widgets.timegraph.layer.TimeGraphBackgroundLayer; +import org.lttng.scope.tmf2.views.ui.timeline.widgets.timegraph.layer.TimeGraphDrawnEventLayer; +import org.lttng.scope.tmf2.views.ui.timeline.widgets.timegraph.layer.TimeGraphSelectionLayer; +import org.lttng.scope.tmf2.views.ui.timeline.widgets.timegraph.layer.TimeGraphStateLayer; +import org.lttng.scope.tmf2.views.ui.timeline.widgets.timegraph.toolbar.ViewerToolBar; + +import com.google.common.annotations.VisibleForTesting; + +import javafx.application.Platform; +import javafx.beans.property.DoubleProperty; +import javafx.beans.property.SimpleDoubleProperty; +import javafx.beans.value.ChangeListener; +import javafx.concurrent.Task; +import javafx.event.EventHandler; +import javafx.geometry.Orientation; +import javafx.scene.Group; +import javafx.scene.Parent; +import javafx.scene.control.ScrollPane; +import javafx.scene.control.ScrollPane.ScrollBarPolicy; +import javafx.scene.control.SplitPane; +import javafx.scene.control.ToolBar; +import javafx.scene.input.InputEvent; +import javafx.scene.input.ScrollEvent; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.Pane; +import javafx.scene.paint.Color; +import javafx.scene.shape.Rectangle; + +/** + * Viewer for the {@link TimelineView}, encapsulating all the view's + * controls. + * + * Both ScrolledPanes's vertical scrollbars are bound together, so that they + * scroll together. + * + * @author Alexandre Montplaisir + */ +public class TimeGraphWidget extends TimeGraphModelView implements ITimelineWidget { + + // ------------------------------------------------------------------------ + // Style definitions + // (Could eventually be moved to separate .css file?) + // ------------------------------------------------------------------------ + + public static final Color BACKGROUD_LINES_COLOR = requireNonNull(Color.LIGHTBLUE); + + private static final String BACKGROUND_STYLE = "-fx-background-color: rgba(255, 255, 255, 255);"; //$NON-NLS-1$ + + private static final int LABEL_SIDE_MARGIN = 10; + + /** + * Height of individual entries (text + states), including padding. + * + * TODO Make this configurable (vertical zoom feature) + */ + public static final double ENTRY_HEIGHT = 20; + + /** Minimum allowed zoom level, in nanos per pixel */ + private static final double ZOOM_LIMIT = 1.0; + + // ------------------------------------------------------------------------ + // Instance fields + // ------------------------------------------------------------------------ + + private final DebugOptions fDebugOptions = new DebugOptions(); + + private final ScrollingContext fScrollingCtx = new ScrollingContext(); + private final ZoomActions fZoomActions = new ZoomActions(); + + /* + * Children of the time graph pane are split into groups, so we can easily + * redraw or add only some of them. + */ + // TODO Layer for bookmarks + private final TimeGraphBackgroundLayer fBackgroundLayer; + private final TimeGraphStateLayer fStateLayer; + private final TimeGraphArrowLayer fArrowLayer; + private final TimeGraphDrawnEventLayer fDrawnEventLayer; + private final TimeGraphSelectionLayer fSelectionLayer; + private final Group fTimeGraphLoadingOverlayGroup; + + private final LatestTaskExecutor fTaskExecutor = new LatestTaskExecutor(); + + private final NestingBoolean fHScrollListenerStatus; + + private final BorderPane fBasePane; + private final ToolBar fToolBar; + private final SplitPane fSplitPane; + + private final TimeGraphWidgetTreeArea fTreeArea; + + private final Pane fTimeGraphPane; + private final ScrollPane fTimeGraphScrollPane; + + private final LoadingOverlay fTimeGraphLoadingOverlay; + + private final Timer fUiUpdateTimer = new Timer(); + private final PeriodicRedrawTask fUiUpdateTimerTask = new PeriodicRedrawTask(this); + + private volatile TimeGraphTreeRender fLatestTreeRender = TimeGraphTreeRender.EMPTY_RENDER; + + /** Current zoom level */ + private final DoubleProperty fNanosPerPixel = new SimpleDoubleProperty(1.0); + + /** + * Constructor + * + * @param control + * The control for this widget. See + * {@link TimeGraphModelControl}. + * @param hScrollListenerStatus + * If the hscroll property of this widget's scrollpane is bound + * with others (possibly through the + * {@link ITimelineWidget#getTimeBasedScrollPane()} method), then + * a common {@link NestingBoolean} should be used to track + * requests to disable the hscroll listener. + *

+ * If the widget is to be used stand-alone, then you can pass a " + * new NestingBoolean() " that only this view will + * use. + */ + public TimeGraphWidget(TimeGraphModelControl control, NestingBoolean hScrollListenerStatus) { + super(control); + fHScrollListenerStatus = hScrollListenerStatus; + + // -------------------------------------------------------------------- + // Prepare the tree part's scene graph + // -------------------------------------------------------------------- + + fTreeArea = new TimeGraphWidgetTreeArea(ENTRY_HEIGHT, getControl().getModelRenderProvider().traceProperty()); + + // -------------------------------------------------------------------- + // Prepare the time graph's part scene graph + // -------------------------------------------------------------------- + + fTimeGraphLoadingOverlay = new LoadingOverlay(fDebugOptions); + fTimeGraphLoadingOverlayGroup = new Group(fTimeGraphLoadingOverlay); + + fTimeGraphPane = new Pane(); + fBackgroundLayer = new TimeGraphBackgroundLayer(this, new Group()); + fStateLayer = new TimeGraphStateLayer(this, new Group()); + fArrowLayer = new TimeGraphArrowLayer(this, new Group()); + fDrawnEventLayer = new TimeGraphDrawnEventLayer(this, new Group()); + fSelectionLayer = new TimeGraphSelectionLayer(this, new Group()); + + /* + * The order of the layers is important here, it will go from back to + * front. + */ + fTimeGraphPane.getChildren().addAll(fBackgroundLayer.getParentGroup(), + fStateLayer.getParentGroup(), + fStateLayer.getLabelGroup(), + fArrowLayer.getParentGroup(), + fDrawnEventLayer.getParentGroup(), + fSelectionLayer.getParentGroup(), + fTimeGraphLoadingOverlayGroup); + + fTimeGraphPane.setStyle(BACKGROUND_STYLE); + + /* + * We control the width of the time graph pane programmatically, so + * ensure that calls to setPrefWidth set the actual width right away. + */ + fTimeGraphPane.minWidthProperty().bind(fTimeGraphPane.prefWidthProperty()); + fTimeGraphPane.maxWidthProperty().bind(fTimeGraphPane.prefWidthProperty()); + + /* + * Ensure the time graph pane is always exactly the same vertical size + * as the tree pane, so they remain aligned. + */ + + fTimeGraphPane.minHeightProperty().bind(fTreeArea.currentHeightProperty()); + fTimeGraphPane.prefHeightProperty().bind(fTreeArea.currentHeightProperty()); + fTimeGraphPane.maxHeightProperty().bind(fTreeArea.currentHeightProperty()); + + /* + * Setup clipping on the timegraph pane, meaning its children outside of its + * actual boundary should not be rendered. For example, when the tree gets + * collapsed, data for hidden entries should be hidden too. + */ + Rectangle clipRect = new Rectangle(); + clipRect.setX(0); + clipRect.setY(0); + clipRect.widthProperty().bind(fTimeGraphPane.widthProperty()); + clipRect.heightProperty().bind(fTimeGraphPane.heightProperty()); + fTimeGraphPane.setClip(clipRect); + + /* + * Set the loading overlay's size to always follow the size of the pane. + */ + fTimeGraphLoadingOverlay.widthProperty().bind(fTimeGraphPane.widthProperty()); + fTimeGraphLoadingOverlay.heightProperty().bind(fTimeGraphPane.heightProperty()); + + fTimeGraphScrollPane = new ScrollPane(fTimeGraphPane); + fTimeGraphScrollPane.setVbarPolicy(ScrollBarPolicy.ALWAYS); + fTimeGraphScrollPane.setHbarPolicy(ScrollBarPolicy.ALWAYS); + fTimeGraphScrollPane.setFitToHeight(true); + fTimeGraphScrollPane.setFitToWidth(true); + fTimeGraphScrollPane.setPannable(true); + + /* + * Attach the scrollbar listener + * + * TODO Move this to the timeline ? + */ + fTimeGraphScrollPane.hvalueProperty().addListener(fScrollingCtx.fHScrollChangeListener); + + /* + * Mouse scroll handlers (for zooming) are attached to the time graph + * itself: events let through will be used by the scrollpane as normal + * scroll actions. + */ + fTimeGraphPane.setOnScroll(fMouseScrollListener); + + /* + * Upon reception of any mouse/keyboard event, if there's still a drawn + * tooltip it should be hidden. + */ + fTimeGraphPane.addEventFilter(InputEvent.ANY, e -> { + StateRectangle selectedState = fSelectedState; + if (selectedState != null) { + selectedState.hideTooltip(); + } + /* We must not consume the event here */ + }); + + /* Synchronize the two scrollpanes' vertical scroll bars together */ + fTreeArea.getVerticalScrollBar().valueProperty().bindBidirectional(fTimeGraphScrollPane.vvalueProperty()); + + // -------------------------------------------------------------------- + // Prepare the top-level area + // -------------------------------------------------------------------- + + fToolBar = new ViewerToolBar(this); + + fSplitPane = new SplitPane(fTreeArea, fTimeGraphScrollPane); + fSplitPane.setOrientation(Orientation.HORIZONTAL); + + fBasePane = new BorderPane(); + fBasePane.setCenter(fSplitPane); + fBasePane.setTop(fToolBar); + + /* Start the periodic redraw thread */ + long delay = fDebugOptions.uiUpdateDelay.get(); + fUiUpdateTimer.schedule(fUiUpdateTimerTask, delay, delay); + } + + public TimeGraphTreeRender getLatestTreeRender() { + return fLatestTreeRender; + } + + // ------------------------------------------------------------------------ + // ITimelineWidget + // ------------------------------------------------------------------------ + + @Override + public String getName() { + return getControl().getModelRenderProvider().getName(); + } + + @Override + public Parent getRootNode() { + return fBasePane; + } + + @Override + public @NonNull SplitPane getSplitPane() { + return fSplitPane; + } + + @Override + public @NonNull ScrollPane getTimeBasedScrollPane() { + return fTimeGraphScrollPane; + } + + @Override + public @Nullable Rectangle getSelectionRectangle() { + return fSelectionLayer.getSelectionRectangle(); + } + + @Override + public @Nullable Rectangle getOngoingSelectionRectangle() { + return fSelectionLayer.getOngoingSelectionRectangle(); + } + + // ------------------------------------------------------------------------ + // Operations + // ------------------------------------------------------------------------ + + @Override + public void disposeImpl() { + /* Stop/cleanup the redraw thread */ + fUiUpdateTimer.cancel(); + fUiUpdateTimer.purge(); + } + + @Override + public void clear() { + Platform.runLater(() -> { + /* + * Clear the generated children of the various groups so they go + * back to their initial (post-constructor) state. + */ + fTreeArea.clear(); + + fBackgroundLayer.clear(); + fStateLayer.clear(); + fArrowLayer.clear(); + fDrawnEventLayer.clear(); + + /* Also clear whatever cached objects the viewer currently has. */ + fLatestTreeRender = TimeGraphTreeRender.EMPTY_RENDER; + fUiUpdateTimerTask.forceRedraw(); + }); + } + + @Override + public void seekVisibleRange(TimeRange newVisibleRange) { + final TimeRange fullTimeGraphRange = getViewContext().getCurrentTraceFullRange(); + + /* Update the zoom level */ + long windowTimeRange = newVisibleRange.getDuration(); + double timeGraphVisibleWidth = fTimeGraphScrollPane.getViewportBounds().getWidth(); + /* Clamp the width to 1 px (0 is reported if the view is not visible) */ + timeGraphVisibleWidth = Math.max(1, timeGraphVisibleWidth); + fNanosPerPixel.set(windowTimeRange / timeGraphVisibleWidth); + + double oldTotalWidth = fTimeGraphPane.getLayoutBounds().getWidth(); + double newTotalWidth = timestampToPaneXPos(fullTimeGraphRange.getEnd()) - timestampToPaneXPos(fullTimeGraphRange.getStart()); + if (newTotalWidth < 1.0) { + // FIXME + return; + } + + double newValue; + if (newVisibleRange.getStart() == fullTimeGraphRange.getStart()) { + newValue = fTimeGraphScrollPane.getHmin(); + } else if (newVisibleRange.getEnd() == fullTimeGraphRange.getEnd()) { + newValue = fTimeGraphScrollPane.getHmax(); + } else { + /* + * The "hvalue" is in reference to the beginning of the pane, not + * the middle point as one could think. + * + * Also note that the "scrollable distance" is not simply + * "timeGraphTotalWidth", it's + * "timeGraphTotalWidth - timeGraphVisibleWidth". The view does not + * allow scrolling the start and end edges up to the middle point + * for example. + * + * See http://stackoverflow.com/a/23518314/4227853 for a great + * explanation. + */ + double startPos = timestampToPaneXPos(newVisibleRange.getStart()); + newValue = startPos / (newTotalWidth - timeGraphVisibleWidth); + } + + fHScrollListenerStatus.disable(); + try { + + /* + * If the zoom level changed, resize the pane and relocate its + * current contents. That way the "intermediate" display before the + * next repaint will continue showing correct data. + */ + if (Math.abs(newTotalWidth - oldTotalWidth) > 0.5) { + + /* Resize/reposition the state rectangles */ + double factor = (newTotalWidth / oldTotalWidth); + fStateLayer.getRenderedStateRectangles().forEach(rect -> { + rect.setLayoutX(rect.getLayoutX() * factor); + rect.setWidth(rect.getWidth() * factor); + }); + + /* Reposition the text labels (don't stretch them!) */ + fStateLayer.getRenderedStateLabels().forEach(text -> { + text.setX(text.getX() * factor); + }); + + /* Reposition the arrows */ + fArrowLayer.getRenderedArrows().forEach(arrow -> { + arrow.setStartX(arrow.getStartX() * factor); + arrow.setEndX(arrow.getEndX() * factor); + }); + + /* Reposition the drawn events */ + fDrawnEventLayer.getRenderedEvents().forEach(event -> { + /* + * Drawn events use the "translate" properties to define + * their position. + */ + event.setTranslateX(event.getTranslateX() * factor); + }); + + + /* + * Resize the pane itself. Remember min/max are bound to the + * "pref" width, so this will change the actual size right away. + */ + fTimeGraphPane.setPrefWidth(newTotalWidth); + /* + * Since we changed the size of a child of the scrollpane, it's + * important to call layout() on it before setHvalue(). If we + * don't, the setHvalue() will apply to the old layout, and the + * upcoming pulse will simply revert our changes. + */ + fTimeGraphScrollPane.layout(); + } + + fTimeGraphScrollPane.setHvalue(newValue); + + } finally { + fHScrollListenerStatus.enable(); + } + + /* + * Redraw the current selection, as it may have moved if we changed the + * size of the pane. + */ + redrawSelection(); + } + + /** + * + * Paint the specified view area. + * + * @param windowRange + * The horizontal position where the visible window currently is + * @param verticalPos + * The vertical position where the visible window currently is + * @param movedHorizontally + * If we have moved horizontally since the last redraw. May be + * used to skip some operations. If you are not sure say "true". + * @param movedVertically + * If we have moved vertically since the last redraw. May be used + * to skip some operations. If you are not sure say "true". + * @param taskSeqNb + * The sequence number of this task, used for logging only + */ + void paintArea(TimeRange windowRange, VerticalPosition verticalPos, + boolean movedHorizontally, boolean movedVertically, + long taskSeqNb) { + final TimeRange fullTimeGraphRange = getViewContext().getCurrentTraceFullRange(); + + /* + * Request the needed renders and prepare the corresponding UI objects. + * We may ask for some padding on each side, clamped by the trace's + * start and end. + */ + final long timeRangePadding = Math.round(windowRange.getDuration() * fDebugOptions.renderRangePadding.get()); + final long renderingStartTime = Math.max(fullTimeGraphRange.getStart(), windowRange.getStart() - timeRangePadding); + final long renderingEndTime = Math.min(fullTimeGraphRange.getEnd(), windowRange.getEnd() + timeRangePadding); + final TimeRange renderingRange = TimeRange.of(renderingStartTime, renderingEndTime); + + /* + * Start a new repaint, display the "loading" overlay. The next + * paint task to finish will put it back to non-visible. + */ + if (getDebugOptions().isLoadingOverlayEnabled.get()) { + fTimeGraphLoadingOverlay.fadeIn(); + } + + Task<@Nullable Void> task = new Task<@Nullable Void>() { + @Override + protected @Nullable Void call() { + System.err.println("Starting paint task #" + taskSeqNb); + + ITimeGraphModelProvider modelProvider = getControl().getModelRenderProvider(); + TimeGraphTreeRender treeRender = modelProvider.getTreeRender(); + + if (isCancelled()) { + return null; + } + + /* Prepare the tree part, if needed */ + if (!treeRender.equals(fLatestTreeRender)) { + fLatestTreeRender = treeRender; + fTreeArea.updateTreeContents(treeRender); + } + + if (isCancelled()) { + return null; + } + + /* Paint the background. It's very quick so we can do it every time. */ + fBackgroundLayer.drawContents(treeRender, renderingRange, verticalPos, this); + + /* + * The state rectangles should be redrawn as soon as we move, + * either horizontally or vertically. + */ + fStateLayer.setWindowRange(windowRange); + fStateLayer.drawContents(treeRender, renderingRange, verticalPos, this); + + if (isCancelled()) { + return null; + } + + /* + * Arrows and drawn events are drawn for the full vertical + * range. Only refetch/repaint them if we moved horizontally. + */ + if (movedHorizontally) { + fArrowLayer.drawContents(treeRender, renderingRange, verticalPos, this); + fDrawnEventLayer.drawContents(treeRender, renderingRange, verticalPos, this); + } + + if (isCancelled()) { + return null; + } + + /* Painting is finished, turn off the loading overlay */ + Platform.runLater(() -> { + System.err.println("fading out overlay"); + fTimeGraphLoadingOverlay.fadeOut(); + if (fRepaintLatch != null) { + fRepaintLatch.countDown(); + } + }); + + return null; + } + }; + + System.err.println("Queueing task #" + taskSeqNb); + + /* + * Attach a listener to the task to receive exceptions thrown within the + * task. + */ + task.exceptionProperty().addListener((obs, oldVal, newVal) -> { + if (newVal != null) { + newVal.printStackTrace(); + } + }); + + fTaskExecutor.schedule(task); + } + + @Override + public void drawSelection(TimeRange selectionRange) { + fSelectionLayer.drawSelection(selectionRange); + } + + private void redrawSelection() { + TimeRange selectionRange = getViewContext().getCurrentSelectionTimeRange(); + drawSelection(selectionRange); + } + + private @Nullable StateRectangle fSelectedState = null; + + /** + * Set the selected state rectangle + * + * @param state + * The new selected state. It should ideally be one that's + * present in the scenegraph. + * @param deselectPrevious + * If the previously selected interval should be unmarked as + * selected. + */ + public void setSelectedState(StateRectangle state, boolean deselectPrevious) { + @Nullable StateRectangle previousSelectedState = fSelectedState; + if (previousSelectedState != null) { + previousSelectedState.hideTooltip(); + if (deselectPrevious) { + previousSelectedState.setSelected(false); + } + } + + state.setSelected(true); + fSelectedState = state; + } + + /** + * Get the currently selected state interval + * + * @return The current selected state + */ + public @Nullable StateRectangle getSelectedState() { + return fSelectedState; + } + + /** + * Return all state rectangles currently present in the timegraph. + * + * @return The rendered state rectangles + */ + public Collection getRenderedStateRectangles() { + return fStateLayer.getRenderedStateRectangles(); + } + + // ------------------------------------------------------------------------ + // Mouse event listeners + // ------------------------------------------------------------------------ + + /** + * Class encapsulating the scrolling operations of the time graph pane. + * + * The mouse entered/exited handlers ensure only the scrollpane being + * interacted by the user is the one sending the synchronization signals. + */ + private class ScrollingContext { + + /** + * Listener for the horizontal scrollbar changes + */ + private final ChangeListener fHScrollChangeListener = (observable, oldValue, newValue) -> { + if (!fDebugOptions.isScrollingListenersEnabled.get()) { + System.out.println("HScroll event ignored due to debug option"); + return; + } + if (!fHScrollListenerStatus.enabledProperty().get()) { + System.out.println("HScroll listener triggered but inactive"); + return; + } + + System.out.println("HScroll change listener triggered, oldval=" + oldValue.toString() + ", newval=" + newValue.toString()); + + /* We need to specify the new value here, or else the old one will be used */ + TimeRange range = getTimeGraphEdgeTimestamps(newValue.doubleValue()); + + System.out.println("Sending visible range update: " + range.toString()); + + getControl().updateVisibleTimeRange(range, false); + + /* + * We ask the control to not send this signal back to us (to avoid + * jitter while scrolling), but the next UI update should refresh + * the view accordingly. + * + * It is not our responsibility to update to this + * HorizontalPosition. The control will update accordingly upon + * managing the signal we just sent. + */ + }; + } + + /** + * Event handler attached to the *time graph pane*, to execute zooming + * operations when the control key is down (otherwise, it just lets the even + * bubble to the ScrollPane, which will do a standard scroll). + */ + private final EventHandler fMouseScrollListener = e -> { + boolean forceUseMousePosition = false; + + if (!e.isControlDown()) { + return; + } + + if (e.isShiftDown()) { + forceUseMousePosition = true; + } + e.consume(); + + double delta = e.getDeltaY(); + boolean zoomIn = (delta > 0.0); // false means a zoom-out + + /* + * getX() corresponds to the X position of the mouse on the time graph. + * This is seriously awesome. + */ + fZoomActions.zoom(zoomIn, forceUseMousePosition, e.getX()); + + }; + + // ------------------------------------------------------------------------ + // View-specific actions + // These do not come from the control, but from the view itself + // ------------------------------------------------------------------------ + + /** + * Utils class encapsulating zoom operations + */ + public class ZoomActions { + + public void zoom(boolean zoomIn, boolean forceUseMousePosition, @Nullable Double mouseX) { + final double zoomStep = fDebugOptions.zoomStep.get(); + + double newScaleFactor = (zoomIn ? 1.0 * (1 + zoomStep) : 1.0 * (1 / (1 + zoomStep))); + + /* Send a corresponding window-range signal to the control */ + TimeGraphModelControl control = getControl(); + TimeRange visibleRange = getViewContext().getCurrentVisibleTimeRange(); + + TimeRange currentSelection = getViewContext().getCurrentSelectionTimeRange(); + long currentSelectionCenter = ((currentSelection.getDuration() / 2) + currentSelection.getStart()); + boolean currentSelectionCenterIsVisible = visibleRange.contains(currentSelectionCenter); + + long zoomPivot; + if (fDebugOptions.zoomPivotOnMousePosition.get() && mouseX != null && forceUseMousePosition) { + /* Pivot on mouse position */ + zoomPivot = paneXPosToTimestamp(mouseX); + } else if (fDebugOptions.zoomPivotOnSelection.get() && currentSelectionCenterIsVisible) { + /* Pivot on current selection center */ + zoomPivot = currentSelectionCenter; + } else if (fDebugOptions.zoomPivotOnMousePosition.get() && mouseX != null) { + /* Pivot on mouse position */ + zoomPivot = paneXPosToTimestamp(mouseX); + } else { + /* Pivot on center of visible range */ + zoomPivot = visibleRange.getStart() + (visibleRange.getDuration() / 2); + } + + /* Prevent going closer than the zoom limit */ + double timeGraphVisibleWidth = Math.max(1, fTimeGraphScrollPane.getViewportBounds().getWidth()); + double minDuration = ZOOM_LIMIT * timeGraphVisibleWidth; + + double newDuration = visibleRange.getDuration() * (1.0 / newScaleFactor); + newDuration = Math.max(minDuration, newDuration); + double durationDelta = newDuration - visibleRange.getDuration(); + double zoomPivotRatio = (double) (zoomPivot - visibleRange.getStart()) / (double) (visibleRange.getDuration()); + + long newStart = visibleRange.getStart() - Math.round(durationDelta * zoomPivotRatio); + long newEnd = visibleRange.getEnd() + Math.round(durationDelta - (durationDelta * zoomPivotRatio)); + + /* Clamp newStart and newEnd to the full trace's range */ + TimeRange fullRange = control.getViewContext().getCurrentTraceFullRange(); + long traceStart = fullRange.getStart(); + long traceEnd = fullRange.getEnd(); + newStart = Math.max(newStart, traceStart); + newEnd = Math.min(newEnd, traceEnd); + + control.updateVisibleTimeRange(TimeRange.of(newStart, newEnd), true); + } + + } + + /** + * Get the viewer's zoom actions + * + * @return The zoom actions + */ + public ZoomActions getZoomActions() { + return fZoomActions; + } + + // ------------------------------------------------------------------------ + // Common utils + // ------------------------------------------------------------------------ + + /** + * Determine the timestamps currently represented by the left and right + * edges of the time graph pane. In other words, the current "visible range" + * the view is showing. + * + * Note that this method gets its information from UI objects only, so there + * might be discrepancies between this and the results of + * {@link TimeGraphModelControl#getVisibleTimeRange()}. + * + * @param newHValue + * The "hvalue" property of the horizontal scrollbar to use. If + * null, the current value will be retrieved from the scenegraph + * object. For example, a scrolling listener might want to pass + * its newValue here, since the scenegraph object will not have + * been updated yet. + * @return The corresponding time range + */ + TimeRange getTimeGraphEdgeTimestamps(@Nullable Double newHValue) { + double hvalue = (newHValue == null ? fTimeGraphScrollPane.getHvalue() : newHValue.doubleValue()); + + /* + * Determine the X positions represented by the edges. + */ + double hmin = fTimeGraphScrollPane.getHmin(); + double hmax = fTimeGraphScrollPane.getHmax(); + double contentWidth = fTimeGraphPane.getLayoutBounds().getWidth(); + double viewportWidth = fTimeGraphScrollPane.getViewportBounds().getWidth(); + double hoffset = Math.max(0, contentWidth - viewportWidth) * (hvalue - hmin) / (hmax - hmin); + + /* + * Convert the positions of the left and right edges to timestamps. + */ + long tsStart = paneXPosToTimestamp(hoffset); + long tsEnd = paneXPosToTimestamp(hoffset + viewportWidth); + + return TimeRange.of(tsStart, tsEnd); + } + + public double timestampToPaneXPos(long timestamp) { + TimeRange fullTimeGraphRange = getViewContext().getCurrentTraceFullRange(); + return timestampToPaneXPos(timestamp, fullTimeGraphRange, fNanosPerPixel.get()); + } + + @VisibleForTesting + static double timestampToPaneXPos(long timestamp, TimeRange fullTimeGraphRange, double nanosPerPixel) { + long start = fullTimeGraphRange.getStart(); + long end = fullTimeGraphRange.getEnd(); + + if (timestamp < start) { + throw new IllegalArgumentException(timestamp + " is smaller than trace start time " + start); //$NON-NLS-1$ + } + if (timestamp > end) { + throw new IllegalArgumentException(timestamp + " is greater than trace end time " + end); //$NON-NLS-1$ + } + + double traceDuration = fullTimeGraphRange.getDuration(); + double timeStampRatio = (timestamp - start) / traceDuration; + + long fullTraceWidthInPixels = (long) (traceDuration / nanosPerPixel); + double xPos = fullTraceWidthInPixels * timeStampRatio; + return Math.round(xPos); + } + + public long paneXPosToTimestamp(double x) { + long fullTimeGraphStartTime = getViewContext().getCurrentTraceFullRange().getStart(); + return paneXPosToTimestamp(x, fTimeGraphPane.getWidth(), fullTimeGraphStartTime, fNanosPerPixel.get()); + } + + @VisibleForTesting + static long paneXPosToTimestamp(double x, double totalWidth, long startTimestamp, double nanosPerPixel) { + if (x < 0.0 || totalWidth < 1.0 || x > totalWidth) { + throw new IllegalArgumentException("Invalid position arguments: pos=" + x + ", width=" + totalWidth); + } + + long ts = Math.round(x * nanosPerPixel); + return ts + startTimestamp; + } + + /** + * Get the current vertical position of the timegraph. + * + * @return The corresponding VerticalPosition + */ + VerticalPosition getCurrentVerticalPosition() { + double vvalue = fTimeGraphScrollPane.getVvalue(); + + /* Get the Y position of the top/bottom edges of the pane */ + double vmin = fTimeGraphScrollPane.getVmin(); + double vmax = fTimeGraphScrollPane.getVmax(); + double contentHeight = fTimeGraphPane.getLayoutBounds().getHeight(); + double viewportHeight = fTimeGraphScrollPane.getViewportBounds().getHeight(); + + double vtop = Math.max(0, contentHeight - viewportHeight) * (vvalue - vmin) / (vmax - vmin); + double vbottom = vtop + viewportHeight; + + return new VerticalPosition(vtop, vbottom); + } + + public static int paneYPosToEntryListIndex(double yPos, double entryHeight) { + if (yPos < 0.0 || entryHeight < 0.0) { + throw new IllegalArgumentException(); + } + + return (int) (yPos / entryHeight); + } + + // ------------------------------------------------------------------------ + // Test accessors + // ------------------------------------------------------------------------ + + private volatile @Nullable CountDownLatch fRepaintLatch = null; + + @VisibleForTesting + void prepareWaitForRepaint() { + if (fRepaintLatch != null) { + throw new IllegalStateException("Do not call this method concurrently!"); //$NON-NLS-1$ + } + fRepaintLatch = new CountDownLatch(1); + } + + @VisibleForTesting + boolean waitForRepaint() { + CountDownLatch latch = fRepaintLatch; + boolean done = false; + if (latch == null) { + throw new IllegalStateException("Do not call this method concurrently!"); //$NON-NLS-1$ + } + try { + done = latch.await(100, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + } + if (done) { + fRepaintLatch = null; + } + return done; + } + + /** + * Bypass the redraw thread and do a manual redraw of the current location. + */ + @VisibleForTesting + void paintCurrentLocation() { + TimeRange currentHorizontalPos = getViewContext().getCurrentVisibleTimeRange(); + VerticalPosition currentVerticalPos = getCurrentVerticalPosition(); + paintArea(currentHorizontalPos, currentVerticalPos, true, true, 0); + } + + // could eventually be exposed to the user, as "advanced preferences" + public DebugOptions getDebugOptions() { + return fDebugOptions; + } + + public double getCurrentNanosPerPixel() { + return fNanosPerPixel.get(); + } + + public Pane getTimeGraphPane() { + return fTimeGraphPane; + } + + @VisibleForTesting + ScrollPane getTimeGraphScrollPane() { + return fTimeGraphScrollPane; + } + + @VisibleForTesting + TimeGraphArrowLayer getArrowLayer() { + return fArrowLayer; + } + + @VisibleForTesting + TimeGraphDrawnEventLayer getDrawnEventLayer() { + return fDrawnEventLayer; + } +} diff --git a/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/TimeGraphWidgetTreeArea.java b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/TimeGraphWidgetTreeArea.java new file mode 100644 index 0000000000..0ed83212be --- /dev/null +++ b/tmf/org.lttng.scope.tmf2.views.ui/src/org/lttng/scope/tmf2/views/ui/timeline/widgets/timegraph/TimeGraphWidgetTreeArea.java @@ -0,0 +1,284 @@ +/* + * Copyright (C) 2017 EfficiOS Inc., Alexandre Montplaisir + * + * 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 + */ + +package org.lttng.scope.tmf2.views.ui.timeline.widgets.timegraph; + +import static java.util.Objects.requireNonNull; + +import java.util.List; +import java.util.stream.Collectors; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeElement; +import org.lttng.scope.tmf2.views.core.timegraph.model.render.tree.TimeGraphTreeRender; +import org.lttng.scope.tmf2.views.ui.jfx.JfxUtils; + +import com.sun.javafx.scene.control.skin.TreeViewSkin; +import com.sun.javafx.scene.control.skin.VirtualFlow; + +import javafx.application.Platform; +import javafx.beans.binding.DoubleBinding; +import javafx.beans.property.ObjectProperty; +import javafx.geometry.Insets; +import javafx.geometry.Orientation; +import javafx.scene.control.ScrollBar; +import javafx.scene.control.ScrollPane; +import javafx.scene.control.TreeCell; +import javafx.scene.control.TreeItem; +import javafx.scene.control.TreeView; +import javafx.scene.layout.BorderPane; + +/** + * Extension of {@link TreeView} which exposes some of its components, like + * Scrollbars. + * + * It also supports specifying a static visibility modifier for the scrollbars, + * similar to a {@link ScrollPane}'s bar policy. + * + * This class makes us of some internal, non-API JavaFX objects and methods and + * thus, might break once the codebase moves to a newer version. + * + * @author Alexandre Montplaisir + */ +@SuppressWarnings("restriction") +public class TimeGraphWidgetTreeArea extends BorderPane { + + private final double fEntryHeight; + + private final TreeAreaTreeView fTreeView; + + /** + * Constructor + */ + public TimeGraphWidgetTreeArea(double entryHeight, ObjectProperty<@Nullable ITmfTrace> targetTraceProperty) { + TreeItem treeRoot = new TreeItem<>(); + treeRoot.setExpanded(true); + + TreeAreaTreeView treeView = new TreeAreaTreeView(treeRoot); + treeView.setFixedCellSize(entryHeight); + + /* + * Instead of using the TreeView's scrollbar, whose visibility and size are + * managed internally by the super-class, we will instantiate our own and will + * bind its important properties to the "real" one. + */ + ScrollBar dummyScrollBar = new ScrollBar(); + dummyScrollBar.setOrientation(Orientation.HORIZONTAL); + ScrollBar realHScrollBar = treeView.getHBar(); + dummyScrollBar.valueProperty().bindBidirectional(realHScrollBar.valueProperty()); + dummyScrollBar.visibleAmountProperty().bind(treeView.widthProperty().divide(2)); + + /* Add the "children" to this BorderPane */ + setCenter(treeView); + setBottom(dummyScrollBar); + + treeView.setCellFactory(view -> new TreeAreaTreeViewCell()); + + fEntryHeight = entryHeight; + fTreeView = treeView; + } + + public void clear() { + fTreeView.setRoot(null); + } + + public ScrollBar getVerticalScrollBar() { + return fTreeView.getVBar(); + } + + public DoubleBinding currentHeightProperty() { + return fTreeView.expandedItemCountProperty().multiply((fEntryHeight)); + } + + public void updateTreeContents(TimeGraphTreeRender treeRender) { + TreeItem newRoot = getTreeItemForElement(treeRender.getRootElement()); + newRoot.setExpanded(true); + Platform.runLater(() -> { + fTreeView.setRoot(newRoot); + }); + } + + private static TreeItem getTreeItemForElement(TimeGraphTreeElement element) { + TreeItem treeItem = new TreeItem<>(element.getName()); + List> childItems = element.getChildElements().stream() + .map(treeElem -> getTreeItemForElement(treeElem)) + .collect(Collectors.toList()); + if (!childItems.isEmpty()) { + treeItem.getChildren().addAll(childItems); + } + + // TODO Correctly manage sub-trees being expanded. Disallow it for now. + treeItem.setExpanded(true); + treeItem.addEventHandler(TreeItem.branchCollapsedEvent(), + event -> event.getTreeItem().setExpanded(true)); + + return treeItem; + } + + // ------------------------------------------------------------------------ + // Methods related to the Tree area + // ------------------------------------------------------------------------ + + private static List> getTreeItemNames(TimeGraphTreeRender treeRender) { + return treeRender.getAllTreeElements().stream() + .map(elem -> new TreeItem<>(elem.getName())) + .collect(Collectors.toList()); + } + + // TODO Background could be re-added by salvaging this +// private static Node prepareTreeContents(TimeGraphTreeRender treeRender, ReadOnlyDoubleProperty widthProperty) { +// /* Prepare the tree element objects */ +// List