--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.linuxtools.lttng.ui</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %Bundle-Name
+Bundle-SymbolicName: org.eclipse.linuxtools.lttng.ui;singleton:=true
+Bundle-Version: 0.2.0.qualifier
+Bundle-Activator: org.eclipse.linuxtools.lttng.ui.LTTngUiPlugin
+Bundle-Vendor: %Bundle-Vendor
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.ui.ide,
+ org.eclipse.core.resources,
+ org.eclipse.core.filesystem,
+ org.eclipse.core.runtime,
+ org.eclipse.linuxtools.tmf;bundle-version="0.2.0",
+ org.eclipse.linuxtools.tmf.ui;bundle-version="0.2.0",
+ org.eclipse.linuxtools.lttng;bundle-version="0.2.0"
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Bundle-ActivationPolicy: lazy
+Bundle-Localization: plugin
--- /dev/null
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ plugin.xml,\
+ icons/,\
+ plugin.properties
--- /dev/null
+#Properties file for org.eclipse.linuxtools.lttng.ui
+Bundle-Name = Linux Tracing Toolkit (LTTng) UI (Incubation)
+Bundle-Vendor = Eclipse Linux Tools
+
+# org.eclipse.ui.perspectives
+extension.name.0 = LTTng Perspective
+perspective.name = LTTng
+
+# org.eclipse.ui.views
+extension.name.1 = LTTng Views
+category.name = LTTng
+view.name.0 = Project
+view.name.1 = Control
+view.name.2 = Events
+view.name.3 = Time Frame
+view.name.4 = Control Flow
+view.name.5 = Resources
+view.name.6 = Statistics
+view.name.7 = Histogram
+
+# org.eclipse.ui.newWizards
+extension.name.2 = LTTng New Wizards
+category.name.0 = LTTng
+wizard.name.0 = LTTng Project
+wizard.description.0 = Create an LTTng project
+
+# org.eclipse.core.resources.natures
+extension.name.3 = LTTng Project Nature
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+ <extension
+ id="org,eclipse.linuxtools.lttng.ui.perspective"
+ name="%extension.name.0"
+ point="org.eclipse.ui.perspectives">
+ <perspective
+ class="org.eclipse.linuxtools.lttng.ui.views.PerspectiveFactory"
+ icon="icons/garland32.png"
+ id="org.eclipse.linuxtools.lttng.ui.perspective"
+ name="%perspective.name">
+ </perspective>
+ </extension>
+ <extension
+ id="org.eclipse.linuxtools.lttng.ui.views"
+ name="%extension.name.1"
+ point="org.eclipse.ui.views">
+ <category
+ id="org.eclipse.linuxtools.lttng.ui.views.category"
+ name="%category.name">
+ </category>
+ <view
+ allowMultiple="false"
+ category="org.eclipse.linuxtools.lttng.ui.views.category"
+ class="org.eclipse.linuxtools.lttng.ui.views.project.ProjectView"
+ icon="icons/project_view.gif"
+ id="org.eclipse.linuxtools.lttng.ui.views.project"
+ name="%view.name.0"
+ restorable="true">
+ </view>
+ <view
+ allowMultiple="false"
+ category="org.eclipse.linuxtools.lttng.ui.views.category"
+ class="org.eclipse.linuxtools.lttng.ui.views.control.ControlView"
+ icon="icons/control_view.gif"
+ id="org.eclipse.linuxtools.lttng.ui.views.control"
+ name="%view.name.1"
+ restorable="true">
+ </view>
+ <view
+ allowMultiple="false"
+ category="org.eclipse.linuxtools.lttng.ui.views.category"
+ class="org.eclipse.linuxtools.lttng.ui.views.events.EventsView"
+ icon="icons/events_view.gif"
+ id="org.eclipse.linuxtools.lttng.ui.views.events"
+ name="%view.name.2"
+ restorable="true">
+ </view>
+ <view
+ allowMultiple="false"
+ category="org.eclipse.linuxtools.lttng.ui.views.category"
+ class="org.eclipse.linuxtools.lttng.ui.views.timeframe.TimeFrameView"
+ icon="icons/time_frame_view.gif"
+ id="org.eclipse.linuxtools.lttng.ui.views.timeframe"
+ name="%view.name.3"
+ restorable="true">
+ </view>
+ <view
+ allowMultiple="false"
+ category="org.eclipse.linuxtools.lttng.ui.views.category"
+ class="org.eclipse.linuxtools.lttng.ui.views.controlflow.ControlFlowView"
+ icon="icons/control_flow_view.gif"
+ id="org.eclipse.linuxtools.lttng.ui.views.controlflow"
+ name="%view.name.4"
+ restorable="true">
+ </view>
+ <view
+ allowMultiple="false"
+ category="org.eclipse.linuxtools.lttng.ui.views.category"
+ class="org.eclipse.linuxtools.lttng.ui.views.resources.ResourcesView"
+ icon="icons/resources_view.gif"
+ id="org.eclipse.linuxtools.lttng.ui.views.resources"
+ name="%view.name.5"
+ restorable="true">
+ </view>
+ <view
+ allowMultiple="false"
+ category="org.eclipse.linuxtools.lttng.ui.views.category"
+ class="org.eclipse.linuxtools.lttng.ui.views.statistics.StatisticsView"
+ icon="icons/statistics_view.gif"
+ id="org.eclipse.linuxtools.lttng.ui.views.statistics"
+ name="%view.name.6"
+ restorable="true">
+ </view>
+ <view
+ allowMultiple="false"
+ category="org.eclipse.linuxtools.lttng.ui.views.category"
+ class="org.eclipse.linuxtools.lttng.ui.views.histogram.HistogramView"
+ icon="icons/histogram.gif"
+ id="org.eclipse.linuxtools.lttng.ui.views.histogram"
+ name="%view.name.7"
+ restorable="true">
+ </view>
+ </extension>
+ <extension
+ id="org.eclipse.linuxtools.lttng.wizards.new"
+ name="%extension.name.2"
+ point="org.eclipse.ui.newWizards">
+ <category
+ id="org.eclipse.linuxtools.lttng.ui.wizards.new"
+ name="%category.name.0">
+ </category>
+ <wizard
+ category="org.eclipse.linuxtools.lttng.ui.wizards.new"
+ class="org.eclipse.linuxtools.lttng.ui.views.project.dialogs.NewProjectWizard"
+ descriptionImage="icons/garland16.png"
+ finalPerspective="org.eclipse.linuxtools.lttng.ui.perspective"
+ icon="icons/garland16.png"
+ id="org.eclipse.linuxtools.lttng.ui.views.ui.wizards.newProject"
+ name="%wizard.name.0"
+ project="true">
+ <description>
+ %wizard.description.0
+ </description>
+ </wizard>
+ </extension>
+ <extension
+ id="org.eclipse.linuxtools.lttng.ui.views.project.LTTngProjectNature"
+ name="%extension.name.3"
+ point="org.eclipse.core.resources.natures">
+ <runtime>
+ <run
+ class="org.eclipse.linuxtools.lttng.ui.views.project.LTTngProjectNature">
+ </run>
+ </runtime>
+ </extension>
+ <extension
+ id="org.eclipse.linuxtools.lttng.ui.actionSets"
+ name="LTTng Action Sets"
+ point="org.eclipse.ui.actionSets">
+ <actionSet
+ description="LTTng Action Set"
+ id="org.eclipse.linuxtools.lttng.ui.actionSet"
+ label="LTTng Action Set"
+ visible="true">
+ </actionSet>
+ </extension>
+ <extension
+ id="org.eclipse.linuxtools.lttng.ui.commands"
+ name="LTTng Commands"
+ point="org.eclipse.ui.commands">
+ <category
+ description="LTTng Project Commands"
+ id="org.eclipse.linuxtools.lttng.ui.commands.project.category"
+ name="LTTng Project Commands">
+ </category>
+ <command
+ categoryId="org.eclipse.linuxtools.lttng.ui.commands.project.category"
+ description="Create an LTTng Project"
+ id="org.eclipse.linuxtools.lttng.ui.command.project.new"
+ name="New Project">
+ </command>
+ <command
+ categoryId="org.eclipse.linuxtools.lttng.ui.commands.project.category"
+ description="Open an LTTng Project"
+ id="org.eclipse.linuxtools.lttng.ui.command.project.open"
+ name="Open Project">
+ </command>
+ <command
+ categoryId="org.eclipse.linuxtools.lttng.ui.commands.project.category"
+ description="Close an LTTng Project"
+ id="org.eclipse.linuxtools.lttng.ui.command.project.close"
+ name="Close Project">
+ </command>
+ <command
+ categoryId="org.eclipse.linuxtools.lttng.ui.commands.project.category"
+ description="Rename an LTTng Project"
+ id="org.eclipse.linuxtools.lttng.ui.command.project.rename"
+ name="Rename Project">
+ </command>
+ <command
+ categoryId="org.eclipse.linuxtools.lttng.ui.commands.project.category"
+ description="Delete an LTTng Project"
+ id="org.eclipse.linuxtools.lttng.ui.command.project.delete"
+ name="Delete Project">
+ </command>
+ <command
+ categoryId="org.eclipse.linuxtools.lttng.ui.commands.project.category"
+ description="Import an LTTng Trace"
+ id="org.eclipse.linuxtools.lttng.ui.command.project.trace.import"
+ name="Import Trace">
+ </command>
+ <command
+ categoryId="org.eclipse.linuxtools.lttng.ui.commands.project.category"
+ description="Open an LTTng Trace"
+ id="org.eclipse.linuxtools.lttng.ui.command.project.trace.open"
+ name="Open Trace">
+ </command>
+ <command
+ categoryId="org.eclipse.linuxtools.lttng.ui.commands.project.category"
+ description="Rename an LTTng Trace"
+ id="org.eclipse.linuxtools.lttng.ui.command.project.trace.rename"
+ name="Rename Trace">
+ </command>
+ <command
+ categoryId="org.eclipse.linuxtools.lttng.ui.commands.project.category"
+ description="Delete an LTTng Trace"
+ id="org.eclipse.linuxtools.lttng.ui.command.project.trace.delete"
+ name="Delete Trace">
+ </command>
+ <command
+ categoryId="org.eclipse.linuxtools.lttng.ui.commands.project.category"
+ description="Create an LTTng Experiment"
+ id="org.eclipse.linuxtools.lttng.ui.command.project.experiment.new"
+ name="New Experiment">
+ </command>
+ <command
+ categoryId="org.eclipse.linuxtools.lttng.ui.commands.project.category"
+ description="Select LTTng Traces"
+ id="org.eclipse.linuxtools.lttng.ui.command.project.experiment.select"
+ name="Select Traces">
+ </command>
+ <command
+ categoryId="org.eclipse.linuxtools.lttng.ui.commands.project.category"
+ description="Open an LTTng Experiment"
+ id="org.eclipse.linuxtools.lttng.ui.command.project.experiment.open"
+ name="Open Experiment">
+ </command>
+ <command
+ categoryId="org.eclipse.linuxtools.lttng.ui.commands.project.category"
+ description="Rename an LTTng Experiment"
+ id="org.eclipse.linuxtools.lttng.ui.command.project.experiment.rename"
+ name="Rename Experiment">
+ </command>
+ <command
+ categoryId="org.eclipse.linuxtools.lttng.ui.commands.project.category"
+ description="Delete an LTTng Experiment"
+ id="org.eclipse.linuxtools.lttng.ui.command.project.experiment.delete"
+ name="Delete Experiment">
+ </command>
+ <command
+ categoryId="org.eclipse.linuxtools.lttng.ui.commands.project.category"
+ description="Refresh View"
+ id="org.eclipse.linuxtools.lttng.ui.command.project.refresh"
+ name="Refresh View">
+ </command>
+ </extension>
+ <extension
+ id="org.eclipse.linuxtools.lttng.ui.menus"
+ name="LTTng Menus"
+ point="org.eclipse.ui.menus">
+ <menuContribution
+ locationURI="popup:org.eclipse.linuxtools.lttng.ui.views.project?after=additions">
+ <command
+ commandId="org.eclipse.linuxtools.lttng.ui.command.project.new"
+ icon="icons/garland16.png"
+ id="org.eclipse.linuxtools.lttng.ui.menu.popup.project.new"
+ label="New Project"
+ style="push">
+ </command>
+ <command
+ commandId="org.eclipse.linuxtools.lttng.ui.command.project.open"
+ id="org.eclipse.linuxtools.lttng.ui.menu.popup.project.open"
+ label="Open Project"
+ style="push">
+ </command>
+ <command
+ commandId="org.eclipse.linuxtools.lttng.ui.command.project.close"
+ id="org.eclipse.linuxtools.lttng.ui.menu.popup.project.close"
+ label="Close Project"
+ style="push">
+ </command>
+ <!-- command
+ commandId="org.eclipse.linuxtools.lttng.ui.command.project.rename"
+ id="org.eclipse.linuxtools.lttng.ui.menu.popup.project.rename"
+ label="Rename Project"
+ style="push">
+ </command -->
+ <command
+ commandId="org.eclipse.linuxtools.lttng.ui.command.project.delete"
+ id="org.eclipse.linuxtools.lttng.ui.menu.popup.project.delete"
+ label="Delete Project"
+ style="push">
+ </command>
+ <separator
+ name="org.eclipse.linuxtools.lttng.ui.menu.popup.project.separator1"
+ visible="true">
+ </separator>
+ <command
+ commandId="org.eclipse.linuxtools.lttng.ui.command.project.experiment.new"
+ id="org.eclipse.linuxtools.lttng.ui.menu.popup.project.experiment.new"
+ label="New Experiment"
+ style="push">
+ </command>
+ <command
+ commandId="org.eclipse.linuxtools.lttng.ui.command.project.experiment.select"
+ id="org.eclipse.linuxtools.lttng.ui.menu.popup.project.experiment.select"
+ label="Select Traces"
+ style="push">
+ </command>
+ <command
+ commandId="org.eclipse.linuxtools.lttng.ui.command.project.experiment.open"
+ id="org.eclipse.linuxtools.lttng.ui.menu.popup.project.experiment.open"
+ label="Open Experiment"
+ style="push">
+ </command>
+ <!-- command
+ commandId="org.eclipse.linuxtools.lttng.ui.command.project.experiment.rename"
+ id="org.eclipse.linuxtools.lttng.ui.menu.popup.project.experiment.rename"
+ label="Rename Experiment"
+ style="push">
+ </command -->
+ <command
+ commandId="org.eclipse.linuxtools.lttng.ui.command.project.experiment.delete"
+ id="org.eclipse.linuxtools.lttng.ui.menu.popup.project.experiment.delete"
+ label="Delete Experiment"
+ style="push">
+ </command>
+ <separator
+ name="org.eclipse.linuxtools.lttng.ui.menu.popup.project.separator2"
+ visible="true">
+ </separator>
+ <command
+ commandId="org.eclipse.linuxtools.lttng.ui.command.project.trace.import"
+ id="org.eclipse.linuxtools.lttng.ui.menu.popup.project.trace.import"
+ label="Import Traces"
+ style="push">
+ </command>
+ <!-- command
+ commandId="org.eclipse.linuxtools.lttng.ui.command.project.trace.open"
+ id="org.eclipse.linuxtools.lttng.ui.menu.popup.project.trace.open"
+ label="Open Trace"
+ style="push">
+ </command -->
+ <!-- command
+ commandId="org.eclipse.linuxtools.lttng.ui.command.project.trace.rename"
+ id="org.eclipse.linuxtools.lttng.ui.menu.popup.project.trace.rename"
+ label="Rename Trace"
+ style="push">
+ </command -->
+ <command
+ commandId="org.eclipse.linuxtools.lttng.ui.command.project.trace.delete"
+ id="org.eclipse.linuxtools.lttng.ui.menu.popup.project.trace.delete"
+ label="Delete Trace"
+ style="push">
+ </command>
+ <separator
+ name="org.eclipse.linuxtools.lttng.ui.menu.popup.project.separator3"
+ visible="true">
+ </separator>
+ <command
+ commandId="org.eclipse.linuxtools.lttng.ui.command.project.refresh"
+ id="org.eclipse.linuxtools.lttng.ui.menu.popup.project.refresh"
+ label="Refresh View"
+ style="push">
+ </command>
+ </menuContribution>
+ </extension>
+ <extension
+ id="org.eclipse.linuxtools.lttng.ui.handlers"
+ name="LTTng Command Handlers"
+ point="org.eclipse.ui.handlers">
+ <handler
+ class="org.eclipse.linuxtools.lttng.ui.views.project.handlers.NewProjectHandler"
+ commandId="org.eclipse.linuxtools.lttng.ui.command.project.new">
+ </handler>
+ <handler
+ class="org.eclipse.linuxtools.lttng.ui.views.project.handlers.OpenProjectHandler"
+ commandId="org.eclipse.linuxtools.lttng.ui.command.project.open">
+ </handler>
+ <handler
+ class="org.eclipse.linuxtools.lttng.ui.views.project.handlers.CloseProjectHandler"
+ commandId="org.eclipse.linuxtools.lttng.ui.command.project.close">
+ </handler>
+ <handler
+ class="org.eclipse.linuxtools.lttng.ui.views.project.handlers.RenameProjectHandler"
+ commandId="org.eclipse.linuxtools.lttng.ui.command.project.rename">
+ </handler>
+ <handler
+ class="org.eclipse.linuxtools.lttng.ui.views.project.handlers.DeleteProjectHandler"
+ commandId="org.eclipse.linuxtools.lttng.ui.command.project.delete">
+ </handler>
+ <handler
+ class="org.eclipse.linuxtools.lttng.ui.views.project.handlers.ImportTraceHandler"
+ commandId="org.eclipse.linuxtools.lttng.ui.command.project.trace.import">
+ </handler>
+ <handler
+ class="org.eclipse.linuxtools.lttng.ui.views.project.handlers.OpenTraceHandler"
+ commandId="org.eclipse.linuxtools.lttng.ui.command.project.trace.open">
+ </handler>
+ <handler
+ class="org.eclipse.linuxtools.lttng.ui.views.project.handlers.RenameTraceHandler"
+ commandId="org.eclipse.linuxtools.lttng.ui.command.project.trace.rename">
+ </handler>
+ <handler
+ class="org.eclipse.linuxtools.lttng.ui.views.project.handlers.DeleteTraceHandler"
+ commandId="org.eclipse.linuxtools.lttng.ui.command.project.trace.delete">
+ </handler>
+ <handler
+ class="org.eclipse.linuxtools.lttng.ui.views.project.handlers.NewExperimentHandler"
+ commandId="org.eclipse.linuxtools.lttng.ui.command.project.experiment.new">
+ </handler>
+ <handler
+ class="org.eclipse.linuxtools.lttng.ui.views.project.handlers.SelectTracesHandler"
+ commandId="org.eclipse.linuxtools.lttng.ui.command.project.experiment.select">
+ </handler>
+ <handler
+ class="org.eclipse.linuxtools.lttng.ui.views.project.handlers.OpenExperimentHandler"
+ commandId="org.eclipse.linuxtools.lttng.ui.command.project.experiment.open">
+ </handler>
+ <handler
+ class="org.eclipse.linuxtools.lttng.ui.views.project.handlers.RenameExperimentHandler"
+ commandId="org.eclipse.linuxtools.lttng.ui.command.project.experiment.rename">
+ </handler>
+ <handler
+ class="org.eclipse.linuxtools.lttng.ui.views.project.handlers.DeleteExperimentHandler"
+ commandId="org.eclipse.linuxtools.lttng.ui.command.project.experiment.delete">
+ </handler>
+ <handler
+ class="org.eclipse.linuxtools.lttng.ui.views.project.handlers.RefreshHandler"
+ commandId="org.eclipse.linuxtools.lttng.ui.command.project.refresh">
+ </handler>
+ </extension>
+
+</plugin>
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class LTTngUiPlugin extends AbstractUIPlugin {
+
+ // The plug-in ID
+ public static final String PLUGIN_ID = "org.eclipse.linuxtools.lttng.ui";
+
+ // The shared instance
+ private static LTTngUiPlugin plugin;
+
+ /**
+ * The constructor
+ */
+ public LTTngUiPlugin() {
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ TraceDebug.init();
+ plugin = this;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static LTTngUiPlugin getDefault() {
+ return plugin;
+ }
+
+}
--- /dev/null
+package org.eclipse.linuxtools.lttng.ui;\r
+\r
+import java.text.SimpleDateFormat;\r
+import java.util.Date;\r
+\r
+import org.eclipse.core.runtime.ILog;\r
+import org.eclipse.core.runtime.IStatus;\r
+import org.eclipse.core.runtime.Platform;\r
+import org.eclipse.core.runtime.Plugin;\r
+import org.eclipse.core.runtime.Status;\r
+\r
+public class TraceDebug {\r
+ static boolean DEBUG = false;\r
+ static boolean INFO = false;\r
+ static boolean WARN = false;\r
+\r
+ private static Plugin plugin = LTTngUiPlugin.getDefault();\r
+ private static String pluginID = LTTngUiPlugin.PLUGIN_ID;\r
+ private static SimpleDateFormat stimeformat = new SimpleDateFormat(\r
+ "HH:mm:ss:SSS");\r
+\r
+ public static void init() {\r
+ // Update Trace configuration options\r
+ String debugTrace = Platform.getDebugOption(pluginID + "/debug");\r
+ String infoTrace = Platform.getDebugOption(pluginID + "/info");\r
+ String warnTrace = Platform.getDebugOption(pluginID + "/warn");\r
+\r
+ if (debugTrace != null) {\r
+ DEBUG = (new Boolean(debugTrace)).booleanValue();\r
+ }\r
+\r
+ if (infoTrace != null) {\r
+ INFO = (new Boolean(infoTrace)).booleanValue();\r
+ }\r
+\r
+ if (warnTrace != null) {\r
+ WARN = (new Boolean(warnTrace)).booleanValue();\r
+ }\r
+ }\r
+\r
+ public static void info(String message) {\r
+ if (INFO) {\r
+ ILog logger = plugin.getLog();\r
+ logger.log(new Status(IStatus.INFO, LTTngUiPlugin.PLUGIN_ID,\r
+ IStatus.OK, message, null));\r
+ }\r
+ }\r
+\r
+ public static void warn(String message) {\r
+ if (WARN) {\r
+ ILog logger = plugin.getLog();\r
+ logger.log(new Status(IStatus.WARNING, LTTngUiPlugin.PLUGIN_ID,\r
+ IStatus.WARNING, message, null));\r
+ }\r
+ }\r
+\r
+ public static void debug(String message) {\r
+ if (DEBUG) {\r
+ String location = getCallingLocation();\r
+ System.out.println(location + "\n\t-> " + message);\r
+\r
+ }\r
+ }\r
+\r
+ public static void debug(String message, int additionalStackLines) {\r
+ if (DEBUG) {\r
+ String location = getCallingLocation(additionalStackLines);\r
+ System.out.println(location + "\n\t-> " + message);\r
+ }\r
+ }\r
+\r
+ public static void throwException(String message) {\r
+ if (DEBUG) {\r
+ try {\r
+ triggerException(message);\r
+ } catch (Exception e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+ }\r
+\r
+ private static void triggerException(String message) throws Exception {\r
+ throw new Exception(message);\r
+ }\r
+\r
+ private static String getCallingLocation() {\r
+ StringBuilder sb = new StringBuilder();\r
+ sb.append(trace(Thread.currentThread().getStackTrace(), 4));\r
+ sb.append("\n" + trace(Thread.currentThread().getStackTrace(), 3));\r
+ return sb.toString();\r
+ }\r
+\r
+ private static String getCallingLocation(int numOfStackLines) {\r
+ int stackCalledFromIdx = 3;\r
+ int earliestRequested = numOfStackLines > 0 ? stackCalledFromIdx\r
+ + numOfStackLines : stackCalledFromIdx;\r
+ StringBuilder sb = new StringBuilder();\r
+ for (int i = earliestRequested; i >= stackCalledFromIdx; i--) {\r
+ sb.append(trace(Thread.currentThread().getStackTrace(), i) + "\n");\r
+ }\r
+ return sb.toString();\r
+ }\r
+\r
+ private static String trace(StackTraceElement e[], int level) {\r
+ if (e != null) {\r
+ level = level >= e.length ? e.length - 1 : level;\r
+ StackTraceElement s = e[level];\r
+ if (s != null) {\r
+ String simpleClassName = s.getClassName();\r
+ String[] clsNameSegs = simpleClassName.split("\\.");\r
+ if (clsNameSegs.length > 0)\r
+ simpleClassName = clsNameSegs[clsNameSegs.length - 1];\r
+ return stimeformat.format(new Date()) + " " + simpleClassName\r
+ + "." + s.getLineNumber() + "." + s.getMethodName();\r
+ }\r
+ }\r
+\r
+ return null;\r
+ }\r
+\r
+ public static boolean isDEBUG() {\r
+ return DEBUG;\r
+ }\r
+\r
+ public static boolean isINFO() {\r
+ return INFO;\r
+ }\r
+\r
+ public static boolean isWARN() {\r
+ return WARN;\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.model.trange;
+
+/**
+ * The common component of the Composite related to time-range events its
+ * components or containers
+ *
+ * @author alvaro
+ *
+ */
+public interface ITimeRangeComponent {
+
+ public long getStartTime();
+
+ public void setStartTime(long startTime);
+
+ public long getStopTime();
+
+ public void setStopTime(long endTime);
+
+ public ITimeRangeComponent getEventParent();
+
+ public String getName();
+
+ /**
+ * Flag to indicate if this Time Range is visible within the GUI, May not be
+ * visible if the duration can not be represented in one pixel
+ *
+ * @return true if visible i.e. represented at least in one pixel
+ */
+ public boolean isVisible();
+
+}
--- /dev/null
+package org.eclipse.linuxtools.lttng.ui.model.trange;
+
+import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITmfTimeAnalysisEntry;
+
+public interface ItemContainer<T extends ITmfTimeAnalysisEntry> {
+
+ /**
+ * Interface to add resources.
+ *
+ * @param process
+ */
+ public abstract void addItem(T newItem);
+
+ // ========================================================================
+ // Methods
+ // ========================================================================
+ /**
+ * Request a unique ID
+ *
+ * @return Integer
+ */
+ public abstract Integer getUniqueId();
+
+ /**
+ * This method is intended for read only purposes in order to keep the
+ * internal data structure in Synch
+ *
+ * @return
+ */
+ public abstract T[] readItems();
+
+ /**
+ * Clear the children information for resources related to a specific trace
+ * e.g. just before refreshing data with a new time range
+ *
+ * @param traceId
+ */
+ public abstract void clearChildren();
+
+ /**
+ * Clear all resources items e.g. when a new experiment is selected
+ */
+ public abstract void clearItems();
+
+ /**
+ * Remove the resources related to a specific trace e.g. during trace
+ * removal
+ *
+ * @param traceId
+ */
+ public abstract void removeItems(String traceId);
+
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.model.trange;
+
+
+/**
+ * @author alvaro
+ *
+ */
+public abstract class TimeRangeComponent implements ITimeRangeComponent {
+
+ // ========================================================================
+ // Data
+ // =======================================================================
+ protected Long startTime = 0L;
+ protected Long stopTime = Long.MAX_VALUE;
+ protected TimeRangeComposite eventParent = null;
+ private boolean visible = true;
+
+
+
+ // ========================================================================
+ // Constructor
+ // =======================================================================
+ public TimeRangeComponent(Long stime, Long etime,
+ TimeRangeComposite eventParent) {
+ this.startTime = stime;
+ this.stopTime = etime;
+ this.eventParent = eventParent;
+ }
+
+ // ========================================================================
+ // Methods
+ // =======================================================================
+ /**
+ * This method shall not be used to estimate the starting drawing point of
+ * the time range-event. see interface method getTime(). However this method
+ * can be used to retrieve the tool tip information where we need to reflect
+ * that the actual start of this event is unknown
+ *
+ * @param time
+ */
+ public long getStartTime() {
+ return startTime.longValue();
+ }
+
+ public void setStartTime(long time) {
+ if (time > -1) {
+ startTime = time;
+ }
+ }
+
+ public long getStopTime() {
+ return stopTime.longValue();
+ }
+
+ public void setStopTime(long stopTime) {
+ if (stopTime > -1) {
+ this.stopTime = stopTime;
+ }
+ }
+
+ public ITimeRangeComponent getEventParent() {
+ return eventParent;
+ }
+
+ public void setEventParent(TimeRangeComposite eventParent) {
+ this.eventParent = eventParent;
+ }
+
+ public abstract String getName();
+
+
+ public void setVisible(boolean visible) {
+ this.visible = visible;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.linuxtools.lttng.ui.model.trange.ITimeRangeComponent#isVisible()
+ */
+ public boolean isVisible() {
+ return visible;
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.model.trange;
+
+import java.util.Vector;
+
+import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITmfTimeAnalysisEntry;
+
+public class TimeRangeComposite extends TimeRangeComponent implements
+ITmfTimeAnalysisEntry {
+
+ // ========================================================================
+ // Data
+ // =======================================================================
+ /**
+ * Type of Composites or Containers
+ * <p>
+ * PROPERTY: Refers to a sub-composite of a RESOURCE or a PROCESS e.g the
+ * cpu which can vary over time and can have time range events associated to
+ * it, and at the same time PROPERTY is associated to a Composite parent
+ * like a PROCESS
+ * </p>
+ * <p>
+ * PROCESS: A composite of time range events representing a Process
+ * </p>
+ * <p>
+ * RESOURCE: A composite of time range events representing a resource i.g.
+ * irq, softIrq, trap, bdev, cpu
+ * </p>
+ *
+ * @author alvaro
+ *
+ */
+ public static enum CompositeType {
+ UNKNOWN, PROPERTY, PROCESS, RESOURCE
+ }
+
+ protected final Vector<TimeRangeComponent> ChildEventLeafs = new Vector<TimeRangeComponent>();
+ protected final Vector<TimeRangeComponent> ChildEventComposites = new Vector<TimeRangeComponent>();
+ protected Integer id = 0;
+ protected String name;
+ protected String groupName = "";
+ protected String className = "";
+ protected CompositeType contType = CompositeType.UNKNOWN;
+ protected Long next_good_time = -1L;
+ /*Time of first event which trigger the creation of this local resource */
+ protected Long insertionTime = -1L;
+
+ // ========================================================================
+ // Constructors
+ // =======================================================================
+ public TimeRangeComposite(Integer id, Long stime, Long etime, String name,
+ CompositeType type, long insertionTime) {
+ super(stime, etime, null);
+ this.id = id;
+ this.name = name;
+ contType = type;
+ this.insertionTime = insertionTime;
+ // Adjust the first good drawing position to the event time creating this resource
+ next_good_time = insertionTime;
+ }
+
+ public TimeRangeComposite(Integer id, Long stime, Long etime, String name,
+ String groupName, String className, CompositeType type,
+ long insertionTime) {
+ this(id, stime, etime, name, type, insertionTime);
+ this.groupName = groupName;
+ this.className = className;
+ }
+
+ // ========================================================================
+ // Methods
+ // =======================================================================
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeComponent#getName()
+ */
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @param name
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.
+ * ITmfTimeAnalysisEntry#getGroupName()
+ */
+ public String getGroupName() {
+ return groupName;
+ }
+
+ /**
+ * @param groupName
+ */
+ public void setGroupName(String groupName) {
+ this.groupName = groupName;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.
+ * ITmfTimeAnalysisEntry#getId()
+ */
+ public int getId() {
+ return id;
+ }
+
+ /**
+ * @param id
+ */
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ /**
+ * @return
+ */
+ public String getClassName() {
+ return className;
+ }
+
+ /**
+ * @param className
+ */
+ public void setClassName(String className) {
+ this.className = className;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.
+ * ITmfTimeAnalysisEntry#getTraceEvents()
+ */
+ @SuppressWarnings("unchecked")
+ public Vector<TimeRangeComponent> getTraceEvents() {
+ return ChildEventLeafs;
+ }
+
+ /**
+ * @return
+ */
+ public Vector<TimeRangeComponent> getChildEventComposites() {
+ return ChildEventComposites;
+ }
+
+ /**
+ * Represents the time where the next time range can start the drawing i.e.
+ * right after previous time range.
+ *
+ * @return
+ */
+ public long getNext_good_time() {
+ return next_good_time;
+ }
+
+ /**
+ * Represents the time where the next time range can start the drawing i.e.
+ * right after previous time range.
+ *
+ * @param nextGoodTime
+ */
+ public void setNext_good_time(long nextGoodTime) {
+ next_good_time = nextGoodTime;
+ }
+
+ /**
+ * Reset this resource to the construction state
+ */
+ public void reset() {
+ getChildEventComposites().clear();
+ getTraceEvents().clear();
+ next_good_time = insertionTime;
+ }
+
+ /**
+ * Event Time reflecting the creation of this local resource e.g. at Reception of Fork, etc.
+ *
+ * @return
+ */
+ public long getInsertionTime() {
+ return insertionTime;
+ }
+}
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2009 Ericsson\r
+ * \r
+ * All rights reserved. This program and the accompanying materials are\r
+ * made available under the terms of the Eclipse Public License v1.0 which\r
+ * accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ * \r
+ * Contributors:\r
+ * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation\r
+ *******************************************************************************/\r
+\r
+package org.eclipse.linuxtools.lttng.ui.model.trange;\r
+\r
+import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITimeEvent;\r
+import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITmfTimeAnalysisEntry;\r
+\r
+/**\r
+ * @author alvaro\r
+ * \r
+ */\r
+public class TimeRangeEvent extends TimeRangeComponent implements ITimeEvent {\r
+ // =======================================================================\r
+ // Data\r
+ // =======================================================================\r
+ TimeRangeComposite parent = null;\r
+\r
+ public static enum Type {\r
+ UNKNOWN, PROPERTY, PROCESS_MODE, BDEV_MODE, TRAP_MODE, SOFT_IRQ_MODE, IRQ_MODE, CPU_MODE\r
+ }\r
+\r
+ protected Type eventType = Type.UNKNOWN;\r
+ protected String stateMode = "";\r
+\r
+ // =======================================================================\r
+ // Constructors\r
+ // =======================================================================\r
+ /**\r
+ * @param stime\r
+ * Event Start Time (may be unknown)\r
+ * @param etime\r
+ * Event EndTime (may be unknown)\r
+ * @param eventParent\r
+ * @param type\r
+ * @param duration\r
+ */\r
+ public TimeRangeEvent(Long stime, Long etime,\r
+ TimeRangeComposite eventParent, Type type, String stateMode) {\r
+ super(stime, etime, eventParent);\r
+\r
+ this.eventType = type;\r
+ this.stateMode = stateMode;\r
+ }\r
+\r
+ // =======================================================================\r
+ // Methods\r
+ // =======================================================================\r
+ \r
+ // @Override\r
+ /*\r
+ * (non-Javadoc)\r
+ * \r
+ * @see\r
+ * org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITimeEvent#getTime\r
+ * ()\r
+ */\r
+ public long getTime() {\r
+ // The value provided by this method is used to start drawing the\r
+ // time-range,\r
+ // so a null value shall not be provided.\r
+ // If the actual start time is unknown then use the start of the Trace\r
+ // as the\r
+ // starting reference point.\r
+ if (startTime == null) {\r
+ return eventParent.getStartTime();\r
+ }\r
+ return startTime;\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * \r
+ * @see\r
+ * org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITimeEvent#getEntry\r
+ * ()\r
+ */\r
+ public ITmfTimeAnalysisEntry getEntry() {\r
+ return parent;\r
+ }\r
+\r
+ /**\r
+ * return the duration between end and start time , if the start time or end\r
+ * time are unknown, use the Trace start and End times to estimate it, this\r
+ * value will be used to draw the time range and need to provide a valid\r
+ * time width.\r
+ * \r
+ * @return the duration\r
+ */\r
+ /*\r
+ * (non-Javadoc)\r
+ * \r
+ * @seeorg.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITimeEvent#\r
+ * getDuration()\r
+ */\r
+ public long getDuration() {\r
+ long duration = -1;\r
+ long endT = (stopTime == null) ? parent.getStopTime() : stopTime;\r
+ long startT = (startTime == null) ? parent.getStartTime() : startTime;\r
+\r
+ if (endT > startT) {\r
+ return stopTime - startTime;\r
+ }\r
+ return duration;\r
+ }\r
+\r
+ /**\r
+ * @return\r
+ */\r
+ public String getStateMode() {\r
+ return stateMode;\r
+ }\r
+\r
+ /**\r
+ * @param stateMode\r
+ */\r
+ public void setStateMode(String stateMode) {\r
+ if (stateMode != null) {\r
+ this.stateMode = stateMode;\r
+ }\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * \r
+ * @see org.eclipse.linuxtools.lttng.ui.model.ITimeRangeComponent#getName()\r
+ */\r
+ @Override\r
+ public String getName() {\r
+ return stateMode;\r
+ }\r
+\r
+ /**\r
+ * @return\r
+ */\r
+ public Type getEventType() {\r
+ return eventType;\r
+ }\r
+\r
+ /**\r
+ * @param eventType\r
+ */\r
+ public void setEventType(Type eventType) {\r
+ this.eventType = eventType;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2009 Ericsson\r
+ * \r
+ * All rights reserved. This program and the accompanying materials are\r
+ * made available under the terms of the Eclipse Public License v1.0 which\r
+ * accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ * \r
+ * Contributors:\r
+ * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation\r
+ *******************************************************************************/\r
+package org.eclipse.linuxtools.lttng.ui.model.trange;\r
+\r
+public class TimeRangeEventProcess extends TimeRangeComposite implements\r
+ Comparable<TimeRangeEventProcess> {\r
+ // ========================================================================\r
+ // Data\r
+ // =======================================================================\r
+ // GUI information\r
+ private Long pid = 0L;\r
+ private Long tgid = 0L;\r
+ private Long ppid = 0L;\r
+ private Long creationTime = 0L;\r
+ private String traceID = "";\r
+ private String processType = "User"; // Kernel or user thread\r
+ private Long cpu = 0L;\r
+ private String brand = "";\r
+\r
+ // ========================================================================\r
+ // Constructor\r
+ // =======================================================================\r
+ /**\r
+ * @param id\r
+ * @param name\r
+ * @param sTime\r
+ * normally set to the Trace start time\r
+ * @param stopTime\r
+ * normally set to the Trace end time\r
+ * @param groupName\r
+ * @param className\r
+ */\r
+ public TimeRangeEventProcess(int id, String name, long startTime,\r
+ long stopTime, String groupName, String className, Long cpu,\r
+ long insertionTime) {\r
+\r
+ super(id, startTime, stopTime, name, CompositeType.PROCESS,\r
+ insertionTime);\r
+ this.cpu = cpu;\r
+ }\r
+\r
+ // ========================================================================\r
+ // Methods\r
+ // =======================================================================\r
+ \r
+ \r
+ /**\r
+ * Interface to add children to this process\r
+ * \r
+ * @param newEvent\r
+ */\r
+ public void addChildren(TimeRangeEvent newEvent) {\r
+ if ((newEvent != null)) {\r
+ this.ChildEventLeafs.add(newEvent);\r
+ }\r
+ }\r
+ \r
+ /**\r
+ * @return\r
+ */\r
+ public Long getPid() {\r
+ return pid;\r
+ }\r
+\r
+ /**\r
+ * @param pid\r
+ */\r
+ public void setPid(Long pid) {\r
+ this.pid = pid;\r
+ }\r
+\r
+ /**\r
+ * @return\r
+ */\r
+ public Long getTgid() {\r
+ return tgid;\r
+ }\r
+\r
+ /**\r
+ * @param tgid\r
+ */\r
+ public void setTgid(Long tgid) {\r
+ this.tgid = tgid;\r
+ }\r
+\r
+ /**\r
+ * @return\r
+ */\r
+ public Long getPpid() {\r
+ return ppid;\r
+ }\r
+\r
+ /**\r
+ * @param ppid\r
+ */\r
+ public void setPpid(Long ppid) {\r
+ this.ppid = ppid;\r
+ }\r
+\r
+ /**\r
+ * @return\r
+ */\r
+ public Long getCreationTime() {\r
+ return creationTime;\r
+ }\r
+\r
+ /**\r
+ * @param creationTime\r
+ */\r
+ public void setCreationTime(Long creationTime) {\r
+ this.creationTime = creationTime;\r
+ }\r
+\r
+ /**\r
+ * @return\r
+ */\r
+ public String getTraceID() {\r
+ return traceID;\r
+ }\r
+\r
+ /**\r
+ * @param traceID\r
+ */\r
+ public void setTraceID(String traceID) {\r
+ if (traceID != null) {\r
+ this.traceID = traceID;\r
+ } else {\r
+ this.traceID = "";\r
+ }\r
+ }\r
+\r
+ /**\r
+ * @return\r
+ */\r
+ public String getProcessType() {\r
+ return processType;\r
+ }\r
+\r
+ /**\r
+ * @param processType\r
+ */\r
+ public void setProcessType(String processType) {\r
+ if (processType != null) {\r
+ this.processType = processType;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * @return\r
+ */\r
+ public Long getCpu() {\r
+ return cpu;\r
+ }\r
+\r
+ /**\r
+ * @param cpu\r
+ */\r
+ public void setCpu(Long cpu) {\r
+ if (cpu != null) {\r
+ this.cpu = cpu;\r
+ } else {\r
+ cpu = 0L;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * @return\r
+ */\r
+ public String getBrand() {\r
+ return brand;\r
+ }\r
+\r
+ /**\r
+ * @param brand\r
+ */\r
+ public void setBrand(String brand) {\r
+ if (brand != null) {\r
+ this.brand = brand;\r
+ } else {\r
+ brand = "";\r
+ }\r
+ }\r
+ \r
+ /*\r
+ * (non-Javadoc)\r
+ * \r
+ * @see java.lang.Comparable#compareTo(java.lang.Object)\r
+ */\r
+ public int compareTo(TimeRangeEventProcess process) {\r
+ if (process != null) {\r
+ int result = 0;\r
+ // Compare by trace first\r
+ String anotherTraceId = process.getTraceID();\r
+ result = traceID.compareTo(anotherTraceId);\r
+ if (result != 0) {\r
+ return result;\r
+ }\r
+\r
+ // Then by CPU\r
+ Long anotherCpu = process.getCpu();\r
+ result = cpu.compareTo(anotherCpu);\r
+ if (result != 0) {\r
+ return result;\r
+ }\r
+\r
+ // finally Compare by pid\r
+ Long anotherPid = process.getPid();\r
+ return pid.compareTo(anotherPid);\r
+ }\r
+\r
+ return 0;\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2009 Ericsson\r
+ * \r
+ * All rights reserved. This program and the accompanying materials are\r
+ * made available under the terms of the Eclipse Public License v1.0 which\r
+ * accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ * \r
+ * Contributors:\r
+ * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation\r
+ *******************************************************************************/\r
+package org.eclipse.linuxtools.lttng.ui.model.trange;\r
+\r
+import org.eclipse.linuxtools.lttng.state.model.LttngTraceState;\r
+\r
+/**\r
+ * @author alvaro\r
+ * \r
+ */\r
+public abstract class TimeRangeEventResource extends TimeRangeComposite\r
+ implements\r
+ Comparable<TimeRangeEventResource> {\r
+\r
+ // ========================================================================\r
+ // Data\r
+ // =======================================================================\r
+ public static enum ResourceTypes {\r
+ UNKNOWN, IRQ, TRAP, SOFT_IRQ, BDEV, CPU\r
+ }\r
+\r
+ private ResourceTypes type = ResourceTypes.UNKNOWN;\r
+ private Long resourceId = null;\r
+\r
+ // ========================================================================\r
+ // Constructor\r
+ // =======================================================================\r
+ /**\r
+ * Constructor<br>\r
+ * \r
+ * @param newId Id used by the UI\r
+ * @param newStartTime normally set to the Trace start time\r
+ * @param newStopTime normally set to the Trace end time\r
+ * @param newName the name of this resource\r
+ * @param newGroupName the group name of this resource. Should be same as the traceId\r
+ * @param newClassName the classname of this resource.\r
+ * @param newType the type of the resource, as defined in the ResourceTypes enum\r
+ * @param newResourceId the resourceId, unique id identifying this resource \r
+ * \r
+ */\r
+ public TimeRangeEventResource(int newId, long newStartTime,\r
+ long newStopTime, String newName, String newGroupName,\r
+ String newClassName, ResourceTypes newType, Long newResourceId,\r
+ long insertionTime) {\r
+\r
+ super(newId, newStartTime, newStopTime, newName, newGroupName,\r
+ newClassName, CompositeType.RESOURCE, insertionTime);\r
+\r
+ type = newType;\r
+ resourceId = newResourceId;\r
+ }\r
+\r
+ // ========================================================================\r
+ // Methods\r
+ // =======================================================================\r
+\r
+ /**\r
+ * Interface to add children to this resource\r
+ * \r
+ * @param newEvent\r
+ */\r
+ public void addChildren(TimeRangeEvent newEvent) {\r
+ if ((newEvent != null)) {\r
+ this.ChildEventLeafs.add(newEvent);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * @return\r
+ */\r
+ public Long getResourceId() {\r
+ return resourceId;\r
+ }\r
+\r
+ /**\r
+ * @param newResId\r
+ */\r
+ public void setResourceId(Long newResId) {\r
+ this.resourceId = newResId;\r
+ }\r
+\r
+ /**\r
+ * @return\r
+ */\r
+ public ResourceTypes getType() {\r
+ return type;\r
+ }\r
+\r
+ /**\r
+ * @param type\r
+ */\r
+ public void setType(ResourceTypes type) {\r
+ this.type = type;\r
+ }\r
+\r
+ /**\r
+ * Getter for traceId.<br>\r
+ * Note : traceId and groupName are the same for EventResource\r
+ * \r
+ * @return String\r
+ */\r
+ public String getTraceId() {\r
+ return groupName;\r
+ }\r
+\r
+ /**\r
+ * Getter for traceId.<br>\r
+ * Note : traceId and groupName are the same for EventResource\r
+ * \r
+ * @return String\r
+ */\r
+ public void setTraceId(String traceId) {\r
+ this.groupName = traceId;\r
+ }\r
+\r
+ // @Override\r
+ /*\r
+ * (non-Javadoc)\r
+ * \r
+ * @see java.lang.Object#toString()\r
+ */\r
+ @Override\r
+ public String toString() {\r
+ return getResourceId().toString() + ":" + getTraceId().toString() + ":"\r
+ + getType().toString();\r
+ }\r
+\r
+ /**\r
+ * Compare function to implement Comparable<br>\r
+ * <br>\r
+ * Compare by traceId THEN IF EQUAL by resourceType THEN IF EQUAL by\r
+ * resourceId\r
+ * \r
+ * @param comparedResource\r
+ * The resource to compare to\r
+ * \r
+ * @return int 0 if equals, negative number if "smaller", positive if\r
+ * "bigger".\r
+ */\r
+ // @Override\r
+ public int compareTo(TimeRangeEventResource comparedResource) {\r
+ int returnedValue = 0;\r
+\r
+ if (comparedResource != null) {\r
+ // Compare by trace id first\r
+ returnedValue = this.getTraceId().compareTo(\r
+ comparedResource.getTraceId());\r
+\r
+ // If same, compare by resourceName\r
+ if (returnedValue == 0) {\r
+ returnedValue = this.getName().compareTo(\r
+ comparedResource.getName());\r
+\r
+ // Finally, if same, compare by ResourceId\r
+ if (returnedValue == 0) {\r
+ returnedValue = this.getResourceId().compareTo(\r
+ comparedResource.getResourceId());\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ return returnedValue;\r
+ }\r
+\r
+ public abstract String getStateMode(LttngTraceState traceState);\r
+}\r
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.model.trange;
+
+
+import org.eclipse.linuxtools.lttng.state.StateStrings;
+import org.eclipse.linuxtools.lttng.state.model.LttngIRQState;
+import org.eclipse.linuxtools.lttng.state.model.LttngTraceState;
+import org.eclipse.linuxtools.lttng.state.model.LttngTrapState;
+import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEventResource.ResourceTypes;
+
+/**
+ * Creates Resources with custom implementation to obtain its corresponding
+ * state mode
+ * <p>
+ * The state mode resolution is needed at the end of a data request, as well as
+ * in the before and after handlers
+ * </p>
+ *
+ * @author alvaro
+ *
+ */
+public class TimeRangeResourceFactory {
+ // ========================================================================
+ // Data
+ // =======================================================================
+ private static TimeRangeResourceFactory instance = null;
+
+ // ========================================================================
+ // Create instance
+ // =======================================================================
+ /**
+ * Factory singleton
+ *
+ * @return
+ */
+ public static TimeRangeResourceFactory getInstance() {
+ if (instance == null) {
+ instance = new TimeRangeResourceFactory();
+ }
+ return instance;
+ }
+
+ // ========================================================================
+ // Public methods
+ // =======================================================================
+ public TimeRangeEventResource createResource(int newId, long newStartTime,
+ long newStopTime, String newName, String newGroupName,
+ String newClassName, ResourceTypes type, Long newResourceId,
+ long insertionTime) {
+
+ TimeRangeEventResource resource = null;
+ switch (type) {
+ case CPU:
+ resource = createCpuResource(newId, newStartTime, newStopTime,
+ newName, newGroupName, newClassName, type, newResourceId,
+ insertionTime);
+ break;
+ case IRQ:
+ resource = createIrqResource(newId, newStartTime, newStopTime,
+ newName, newGroupName, newClassName, type, newResourceId,
+ insertionTime);
+ break;
+ case SOFT_IRQ:
+ resource = createSoftIrqResource(newId, newStartTime, newStopTime,
+ newName, newGroupName, newClassName, type, newResourceId,
+ insertionTime);
+ break;
+ case TRAP:
+ resource = createTrapResource(newId, newStartTime, newStopTime,
+ newName, newGroupName, newClassName, type, newResourceId,
+ insertionTime);
+ break;
+ case BDEV:
+ resource = createBdevResource(newId, newStartTime, newStopTime,
+ newName, newGroupName, newClassName, type, newResourceId,
+ insertionTime);
+ break;
+ default:
+ break;
+ }
+
+ return resource;
+ }
+
+ // ========================================================================
+ // Private methods
+ // =======================================================================
+ private TimeRangeEventResource createIrqResource(int newId,
+ long newStartTime, long newStopTime, String newName,
+ String newGroupName, String newClassName, ResourceTypes newType,
+ Long newResourceId, long insertionTime) {
+
+ TimeRangeEventResource resource = new TimeRangeEventResource(newId,
+ newStartTime, newStopTime, newName, newGroupName, newClassName,
+ newType, newResourceId, insertionTime) {
+
+ @Override
+ public String getStateMode(LttngTraceState traceSt) {
+ LttngIRQState irqState = traceSt.getIrq_states().get(
+ getResourceId());
+ String statemode = "";
+ if (irqState != null) {
+ statemode = irqState.peekFromIrqStack().getInName();
+ }
+
+ return statemode;
+ }
+ };
+
+ return resource;
+ }
+
+ private TimeRangeEventResource createTrapResource(int newId,
+ long newStartTime, long newStopTime, String newName,
+ String newGroupName, String newClassName, ResourceTypes newType,
+ Long newResourceId, long insertionTime) {
+
+ TimeRangeEventResource resource = new TimeRangeEventResource(newId,
+ newStartTime, newStopTime, newName, newGroupName, newClassName,
+ newType, newResourceId, insertionTime) {
+
+ @Override
+ public String getStateMode(LttngTraceState traceSt) {
+ // Determine the trap state.
+ String trapStateMode = "";
+ LttngTrapState ts = traceSt.getTrap_states().get(getResourceId());
+
+ // *** Note :
+ // Ts might not have been created yet.
+ // This is because the state system will be updated next to this before hook
+ // It should be correct to create it here as Busy
+ // (traps are created with running++ so it wont be idle)
+ if ( ts != null ) {
+ Long trapState = ts.getRunning();
+
+ if (trapState == 0) {
+ trapStateMode = StateStrings.TrapMode.LTTV_TRAP_IDLE.getInName();
+ } else {
+ trapStateMode = StateStrings.TrapMode.LTTV_TRAP_BUSY.getInName();
+ }
+ }
+ else {
+ trapStateMode = StateStrings.TrapMode.LTTV_TRAP_BUSY.getInName();
+ }
+
+ return trapStateMode;
+ }
+ };
+
+ return resource;
+ }
+
+ private TimeRangeEventResource createSoftIrqResource(int newId,
+ long newStartTime, long newStopTime, String newName,
+ String newGroupName, String newClassName, ResourceTypes newType,
+ Long newResourceId, long insertionTime) {
+
+ TimeRangeEventResource resource = new TimeRangeEventResource(newId,
+ newStartTime, newStopTime, newName, newGroupName, newClassName,
+ newType, newResourceId, insertionTime) {
+
+ @Override
+ public String getStateMode(LttngTraceState traceSt) {
+ // Get the resource id.
+ Long softIrqId = getResourceId();
+ // Get the resource state mode
+ long running = traceSt.getSoft_irq_states().get(softIrqId)
+ .getRunning().longValue();
+ long pending = traceSt.getSoft_irq_states().get(softIrqId)
+ .getPending().longValue();
+
+ String softIrqStateMode;
+ if (running > 0) {
+ softIrqStateMode = StateStrings.SoftIRQMode.LTTV_SOFT_IRQ_BUSY
+ .getInName();
+ } else if (pending > 0) {
+ softIrqStateMode = StateStrings.SoftIRQMode.LTTV_SOFT_IRQ_PENDING
+ .getInName();
+ } else {
+ softIrqStateMode = StateStrings.SoftIRQMode.LTTV_SOFT_IRQ_IDLE
+ .getInName();
+ }
+
+ return softIrqStateMode;
+ }
+
+ };
+
+ return resource;
+ }
+
+ private TimeRangeEventResource createBdevResource(int newId,
+ long newStartTime, long newStopTime, String newName,
+ String newGroupName, String newClassName, ResourceTypes newType,
+ Long newResourceId, long insertionTime) {
+
+ TimeRangeEventResource resource = new TimeRangeEventResource(newId,
+ newStartTime, newStopTime, newName, newGroupName, newClassName,
+ newType, newResourceId, insertionTime) {
+
+ @Override
+ public String getStateMode(LttngTraceState traceSt) {
+ // Get the resource state mode
+ String bdevStateMode = traceSt.getBdev_states().get(
+ getResourceId()).peekFromBdevStack().getInName();
+
+ return bdevStateMode;
+ }
+
+ };
+
+ return resource;
+ }
+
+ private TimeRangeEventResource createCpuResource(int newId,
+ long newStartTime, long newStopTime, String newName,
+ String newGroupName, String newClassName, ResourceTypes newType,
+ Long newResourceId, long insertionTime) {
+
+ TimeRangeEventResource resource = new TimeRangeEventResource(newId,
+ newStartTime, newStopTime, newName, newGroupName, newClassName,
+ newType, newResourceId, insertionTime) {
+
+ @Override
+ public String getStateMode(LttngTraceState traceSt) {
+ // Get the resource state mode
+ String cpuStateMode = traceSt.getCpu_states().get(
+ getResourceId())
+ .peekFromCpuStack().getInName();
+
+ return cpuStateMode;
+ }
+
+ };
+
+ return resource;
+ }
+}
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2009 Ericsson\r
+ * \r
+ * All rights reserved. This program and the accompanying materials are\r
+ * made available under the terms of the Eclipse Public License v1.0 which\r
+ * accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ * \r
+ * Contributors:\r
+ * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation\r
+ *******************************************************************************/\r
+package org.eclipse.linuxtools.lttng.ui.model.trange;\r
+\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+import org.eclipse.linuxtools.lttng.state.StateStrings.BdevMode;\r
+import org.eclipse.linuxtools.lttng.state.StateStrings.CpuMode;\r
+import org.eclipse.linuxtools.lttng.state.StateStrings.ExecutionMode;\r
+import org.eclipse.linuxtools.lttng.state.StateStrings.IRQMode;\r
+import org.eclipse.linuxtools.lttng.state.StateStrings.ProcessStatus;\r
+import org.eclipse.linuxtools.lttng.state.StateStrings.SoftIRQMode;\r
+import org.eclipse.linuxtools.lttng.state.StateStrings.TrapMode;\r
+import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeAnalysisProvider;\r
+import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITimeEvent;\r
+import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITmfTimeAnalysisEntry;\r
+\r
+public class TimeRangeViewerProvider extends TmfTimeAnalysisProvider {\r
+ // ========================================================================\r
+ // Data\r
+ // =======================================================================\r
+ Map<String, StateColor> procStateToColor = new HashMap<String, StateColor>(\r
+ 16);\r
+ Map<String, StateColor> bdevStateToColor = new HashMap<String, StateColor>(\r
+ 4);\r
+ Map<String, StateColor> softIrqStateToColor = new HashMap<String, StateColor>(\r
+ 4);\r
+ Map<String, StateColor> trapStateToColor = new HashMap<String, StateColor>(\r
+ 4);\r
+ Map<String, StateColor> irqStateToColor = new HashMap<String, StateColor>(4);\r
+ Map<String, StateColor> cpuStateToColor = new HashMap<String, StateColor>(8);\r
+\r
+ // ========================================================================\r
+ // Constructors\r
+ // =======================================================================\r
+ public TimeRangeViewerProvider() {\r
+ // Fill the statemode to color maps\r
+ fillProcessStateToColor();\r
+ fillBdevStateToColor();\r
+ fillSoftIRQStateToColor();\r
+ fillTrapStateToColor();\r
+ fillIrqStateToColor();\r
+ fillCpuStateToColor();\r
+ }\r
+\r
+ // ========================================================================\r
+ // Methods\r
+ // =======================================================================\r
+ @Override\r
+ public StateColor getEventColor(ITimeEvent event) {\r
+ StateColor retColor = null;\r
+ \r
+ if (event instanceof TimeRangeEvent) {\r
+ TimeRangeEvent devent = (TimeRangeEvent) event;\r
+ String stateMode = devent.getStateMode();\r
+ switch (devent.getEventType()) {\r
+ case PROCESS_MODE:\r
+ retColor = procStateToColor.get(stateMode);\r
+ break;\r
+ case BDEV_MODE:\r
+ retColor = bdevStateToColor.get(stateMode);\r
+ break;\r
+ case IRQ_MODE:\r
+ retColor = irqStateToColor.get(stateMode);\r
+ break;\r
+ case SOFT_IRQ_MODE:\r
+ retColor = softIrqStateToColor.get(stateMode);\r
+ break;\r
+ case CPU_MODE:\r
+ retColor = cpuStateToColor.get(stateMode);\r
+ break;\r
+ case TRAP_MODE:\r
+ retColor = trapStateToColor.get(stateMode);\r
+ break;\r
+ }\r
+ }\r
+ \r
+ if (retColor == null) {\r
+ return StateColor.MAGENTA3;\r
+ }\r
+ return retColor;\r
+ }\r
+\r
+ /* (non-Javadoc)\r
+ * @see org.eclipse.linuxtools.tmf.ui.widgets.timeAnalysis.api.TsfTmAbstractImplProvider#getStateName(org.eclipse.linuxtools.tmf.ui.widgets.timeAnalysis.api.TsfTmAbstractImplProvider.StateColor)\r
+ */\r
+ @Override\r
+ public String getStateName(StateColor color) {\r
+ //Override to multiple instances of the widget, the same color can have multiple meanings\r
+ return "Not mapped";\r
+ }\r
+\r
+ @Override\r
+ public Map<String, String> getEventHoverToolTipInfo(ITimeEvent revent) {\r
+ Map<String, String> toolTipEventMsgs = new HashMap<String, String>();\r
+ //if the selected resource is a Process, add the Process type to the tool tip\r
+ if (revent instanceof TimeRangeComponent) {\r
+ ITimeRangeComponent parent = ((TimeRangeComponent) revent)\r
+ .getEventParent();\r
+ if (parent != null && parent instanceof TimeRangeEventProcess) {\r
+ TimeRangeEventProcess localProcess = (TimeRangeEventProcess) parent;\r
+ toolTipEventMsgs.put("Process Type", localProcess\r
+ .getProcessType());\r
+ }\r
+ }\r
+\r
+ return toolTipEventMsgs;\r
+ }\r
+\r
+ @Override\r
+ public String getEventName(ITimeEvent event, boolean upper, boolean extInfo) {\r
+ String name = null;\r
+ //The relevant event name for the time range is the actual state mode\r
+ if (event instanceof TimeRangeEvent) {\r
+ TimeRangeEvent devent = (TimeRangeEvent) event;\r
+ StringBuilder sb = new StringBuilder(devent.getStateMode());\r
+ name = sb.toString();\r
+ }\r
+ \r
+ if (name == null) {\r
+ return "Unknown";\r
+ }\r
+ return name;\r
+ }\r
+\r
+ @Override\r
+ public String getTraceClassName(ITmfTimeAnalysisEntry trace) {\r
+ String name = "";\r
+ if (trace instanceof TimeRangeComposite) {\r
+ TimeRangeComposite dTrace = (TimeRangeComposite) trace;\r
+ name = dTrace.getClassName();\r
+ }\r
+ return name;\r
+ }\r
+\r
+ private void fillCpuStateToColor() {\r
+ cpuStateToColor.put(CpuMode.LTTV_CPU_UNKNOWN.getInName(),\r
+ StateColor.BLACK);\r
+ cpuStateToColor.put(CpuMode.LTTV_CPU_IDLE.getInName(), StateColor.GRAY);\r
+ cpuStateToColor.put(CpuMode.LTTV_CPU_BUSY.getInName(),\r
+ StateColor.LIGHT_BLUE);\r
+ cpuStateToColor\r
+ .put(CpuMode.LTTV_CPU_IRQ.getInName(), StateColor.ORANGE);\r
+ cpuStateToColor.put(CpuMode.LTTV_CPU_SOFT_IRQ.getInName(),\r
+ StateColor.PURPLE1);\r
+ cpuStateToColor.put(CpuMode.LTTV_CPU_TRAP.getInName(), StateColor.GOLD);\r
+ }\r
+\r
+ private void fillIrqStateToColor() {\r
+ irqStateToColor.put(IRQMode.LTTV_IRQ_UNKNOWN.getInName(),\r
+ StateColor.BLACK);\r
+ irqStateToColor.put(IRQMode.LTTV_IRQ_IDLE.getInName(), StateColor.GRAY);\r
+ irqStateToColor.put(IRQMode.LTTV_IRQ_BUSY.getInName(),\r
+ StateColor.ORANGE);\r
+ }\r
+\r
+ private void fillTrapStateToColor() {\r
+ trapStateToColor.put(TrapMode.LTTV_TRAP_UNKNOWN.getInName(),\r
+ StateColor.BLACK);\r
+ trapStateToColor.put(TrapMode.LTTV_TRAP_IDLE.getInName(),\r
+ StateColor.BLACK);\r
+ trapStateToColor.put(TrapMode.LTTV_TRAP_BUSY.getInName(),\r
+ StateColor.GOLD);\r
+ }\r
+\r
+ private void fillSoftIRQStateToColor() {\r
+ softIrqStateToColor.put(SoftIRQMode.LTTV_SOFT_IRQ_UNKNOWN.getInName(),\r
+ StateColor.BLACK);\r
+ softIrqStateToColor.put(SoftIRQMode.LTTV_SOFT_IRQ_IDLE.getInName(),\r
+ StateColor.BLACK);\r
+ softIrqStateToColor.put(SoftIRQMode.LTTV_SOFT_IRQ_PENDING.getInName(),\r
+ StateColor.PINK1);\r
+ softIrqStateToColor.put(SoftIRQMode.LTTV_SOFT_IRQ_BUSY.getInName(),\r
+ StateColor.PURPLE1);\r
+ }\r
+\r
+ private void fillBdevStateToColor() {\r
+ softIrqStateToColor.put(BdevMode.LTTV_BDEV_UNKNOWN.getInName(),\r
+ StateColor.BLACK);\r
+ softIrqStateToColor.put(BdevMode.LTTV_BDEV_IDLE.getInName(),\r
+ StateColor.BLACK);\r
+ softIrqStateToColor.put(BdevMode.LTTV_BDEV_BUSY_READING.getInName(),\r
+ StateColor.DARK_BLUE);\r
+ softIrqStateToColor.put(BdevMode.LTTV_BDEV_BUSY_WRITING.getInName(),\r
+ StateColor.RED);\r
+ }\r
+\r
+ private void fillProcessStateToColor() {\r
+ // Process Status\r
+ procStateToColor.put(ProcessStatus.LTTV_STATE_UNNAMED.getInName(),\r
+ StateColor.GRAY);\r
+ procStateToColor.put(ProcessStatus.LTTV_STATE_DEAD.getInName(),\r
+ StateColor.BLACK);\r
+ procStateToColor.put(ProcessStatus.LTTV_STATE_WAIT_FORK.getInName(),\r
+ StateColor.DARK_GREEN);\r
+ procStateToColor.put(ProcessStatus.LTTV_STATE_WAIT_CPU.getInName(),\r
+ StateColor.DARK_YELLOW);\r
+ procStateToColor.put(ProcessStatus.LTTV_STATE_EXIT.getInName(),\r
+ StateColor.MAGENTA3);\r
+ procStateToColor.put(ProcessStatus.LTTV_STATE_ZOMBIE.getInName(),\r
+ StateColor.PURPLE1);\r
+ procStateToColor.put(ProcessStatus.LTTV_STATE_WAIT.getInName(),\r
+ StateColor.RED);\r
+\r
+ // Execution Mode\r
+ procStateToColor.put(ExecutionMode.LTTV_STATE_MODE_UNKNOWN.getInName(),\r
+ StateColor.BLACK);\r
+ procStateToColor.put(ExecutionMode.LTTV_STATE_USER_MODE.getInName(),\r
+ StateColor.GREEN);\r
+ procStateToColor.put(ExecutionMode.LTTV_STATE_SYSCALL.getInName(),\r
+ StateColor.DARK_BLUE);\r
+ procStateToColor.put(ExecutionMode.LTTV_STATE_TRAP.getInName(),\r
+ StateColor.GOLD);\r
+ procStateToColor.put(ExecutionMode.LTTV_STATE_IRQ.getInName(),\r
+ StateColor.ORANGE);\r
+ procStateToColor.put(ExecutionMode.LTTV_STATE_SOFT_IRQ.getInName(),\r
+ StateColor.PINK1);\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views;
+
+import org.eclipse.linuxtools.lttng.ui.views.control.ControlView;
+import org.eclipse.linuxtools.lttng.ui.views.controlflow.ControlFlowView;
+import org.eclipse.linuxtools.lttng.ui.views.events.EventsView;
+import org.eclipse.linuxtools.lttng.ui.views.histogram.HistogramView;
+import org.eclipse.linuxtools.lttng.ui.views.project.ProjectView;
+import org.eclipse.linuxtools.lttng.ui.views.resources.ResourcesView;
+import org.eclipse.linuxtools.lttng.ui.views.statistics.StatisticsView;
+import org.eclipse.linuxtools.lttng.ui.views.timeframe.TimeFrameView;
+import org.eclipse.ui.IFolderLayout;
+import org.eclipse.ui.IPageLayout;
+import org.eclipse.ui.IPerspectiveFactory;
+
+/**
+ * <b><u>PerspectiveFactory</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+public class PerspectiveFactory implements IPerspectiveFactory {
+
+ // LTTng views
+ private static final String PROJECT_VIEW_ID = ProjectView.ID;
+ private static final String CONTROL_VIEW_ID = ControlView.ID;
+ private static final String EVENTS_VIEW_ID = EventsView.ID;
+ private static final String TIME_FRAME_VIEW_ID = TimeFrameView.ID;
+ private static final String CONTROL_FLOW_VIEW_ID = ControlFlowView.ID;
+ private static final String RESOURCES_VIEW_ID = ResourcesView.ID;
+ private static final String STATISTICS_VIEW_ID = StatisticsView.ID;
+ private static final String HISTOGRAM_VIEW_ID = HistogramView.ID;
+
+ // Standard Eclipse views
+ private static final String PROPERTIES_VIEW_ID = IPageLayout.ID_PROP_SHEET;
+ private static final String PROBLEM_VIEW_ID = IPageLayout.ID_PROBLEM_VIEW;
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.IPerspectiveFactory#createInitialLayout(org.eclipse.ui.IPageLayout)
+ */
+ public void createInitialLayout(IPageLayout layout) {
+
+ layout.setEditorAreaVisible(false);
+
+ addFastViews(layout);
+ addViewShortcuts(layout);
+ addPerspectiveShortcuts(layout);
+
+ // Create the top left folder
+ IFolderLayout topLeftFolder = layout.createFolder("topLeftFolder", IPageLayout.LEFT, 0.15f, IPageLayout.ID_EDITOR_AREA);
+ topLeftFolder.addView(PROJECT_VIEW_ID);
+ topLeftFolder.addView(CONTROL_VIEW_ID);
+
+ // Create the bottom left folder
+ IFolderLayout bottomLeftFolder = layout.createFolder("bottomLeftFolder", IPageLayout.BOTTOM, 0.50f, "topLeftFolder");
+ bottomLeftFolder.addView(PROPERTIES_VIEW_ID);
+
+ // Create the middle right folder
+ IFolderLayout topRightFolder = layout.createFolder("topRightFolder", IPageLayout.TOP, 0.50f, IPageLayout.ID_EDITOR_AREA);
+ topRightFolder.addView(CONTROL_FLOW_VIEW_ID);
+ topRightFolder.addView(RESOURCES_VIEW_ID);
+ topRightFolder.addView(STATISTICS_VIEW_ID);
+
+ // Create the middle right folder
+ IFolderLayout middleRightFolder = layout.createFolder("middleRightFolder", IPageLayout.BOTTOM, 0.50f, "topRightFolder");
+ middleRightFolder.addView(EVENTS_VIEW_ID);
+
+ // Create the bottom right folder
+ IFolderLayout bottomRightFolder = layout.createFolder("bottomRightFolder", IPageLayout.BOTTOM, 0.65f, "middleRightFolder");
+ bottomRightFolder.addView(TIME_FRAME_VIEW_ID);
+ bottomRightFolder.addView(HISTOGRAM_VIEW_ID);
+ bottomRightFolder.addView(PROBLEM_VIEW_ID);
+
+ }
+
+ /**
+ * Add fast views to the perspective
+ *
+ * @param layout
+ */
+ private void addFastViews(IPageLayout layout) {
+ // TODO Auto-generated method stub
+ }
+
+ /**
+ * Add view shortcuts to the perspective
+ *
+ * @param layout
+ */
+ private void addViewShortcuts(IPageLayout layout) {
+ // TODO Auto-generated method stub
+ }
+
+ /**
+ * Add perspective shortcuts to the perspective
+ *
+ * @param layout
+ */
+ private void addPerspectiveShortcuts(IPageLayout layout) {
+ // TODO Auto-generated method stub
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors: Alvaro Sanchez-Leon - Initial implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.common;
+
+import org.eclipse.linuxtools.lttng.state.evProcessor.ILttngEventProcessor;
+import org.eclipse.linuxtools.lttng.state.evProcessor.state.AbsStateProcessing;
+import org.eclipse.linuxtools.lttng.state.model.LttngTraceState;
+import org.eclipse.linuxtools.tmf.event.TmfTimeRange;
+
+public abstract class AbsTRangeUpdate extends AbsStateProcessing implements
+ ILttngEventProcessor {
+
+ private static final long MINORBITS = 20;
+
+ // ========================================================================
+ // General methods
+ // =======================================================================
+
+ /**
+ * Get the mkdev node id<br>
+ * <br>
+ * This is an implementation of a KERNEL macro used in Lttv
+ *
+ */
+ public long getMkdevId(long major, long minor) {
+ return (((major) << MINORBITS) | (minor));
+ }
+
+ /**
+ * Get the pixels per Nano second, either from active widgets or initialise
+ * with the experiment time range values
+ *
+ * @param traceSt
+ * @param params
+ *
+ * @return double
+ */
+ protected double getPixelsPerNs(LttngTraceState traceSt, ParamsUpdater params) {
+ double pixPerNs = params.getPixelsPerNs();
+ if (pixPerNs == 0) {
+ TmfTimeRange tsetRange = traceSt.getContext().getExperimentTimeWindow();
+
+ long startTime = tsetRange.getStartTime().getValue();
+ long endTime = tsetRange.getEndTime().getValue();
+ long delta = endTime - startTime;
+
+ if (delta > 0) {
+ pixPerNs = (double) params.getWidth() / (double) delta;
+ params.setPixelsPerNs(pixPerNs);
+ }
+ }
+ return pixPerNs;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.common;
+
+import java.util.Arrays;
+
+import org.eclipse.linuxtools.lttng.control.LttngCoreProviderFactory;
+import org.eclipse.linuxtools.lttng.control.LttngSyntheticEventProvider;
+import org.eclipse.linuxtools.lttng.event.LttngSyntheticEvent;
+import org.eclipse.linuxtools.lttng.event.LttngSyntheticEvent.SequenceInd;
+import org.eclipse.linuxtools.lttng.event.LttngTimestamp;
+import org.eclipse.linuxtools.lttng.request.ILttngSyntEventRequest;
+import org.eclipse.linuxtools.lttng.request.IRequestStatusListener;
+import org.eclipse.linuxtools.lttng.request.LttngSyntEventRequest;
+import org.eclipse.linuxtools.lttng.request.RequestCompletedSignal;
+import org.eclipse.linuxtools.lttng.request.RequestStartedSignal;
+import org.eclipse.linuxtools.lttng.state.evProcessor.ITransEventProcessor;
+import org.eclipse.linuxtools.lttng.ui.TraceDebug;
+import org.eclipse.linuxtools.lttng.ui.model.trange.ItemContainer;
+import org.eclipse.linuxtools.lttng.ui.views.resources.model.ResourceModelFactory;
+import org.eclipse.linuxtools.tmf.event.TmfEvent;
+import org.eclipse.linuxtools.tmf.event.TmfTimeRange;
+import org.eclipse.linuxtools.tmf.event.TmfTimestamp;
+import org.eclipse.linuxtools.tmf.experiment.TmfExperiment;
+import org.eclipse.linuxtools.tmf.request.TmfDataRequest;
+import org.eclipse.linuxtools.tmf.signal.TmfRangeSynchSignal;
+import org.eclipse.linuxtools.tmf.signal.TmfSignalHandler;
+import org.eclipse.linuxtools.tmf.signal.TmfSignalManager;
+import org.eclipse.linuxtools.tmf.signal.TmfTimeSynchSignal;
+import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.ITimeAnalysisViewer;
+import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeScaleSelectionEvent;
+import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeSelectionEvent;
+import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITmfTimeAnalysisEntry;
+import org.eclipse.linuxtools.tmf.ui.views.TmfView;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * <p>
+ * Abstract class used as a base for views handling specific time range data
+ * requests
+ * </p>
+ * <p>
+ * The class handles a single element queue of data requests, i.e. request can
+ * be triggered from different sources e.g. opening a file as well as a new
+ * selected time window
+ * </p>
+ *
+ * @author alvaro
+ *
+ */
+public abstract class AbsTimeUpdateView extends TmfView implements
+ IRequestStatusListener {
+
+ // ========================================================================
+ // Data
+ // ========================================================================
+ /**
+ * One second in nanoseconds
+ */
+ private static final long INITIAL_WINDOW_OFFSET = 1000000000L; /*
+ * 1 sec //
+ * in ns //
+ */
+ // private static final long INITIAL_WINDOW_OFFSET = 100000000L; /* 100 ms
+ // in ns */
+ /**
+ * Number of events before a GUI refresh
+ */
+ private static final Long INPUT_CHANGED_REFRESH = 3000L;
+ private static final long DEFAULT_OFFSET = 0L;
+ private static final int DEFAULT_CHUNK = 1;
+
+ protected boolean synch = true; // time synchronisation, used to be an
+ // option
+ protected ITimeAnalysisViewer tsfviewer = null;
+
+ // ========================================================================
+ // Constructor
+ // ========================================================================
+ public AbsTimeUpdateView(String viewID) {
+ super(viewID);
+ // freqState = UiCommonFactory.getQueue(this);
+ }
+
+ // ========================================================================
+ // Methods
+ // ========================================================================
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.linuxtools.lttng.state.IStateDataRequestListener#
+ * processingStarted(org.eclipse.linuxtools.lttng.state.StateDataRequest)
+ */
+ @TmfSignalHandler
+ public synchronized void processingStarted(RequestStartedSignal signal) {
+ LttngSyntEventRequest request = signal.getRequest();
+ if (request != null) {
+ // update queue with the id of the current request.
+ // freqState.requestStarted(request);
+
+ // if there was no new request then this one is still on
+ // prepare for the reception of new data
+ waitCursor(true);
+
+ // no new time range for zoom orders
+ TmfTimeRange trange = null;
+ // Time Range will be used to filter out events which are
+ // not visible in one pixel
+ trange = request.getRange();
+
+ // indicate if the data model needs to be cleared e.g. a new
+ // experiment is being selected
+ boolean clearData = request.isclearDataInd();
+ // Indicate if current data needs to be cleared and if so
+ // specify the new experiment time range that applies
+ ModelUpdatePrep(trange, clearData);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.linuxtools.lttng.state.IStateDataRequestListener#
+ * processingCompleted(org.eclipse.linuxtools.lttng.state.StateDataRequest)
+ */
+ @TmfSignalHandler
+ public void processingCompleted(RequestCompletedSignal signal) {
+ ILttngSyntEventRequest request = signal.getRequest();
+
+ if (request == null) {
+ return;
+ }
+
+ // Update wait cursor
+ waitCursor(false);
+
+ // No data refresh actions for cancelled requests.
+ if (request.isCancelled() || request.isFailed()) {
+ if (TraceDebug.isDEBUG()) {
+ TmfTimeRange trange = request.getRange();
+ if (request.isCancelled()) {
+ TraceDebug.debug("Request cancelled "
+ + trange.getStartTime() + "-" + trange.getEndTime()
+ + " Handled Events: " + request.getSynEventCount()
+ + " " + request.toString(), 15);
+ } else if (request.isFailed()) {
+ TraceDebug.debug("Request Failed " + trange.getStartTime()
+ + "-" + trange.getEndTime() + " Handled Events: "
+ + request.getSynEventCount() + " "
+ + request.toString());
+ }
+ }
+
+ return;
+ } else {
+ modelInputChanged(request, true);
+ }
+ }
+
+ /**
+ * Registers as listener of time selection from other views
+ *
+ * @param signal
+ */
+ public void synchToTime(TmfTimeSynchSignal signal) {
+ if (synch) {
+ Object source = signal.getSource();
+ if (signal != null && source != null && source != this) {
+ // Internal value is expected in nano seconds.
+ long selectedTime = signal.getCurrentTime().getValue();
+ if (tsfviewer != null) {
+ tsfviewer.setSelectedTime(selectedTime, true, source);
+ }
+ }
+ }
+ }
+
+ /**
+ * Process the reception of time window adjustment in this view if the
+ * source of the update is not this view.
+ *
+ * @param signal
+ * @param clearingData
+ */
+ public void synchToTimeRange(TmfRangeSynchSignal signal, boolean clearingData) {
+ if (synch) {
+ Object source = signal.getSource();
+ if (signal != null && source != null && source != this) {
+ // Internal value is expected in nano seconds.
+ TmfTimeRange trange = signal.getCurrentRange();
+ TmfExperiment<?> experiment = TmfExperiment.getCurrentExperiment();
+ if (experiment == null) {
+ TraceDebug.debug("Current selected experiment is null");
+ return;
+ }
+
+ // Clearing of process data is configurable
+ dataRequest(trange, experiment.getTimeRange(), clearingData);
+ }
+ }
+ }
+
+ /**
+ * Trigger time synchronisation to other views this method shall be called
+ * when a check has been performed to note that an actual change of time has
+ * been performed vs a pure re-selection of the same time
+ *
+ * @param time
+ * @param source
+ */
+ protected void synchTimeNotification(long time, Object source) {
+ // if synchronisation selected
+ if (synch) {
+ // Notify other views
+ TmfSignalManager.dispatchSignal(new TmfTimeSynchSignal(source, new LttngTimestamp(time)));
+ }
+ }
+
+ /**
+ * Common implementation of ITmfTimeSelectionListener, not used by all the
+ * views extending this abstract class
+ *
+ * @param event
+ */
+ protected void tsfTmProcessSelEvent(TmfTimeSelectionEvent event) {
+ Object source = event.getSource();
+ if (source == null) {
+ return;
+ }
+
+ ParamsUpdater paramUpdater = getParamsUpdater();
+ Long savedSelTime = paramUpdater.getSelectedTime();
+
+ long selTimens = event.getSelectedTime();
+
+ // make sure the new selected time is different than saved before
+ // executing update
+ if (savedSelTime == null || savedSelTime != selTimens) {
+ // Notify listener views.
+ synchTimeNotification(selTimens, source);
+
+ // Update the parameter updater to save the selected time
+ paramUpdater.setSelectedTime(selTimens);
+
+ if (TraceDebug.isDEBUG()) {
+ TraceDebug.debug("Selected Time: " + new LttngTimestamp(selTimens) + "\n\t\t" + getName());
+ }
+ }
+ }
+
+ /**
+ * Common implementation of ITmfTimeScaleSelectionListener, not used by all
+ * the views extending this abstract class
+ *
+ * @param event
+ */
+ protected synchronized void tsfTmProcessTimeScaleEvent(TmfTimeScaleSelectionEvent event) {
+ // source needed to keep track of source values
+ Object source = event.getSource();
+
+ if (source != null) {
+ // Update the parameter updater before carrying out a read request
+ ParamsUpdater paramUpdater = getParamsUpdater();
+ boolean newParams = paramUpdater.processTimeScaleEvent(event);
+
+ if (newParams) {
+ // Read the updated time window
+ TmfTimeRange trange = paramUpdater.getTrange();
+ if (trange != null) {
+
+ // Notify listener views. to perform data requests
+ // upon this notification
+ synchTimeRangeNotification(trange, paramUpdater.getSelectedTime(), source);
+ }
+ }
+ }
+ }
+
+ /**
+ * Inform registered listeners about the new time range
+ *
+ * @param trange
+ * @param selectedTime
+ * @param source
+ */
+ protected void synchTimeRangeNotification(TmfTimeRange trange, Long selectedTime, Object source) {
+ // if synchronisation selected
+ if (synch) {
+ // Notify other views
+ TmfSignalManager.dispatchSignal(new TmfRangeSynchSignal(source, trange, new LttngTimestamp(selectedTime)));
+ }
+ }
+
+ /**
+ * @param zoomedTRange
+ * @param experimentTRange
+ */
+ public void dataRequest(TmfTimeRange zoomedTRange,
+ TmfTimeRange experimentTRange, boolean clearingData) {
+
+ // timeRange is the Experiment time range
+ boolean sent = processDataRequest(zoomedTRange, experimentTRange, clearingData);
+
+ if (sent) {
+ waitCursor(true);
+ }
+ }
+
+ /**
+ * send data request directly e.g. doesn't use a queue
+ *
+ * @param requestTrange
+ * @param listener
+ * @param experimentTRange
+ * @param processor
+ * @return
+ */
+ private boolean processDataRequest(TmfTimeRange requestTrange,
+ TmfTimeRange experimentTRange, boolean clearingData) {
+ // Validate input
+ if (requestTrange == null || experimentTRange == null) {
+ TraceDebug.debug("Invalid input");
+ return false;
+ }
+
+ LttngSyntEventRequest request = new LttngSyntEventRequest(
+ requestTrange, DEFAULT_OFFSET, TmfDataRequest.ALL_DATA,
+ DEFAULT_CHUNK, this, experimentTRange, getEventProcessor()) {
+
+ Long fCount = getSynEventCount();
+ ITransEventProcessor processor = getProcessor();
+ TmfTimestamp frunningTimeStamp;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.linuxtools.lttng.request.LttngSyntEventRequest#handleData
+ * ()
+ */
+ public void handleData() {
+ TmfEvent[] result = getData();
+
+ TmfEvent evt = (result.length > 0) ? result[0] : null;
+ if (evt != null) {
+ LttngSyntheticEvent synEvent = (LttngSyntheticEvent) evt;
+ // process event
+ SequenceInd indicator = synEvent.getSynType();
+ if (indicator == SequenceInd.BEFORE
+ || indicator == SequenceInd.AFTER) {
+ processor.process(evt, synEvent.getTraceModel());
+ } else if (indicator == SequenceInd.STARTREQ) {
+ handleRequestStarted();
+ } else if (indicator == SequenceInd.ENDREQ) {
+ processor.process(evt, synEvent.getTraceModel());
+ // handleCompleted();
+ }
+
+ if (indicator == SequenceInd.BEFORE) {
+ fCount++;
+ if (fCount != 0 && fCount % INPUT_CHANGED_REFRESH == 0) {
+ // send partial update
+ modelInputChanged(this, false);
+
+ if (TraceDebug.isDEBUG()) {
+ frunningTimeStamp = evt.getTimestamp();
+ TraceDebug.debug("handled: " + fCount + " sequence: " + synEvent.getSynType());
+ }
+
+ }
+ }
+ }
+ }
+
+ public void handleRequestStarted() {
+ notifyStarting();
+ }
+
+ public void handleCompleted() {
+ super.handleCompleted();
+
+ // Data is not complete and should be handled as such
+ if (isFailed() || isCancelled()) {
+ modelIncomplete(this);
+ }
+
+ if (TraceDebug.isDEBUG()) {
+ if (frunningTimeStamp != null) {
+ TraceDebug.debug("Last event time stamp: "
+ + frunningTimeStamp.getValue());
+ }
+ }
+ }
+ };
+
+ // obtain singleton core provider
+ LttngSyntheticEventProvider provider = LttngCoreProviderFactory
+ .getEventProvider();
+
+ // send the request to TMF
+ request.startRequestInd(provider);
+ request.setclearDataInd(clearingData);
+ return true;
+ }
+
+ /**
+ * Returns an initial smaller window to allow the user to select the area of
+ * interest
+ *
+ * @param experimentTRange
+ * @return
+ */
+ protected TmfTimeRange getInitTRange(TmfTimeRange experimentTRange) {
+ TmfTimestamp expStartTime = experimentTRange.getStartTime();
+ TmfTimestamp expEndTime = experimentTRange.getEndTime();
+ TmfTimestamp initialEndOfWindow = new LttngTimestamp(expStartTime
+ .getValue()
+ + INITIAL_WINDOW_OFFSET);
+ if (initialEndOfWindow.compareTo(expEndTime, false) < 0) {
+ return new TmfTimeRange(expStartTime, initialEndOfWindow);
+ }
+
+ // The original size of the experiment is smaller than proposed adjusted
+ // time
+ return experimentTRange;
+ }
+
+ /**
+ * Request the Time Analysis widget to enable or disable the wait cursor
+ * e.g. data request in progress or data request completed
+ *
+ * @param waitInd
+ */
+ protected void waitCursor(final boolean waitInd) {
+ if (tsfviewer != null) {
+ Display display = tsfviewer.getControl().getDisplay();
+
+ // Perform the updates on the UI thread
+ display.asyncExec(new Runnable() {
+ public void run() {
+ tsfviewer.waitCursor(waitInd);
+ }
+ });
+ }
+ }
+
+ /**
+ * View preparation to override the current local information
+ *
+ * @param timeRange
+ * - new total time range e.g. Experiment level
+ * @param clearAllData
+ */
+ protected void ModelUpdatePrep(TmfTimeRange timeRange, boolean clearAllData) {
+ ItemContainer<?> itemContainer = getItemContainer();
+ if (clearAllData) {
+ // start fresh e.g. new experiment selected
+ itemContainer.clearItems();
+ } else {
+ // clear children but keep processes
+ itemContainer.clearChildren();
+ }
+
+ // Obtain the current resource array
+ ITmfTimeAnalysisEntry[] itemArr = itemContainer.readItems();
+
+ // clean up data and boundaries
+ displayModel(itemArr, -1, -1, false, -1, -1, null);
+
+ ParamsUpdater updater = getParamsUpdater();
+ if (updater != null) {
+ // Start over
+ updater.setEventsDiscarded(0);
+
+ // Update new visible time range if available
+ if (timeRange != null) {
+ updater.update(timeRange.getStartTime().getValue(), timeRange.getEndTime().getValue());
+ }
+ }
+ }
+
+ /**
+ * Initialize the model and view before reloading items
+ *
+ * @param boundaryRange
+ * @param visibleRange
+ * @param source
+ */
+ protected void ModelUpdateInit(TmfTimeRange boundaryRange, TmfTimeRange visibleRange, Object source) {
+ // Update the view boundaries
+ if (boundaryRange != null) {
+ ItemContainer<?> itemContainer = getItemContainer();
+ if (itemContainer != null) {
+ itemContainer.clearItems();
+ // Obtain the current process array
+ ITmfTimeAnalysisEntry[] itemArr = itemContainer.readItems();
+
+ long startTime = boundaryRange.getStartTime().getValue();
+ long endTime = boundaryRange.getEndTime().getValue();
+
+ // Update the view part
+ displayModel(itemArr, startTime, endTime, true, visibleRange.getStartTime().getValue(), visibleRange
+ .getEndTime().getValue(), source);
+ }
+ }
+
+ // update the view filtering parameters
+ if (visibleRange != null) {
+ ParamsUpdater updater = getParamsUpdater();
+ if (updater != null) {
+ // Start over
+ updater.setEventsDiscarded(0);
+ // Update new visible time range if available
+ updater.update(visibleRange.getStartTime().getValue(), visibleRange.getEndTime().getValue());
+ }
+ }
+ }
+
+ /**
+ * Actions taken by the view to refresh its widget(s) with the updated data
+ * model
+ *
+ * @param request
+ * @param complete
+ * true: yes, false: partial update
+ */
+ protected void modelInputChanged(ILttngSyntEventRequest request, boolean complete) {
+ long experimentStartTime = -1;
+ long experimentEndTime = -1;
+ TmfTimeRange experimentTimeRange = request.getExperimentTimeRange();
+ if (experimentTimeRange != null) {
+ experimentStartTime = experimentTimeRange.getStartTime().getValue();
+ experimentEndTime = experimentTimeRange.getEndTime().getValue();
+ }
+
+ // Obtain the current resource list
+ ITmfTimeAnalysisEntry[] itemArr = getItemContainer().readItems();
+
+ if (itemArr != null) {
+ // Sort the array by pid
+ Arrays.sort(itemArr);
+
+ // Update the view part
+ displayModel(itemArr, experimentStartTime, experimentEndTime, false, request.getRange().getStartTime()
+ .getValue(), request.getRange().getEndTime().getValue(), request.getSource());
+ }
+
+ if (complete) {
+ // reselect to original time
+ ParamsUpdater paramUpdater = ResourceModelFactory.getParamsUpdater();
+ if (paramUpdater != null && tsfviewer != null) {
+ final Long selTime = paramUpdater.getSelectedTime();
+ if (selTime != null) {
+ TraceDebug.debug("View: " + getName() + "\n\t\tRestoring the selected time to: " + selTime);
+ Display display = tsfviewer.getControl().getDisplay();
+ display.asyncExec(new Runnable() {
+ public void run() {
+ tsfviewer.setSelectedTime(selTime, false, this);
+ }
+ });
+ }
+
+ if (TraceDebug.isDEBUG()) {
+ int eventCount = 0;
+ Long count = request.getSynEventCount();
+ for (int pos = 0; pos < itemArr.length; pos++) {
+ eventCount += itemArr[pos].getTraceEvents().size();
+ }
+
+ int discarded = getParamsUpdater().getEventsDiscarded();
+ int discardedOutofOrder = paramUpdater.getEventsDiscardedWrongOrder();
+ TmfTimeRange range = request.getRange();
+ StringBuilder sb = new StringBuilder("View: " + getName() + ", Events handled: " + count
+ + ", Events loaded in view: " + eventCount + ", Number of events discarded: " + discarded
+ + "\n\tNumber of events discarded with start time earlier than next good time: "
+ + discardedOutofOrder);
+
+ sb.append("\n\t\tRequested Time Range: " + range.getStartTime() + "-" + range.getEndTime());
+ sb.append("\n\t\tExperiment Time Range: " + experimentStartTime + "-" + experimentEndTime);
+ TraceDebug.debug(sb.toString());
+ }
+ }
+
+ }
+ }
+
+ // /**
+ // * Obtains the remainder fraction on unit Seconds of the entered value in
+ // * nanoseconds. e.g. input: 1241207054171080214 ns The number of seconds
+ // can
+ // * be obtain by removing the last 9 digits: 1241207054 the fractional
+ // * portion of seconds, expressed in ns is: 171080214
+ // *
+ // * @param v
+ // * @return
+ // */
+ // protected String formatNs(long v) {
+ // StringBuffer str = new StringBuffer();
+ // boolean neg = v < 0;
+ // if (neg) {
+ // v = -v;
+ // str.append('-');
+ // }
+ //
+ // String strVal = String.valueOf(v);
+ // if (v < 1000000000) {
+ // return strVal;
+ // }
+ //
+ // // Extract the last nine digits (e.g. fraction of a S expressed in ns
+ // return strVal.substring(strVal.length() - 9);
+ // }
+
+ /**
+ * The request was stopped, the data is incomplete
+ *
+ * @param request
+ */
+ protected abstract void modelIncomplete(ILttngSyntEventRequest request);
+
+ /**
+ * Returns the Event processor instance related to a specific view
+ *
+ * @return
+ */
+ protected abstract ITransEventProcessor getEventProcessor();
+
+ /**
+ * To be overridden by some sub-classes although may not be needed in some
+ * e.g. statistics view
+ *
+ * @param items
+ * @param startBoundTime
+ * @param endBoundTime
+ * @param updateTimeBounds
+ * - Time bounds updated needed e.g. if a new Experiment or trace
+ * is selected
+ * @param startVisibleWindow
+ * @param endVisibleWindow
+ * @param source
+ */
+ protected abstract void displayModel(final ITmfTimeAnalysisEntry[] items, final long startBoundTime,
+ final long endBoundTime, final boolean updateTimeBounds, final long startVisibleWindow,
+ final long endVisibleWindow, final Object source);
+
+ /**
+ * To be overridden by some sub-classes although may not be needed in some
+ * e.g. statistics view
+ *
+ * @return
+ */
+ protected abstract ParamsUpdater getParamsUpdater();
+
+ /**
+ * Returns the model's item container
+ *
+ * @return
+ */
+ protected abstract ItemContainer<?> getItemContainer();
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.common;
+
+import org.eclipse.linuxtools.lttng.event.LttngTimestamp;
+import org.eclipse.linuxtools.lttng.ui.TraceDebug;
+import org.eclipse.linuxtools.tmf.event.TmfTimeRange;
+import org.eclipse.linuxtools.tmf.event.TmfTimestamp;
+import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeScaleSelectionEvent;
+
+/**
+ *
+ * Preserve the time and space width parameters applicable to a particular view
+ * in order to facilitate filtering of events and request handling.
+ *
+ * @author alvaro
+ *
+ */
+public class ParamsUpdater {
+ // ========================================================================
+ // Data
+ // ========================================================================
+
+ private long startTime = 0;
+ private long endTime = Long.MAX_VALUE;
+ private Long selectedTime = null;
+ private final int DEFAULT_WIDTH = 2000; // number of estimated pixels
+ // that
+ // can hold the time range space
+ private int width = DEFAULT_WIDTH; // width in pixels used to represent the
+ // time interval
+ private double pixelsPerNs = 0;
+ private int eventsDiscarded = 0;
+ private int eventsDiscardedWrongOrder = 0;
+ private TmfTimeRange trange = null;
+
+ // ========================================================================
+ // Methods
+ // ========================================================================
+
+ /**
+ * @param event
+ * @return
+ */
+ public synchronized boolean processTimeScaleEvent(
+ TmfTimeScaleSelectionEvent event) {
+
+ boolean updated = false;
+ if (event != null) {
+ long time0 = event.getTime0();
+ long time1 = event.getTime1();
+ int dwidth = event.getWidth();
+
+ updated = update(time0, time1, dwidth);
+
+ // initialization only, otherwise wait for the actual selection
+ // event to update its value. Note that the time must be different
+ // upon selection of a new time in order to trigger an update to all
+ if (selectedTime == null) {
+ setSelectedTime(event.getSelectedTime());
+ }
+
+ }
+
+ return updated;
+
+ }
+
+ /**
+ * Save the selected time
+ * @param selTime
+ */
+ public void setSelectedTime(long selTime) {
+ TraceDebug.debug("Selected time changed from: \n\t" + selectedTime
+ + " to: \n\t" + selTime);
+ selectedTime = selTime;
+ }
+
+ /**
+ * May return null, if the selected time is invalid
+ *
+ * @return
+ */
+ public Long getSelectedTime() {
+ return selectedTime;
+ }
+
+ /**
+ * Update time range but keep width as is
+ *
+ * @param time0
+ * @param time1
+ * @return
+ */
+ public boolean update(long time0, long time1) {
+ return update(time0, time1, width);
+ }
+
+ /**
+ * Only positive attributes are expected
+ *
+ * @param time0
+ * @param time1
+ * @param dwidth
+ * @return
+ */
+ public boolean update(long time0, long time1, int dwidth) {
+ boolean updated = false;
+
+ if (time0 == startTime && time1 == endTime && dwidth == width) {
+ // No updated needed
+ return updated;
+ }
+
+ // Negatives are invalid
+ time0 = time0 > 0 ? time0 : 0;
+ time1 = time1 > 0 ? time1 : 0;
+ dwidth = dwidth > 0 ? dwidth : 0;
+
+ if (time1 > time0) {
+ // Store the new values as long as they are within range
+ startTime = time0;
+ endTime = time1;
+ width = dwidth;
+
+ pixelsPerNs = (double) width / (double) (endTime - startTime);
+
+ TmfTimestamp fTimeStart = new LttngTimestamp(startTime);
+ TmfTimestamp fTimeEnd = new LttngTimestamp(endTime);
+ trange = new TmfTimeRange(fTimeStart, fTimeEnd);
+
+ // make sure the selected time is within the new range or else set
+ // mark it as invalid
+ if (selectedTime != null) {
+ setSelectedTime(selectedTime);
+ }
+
+ // update succeeded
+ updated = true;
+
+ TraceDebug.debug("Configuration updated to: StartTime: " /* */
+ + fTimeStart /* */
+ + "-" /* */
+ + fTimeEnd /* */
+ + " width: " /* */
+ + width + " k: " + pixelsPerNs); /* */
+ } else {
+ TraceDebug
+ .debug("End time is not greater than start time, start time: "
+ + time0 + " end time: " + time1);
+ }
+
+ return updated;
+ }
+
+ /**
+ * @return
+ */
+ public long getStartTime() {
+ return startTime;
+ }
+
+ /**
+ * @return
+ */
+ public long getEndTime() {
+ return endTime;
+ }
+
+ /**
+ * @return
+ */
+ public int getWidth() {
+ if (width == 0) {
+ TraceDebug
+ .debug("Unexpected width value of 0 pixels, returning default");
+ return DEFAULT_WIDTH;
+ }
+
+ return width;
+ }
+
+ /**
+ * Return the current constant "K" of pixels per nano second used for the
+ * widest time space widget registered in this instance.
+ *
+ * @return
+ */
+ public double getPixelsPerNs() {
+ return pixelsPerNs;
+ }
+
+ /**
+ * Set the value of pixels per nano second as long as the value is grater
+ * positive
+ *
+ * @return
+ */
+ public void setPixelsPerNs(double pixperNsec) {
+ if (pixperNsec > 0) {
+ pixelsPerNs = pixperNsec;
+ }
+ }
+
+ /**
+ * @param value
+ */
+ public void setEventsDiscarded(int value) {
+ eventsDiscarded = value;
+ if (value == 0) {
+ eventsDiscardedWrongOrder = 0;
+ }
+ }
+
+ /**
+ *
+ */
+ public void incrementEventsDiscarded() {
+ this.eventsDiscarded++;
+ }
+
+ /**
+ * @return
+ */
+ public int getEventsDiscarded() {
+ return eventsDiscarded;
+ }
+
+ /**
+ * increase the number of events discarder since they were not received in a
+ * later time than previous events
+ */
+ public void incrementEventsDiscardedWrongOrder() {
+ this.eventsDiscarded++;
+ this.eventsDiscardedWrongOrder++;
+ }
+
+ /**
+ * @return
+ */
+ public int getEventsDiscardedWrongOrder() {
+ return eventsDiscardedWrongOrder;
+
+ }
+
+ /**
+ * @return
+ */
+ public TmfTimeRange getTrange() {
+ return trange;
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.control;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.part.ViewPart;
+
+/**
+ * <b><u>ControlView</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+public class ControlView extends ViewPart {
+
+ public static final String ID = "org.eclipse.linuxtools.lttng.ui.views.control";
+
+ /**
+ *
+ */
+ public ControlView() {
+ // TODO Auto-generated constructor stub
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
+ */
+ @Override
+ public void createPartControl(Composite parent) {
+ // TODO Auto-generated method stub
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
+ */
+ @Override
+ public void setFocus() {
+ // TODO Auto-generated method stub
+
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors: Alvaro Sanchez-Leon - Initial implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.controlflow;
+
+import java.util.Vector;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.linuxtools.lttng.event.LttngTimestamp;
+import org.eclipse.linuxtools.lttng.request.ILttngSyntEventRequest;
+import org.eclipse.linuxtools.lttng.state.evProcessor.ITransEventProcessor;
+import org.eclipse.linuxtools.lttng.ui.TraceDebug;
+import org.eclipse.linuxtools.lttng.ui.model.trange.ItemContainer;
+import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEventProcess;
+import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeViewerProvider;
+import org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView;
+import org.eclipse.linuxtools.lttng.ui.views.common.ParamsUpdater;
+import org.eclipse.linuxtools.lttng.ui.views.controlflow.evProcessor.FlowEventToHandlerFactory;
+import org.eclipse.linuxtools.lttng.ui.views.controlflow.model.FlowModelFactory;
+import org.eclipse.linuxtools.tmf.event.TmfEvent;
+import org.eclipse.linuxtools.tmf.event.TmfTimeRange;
+import org.eclipse.linuxtools.tmf.experiment.TmfExperiment;
+import org.eclipse.linuxtools.tmf.signal.TmfExperimentSelectedSignal;
+import org.eclipse.linuxtools.tmf.signal.TmfRangeSynchSignal;
+import org.eclipse.linuxtools.tmf.signal.TmfSignalHandler;
+import org.eclipse.linuxtools.tmf.signal.TmfTimeSynchSignal;
+import org.eclipse.linuxtools.tmf.ui.viewers.TmfViewerFactory;
+import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.ITmfTimeFilterSelectionListener;
+import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.ITmfTimeScaleSelectionListener;
+import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.ITmfTimeSelectionListener;
+import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeFilterSelectionEvent;
+import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeScaleSelectionEvent;
+import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeSelectionEvent;
+import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITmfTimeAnalysisEntry;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.custom.ScrolledComposite;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.ScrollBar;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IWorkbenchActionConstants;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+
+/**
+ * <b><u>ControlFlowView</u></b>
+ */
+/**
+ * @author alvaro
+ *
+ */
+public class ControlFlowView extends AbsTimeUpdateView implements
+ ITmfTimeSelectionListener, ITmfTimeScaleSelectionListener,
+ ITmfTimeFilterSelectionListener {
+
+ public static final String ID = "org.eclipse.linuxtools.lttng.ui.views.controlflow";
+
+ // ========================================================================
+ // Table data
+ // ========================================================================
+ private final String PROCESS_COLUMN = "Process";
+ private final String BRAND_COLUMN = "Brand";
+ private final String PID_COLUMN = "PID";
+ private final String TGID_COLUMN = "TGID";
+ private final String PPID_COLUMN = "PPID";
+ private final String CPU_COLUMN = "CPU";
+ private final String BIRTH_SEC_COLUMN = "Birth sec";
+ private final String BIRTH_NSEC_COLUMN = "Birth nsec";
+ private final String TRACE = "TRACE";
+
+ private final String[] columnNames = new String[] { PROCESS_COLUMN, /* */
+ BRAND_COLUMN,/* */
+ PID_COLUMN,/* */
+ TGID_COLUMN,/* */
+ PPID_COLUMN,/* */
+ CPU_COLUMN, /* */
+ BIRTH_SEC_COLUMN,/* */
+ BIRTH_NSEC_COLUMN,/* */
+ TRACE /* */
+ };
+
+ // ========================================================================
+ // Data
+ // ========================================================================
+ private TableViewer tableViewer;
+ // private int totalNumItems = 0;
+ // Actions
+ private Action doubleClickAction;
+ private Action resetScale;
+ private Action nextEvent;
+ private Action prevEvent;
+ private Action nextTrace;
+ private Action prevTrace;
+ private Action showLegend;
+ private Action filterTraces;
+ private Action zoomIn;
+ private Action zoomOut;
+ private Action zoomFilter;
+
+ private ViewProcessFilter tableFilter = null;
+ private ScrolledComposite scrollFrame = null;
+
+ // private static SimpleDateFormat stimeformat = new SimpleDateFormat(
+ // "yy/MM/dd HH:mm:ss");
+
+ // private TraceModelImplFactory fact;
+
+ // ========================================================================
+ // Methods
+ // ========================================================================
+ /*
+ * The content provider class is responsible for providing objects to the
+ * view. It can wrap existing objects in adapters or simply return objects
+ * as-is. These objects may be sensitive to the current input of the view,
+ * or ignore it and always show the same content (like Task List, for
+ * example).
+ */
+
+ class ViewContentProvider implements
+ /* ILazyContentProvider, */IStructuredContentProvider {
+ private TableViewer cviewer = null;
+ private ITmfTimeAnalysisEntry[] elements = null;
+
+ public ViewContentProvider(TableViewer v) {
+ cviewer = v;
+ }
+
+ public void inputChanged(Viewer v, Object oldInput, Object newInput) {
+ this.elements = (ITmfTimeAnalysisEntry[]) newInput;
+ if (elements != null) {
+ TraceDebug.debug("Total number of processes provided to Control Flow view: " + elements.length);
+ } else {
+ TraceDebug.debug("New input = null");
+ }
+ }
+
+ public void dispose() {
+
+ }
+
+ // Needed with the use of virtual tables in order to initialize items
+ // which were not initially visible.
+ public void updateElement(int index) {
+ cviewer.replace(elements[index], index);
+ }
+
+ // @Override
+ public Object[] getElements(Object inputElement) {
+ return elements;
+ }
+ }
+
+ class ViewLabelProvider extends LabelProvider implements
+ ITableLabelProvider {
+ public String getColumnText(Object obj, int index) {
+ String strRes = ""; //$NON-NLS-1$
+ LttngTimestamp time;
+ if (obj instanceof TimeRangeEventProcess) {
+ TimeRangeEventProcess process = (TimeRangeEventProcess) obj;
+ switch (index) {
+ case 0:
+ strRes = process.getName();
+ break;
+ case 1:
+ strRes = process.getBrand();
+ break;
+ case 2:
+ strRes = process.getPid().toString();
+ break;
+ case 3:
+ strRes = process.getTgid().toString();
+ break;
+ case 4:
+ strRes = process.getPpid().toString();
+ break;
+ case 5:
+ strRes = process.getCpu().toString();
+ break;
+ case 6:
+ time = new LttngTimestamp(process.getCreationTime()
+ .longValue());
+ strRes = time.getSeconds();
+ break;
+ case 7:
+ time = new LttngTimestamp(process.getCreationTime()
+ .longValue());
+ strRes = time.getNanoSeconds();
+ break;
+ case 8:
+ strRes = process.getTraceID();
+ break;
+ default:
+ break;
+ }
+ } else {
+ return getText(obj);
+ }
+
+ return strRes;
+ }
+
+ public Image getColumnImage(Object obj, int index) {
+ return getImage(obj);
+ }
+
+ @Override
+ public Image getImage(Object obj) {
+ // No image needed for the time being
+ // return PlatformUI.getWorkbench().getSharedImages().getImage(
+ // ISharedImages.IMG_OBJ_ELEMENT);
+ return null;
+ }
+ }
+
+ class ViewProcessFilter extends ViewerFilter {
+
+ private Vector<ITmfTimeAnalysisEntry> filteredSet = new Vector<ITmfTimeAnalysisEntry>();
+ StructuredViewer viewer;
+
+ public ViewProcessFilter(StructuredViewer rviewer) {
+ this.viewer = rviewer;
+ }
+
+ public void setFilter(Vector<ITmfTimeAnalysisEntry> filtered) {
+ if (filtered != null) {
+ this.filteredSet = filtered;
+ viewer.refresh();
+ }
+ }
+
+ @Override
+ public boolean select(Viewer viewer, Object parentElement,
+ Object element) {
+ boolean filteredIn = true;
+ if (element instanceof ITmfTimeAnalysisEntry) {
+ ITmfTimeAnalysisEntry process = (ITmfTimeAnalysisEntry) element;
+ if (filteredSet.contains(process)) {
+ // The element is marked to be filtered out
+ return false;
+ }
+ } else {
+ TraceDebug.debug("Unexpected type of filter element received: "
+ + element.toString());
+ }
+ // Compare element versus a list of filtered out
+ return filteredIn;
+ }
+ }
+
+ /**
+ * The constructor.
+ */
+ public ControlFlowView() {
+ super(ID);
+ }
+
+ /**
+ * This is a callback that will allow us to create the viewer and initialize
+ * it.
+ */
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.linuxtools.tmf.ui.views.TmfView#createPartControl(org.eclipse
+ * .swt.widgets.Composite)
+ */
+ @Override
+ public void createPartControl(Composite parent) {
+
+ scrollFrame = new ScrolledComposite(parent, SWT.V_SCROLL);
+
+ scrollFrame.setExpandVertical(true);
+ scrollFrame.setExpandHorizontal(true);
+ scrollFrame.setAlwaysShowScrollBars(true);
+
+ SashForm sash = new SashForm(scrollFrame, SWT.NONE);
+ scrollFrame.setContent(sash);
+
+ tableViewer = new TableViewer(sash, SWT.FULL_SELECTION | SWT.H_SCROLL);
+ tableViewer.setContentProvider(new ViewContentProvider(tableViewer));
+ tableViewer.setLabelProvider(new ViewLabelProvider());
+ Table table = tableViewer.getTable();
+ tableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent event) {
+ ISelection sel = event.getSelection();
+ if (!sel.isEmpty()) {
+ Object firstSel = null;
+ if (sel instanceof IStructuredSelection) {
+ firstSel = ((IStructuredSelection) sel).getFirstElement();
+
+ // Make sure the selection is visible
+ updateScrollOrigin();
+
+ if (firstSel instanceof ITmfTimeAnalysisEntry) {
+ ITmfTimeAnalysisEntry trace = (ITmfTimeAnalysisEntry) firstSel;
+ tsfviewer.setSelectedTrace(trace);
+ }
+ }
+ }
+ }
+
+ /**
+ * Make sure the selected item is visible
+ */
+ private void updateScrollOrigin() {
+ Table table = tableViewer.getTable();
+ if (table != null && table.getItemCount() > 0) {
+ TableItem item = table.getSelection()[0];
+ if (item == null) {
+ // no selected reference to go up or down
+ return;
+ }
+
+ Rectangle itemRect = item.getBounds();
+ int step = itemRect.height;
+
+ // calculate height of horizontal bar
+ int hscrolly = 0;
+ ScrollBar hbar = scrollFrame.getHorizontalBar();
+ if (hbar != null) {
+ hscrolly = hbar.getSize().y;
+ }
+
+ int visibleHeight = scrollFrame.getSize().y - hscrolly;
+
+ // the current scrollbar offset to adjust i.e. start
+ // of
+ // the visible window
+ Point origin = scrollFrame.getOrigin();
+ // end of visible window
+ int endy = origin.y + visibleHeight;
+
+ int itemStartPos = itemRect.y + table.getHeaderHeight() + table.getBorderWidth()
+ + table.getParent().getBorderWidth();
+
+ // Item End Position
+ int itemEndPos = itemStartPos + step;
+
+ // check if need to go up
+ if (origin.y >= step && itemStartPos < origin.y) {
+ // one step up
+ scrollFrame.setOrigin(origin.x, origin.y - step);
+
+ }
+
+ // check if it needs to go down
+ if (itemEndPos > endy) {
+ // one step down
+ scrollFrame.setOrigin(origin.x, origin.y + step);
+
+ }
+ }
+ }
+ });
+
+ // Listen to page up /down and Home / Enc keys
+ tableViewer.getTable().addKeyListener(new KeyListener() {
+ public void keyPressed(KeyEvent e) {
+ Table table = tableViewer.getTable();
+ Point origin = scrollFrame.getOrigin();
+ if (table == null || table.getItemCount() < 1) {
+ // nothing to page
+ return;
+ }
+
+ TableItem item;
+ int count;
+
+ switch (e.keyCode) {
+ case SWT.PAGE_DOWN:
+ updateScrollPageDown();
+ break;
+ case SWT.PAGE_UP:
+ updateScrollUp();
+ break;
+ case SWT.HOME:
+ // Home
+ count = table.getItemCount();
+ item = table.getItem(0);
+ // Go to the top
+ scrollFrame.setOrigin(origin.x, 0);
+ break;
+ case SWT.END:
+ // End Selected
+ count = table.getItemCount();
+ item = table.getItem(count - 1);
+ int itemStartPos = item.getBounds().y;
+ // Get to the bottom
+ scrollFrame.setOrigin(origin.x, itemStartPos);
+ break;
+ default:
+ break;
+ }
+ }
+
+ public void keyReleased(KeyEvent e) {
+ // Nothing to do
+
+ }
+
+ /**
+ * Scroll one page down
+ */
+ private void updateScrollPageDown() {
+ // null protection before calling private method
+ Table table = tableViewer.getTable();
+ int step = table.getItemHeight();
+
+ int hscrolly = 0;
+ ScrollBar hbar = scrollFrame.getHorizontalBar();
+ if (hbar != null) {
+ hscrolly = hbar.getSize().y;
+ }
+
+ Point origin = scrollFrame.getOrigin();
+ int visibleHeight = scrollFrame.getSize().y - hscrolly;
+ int endy = origin.y + visibleHeight;
+
+ scrollFrame.setOrigin(origin.x, endy - step);
+ }
+
+ /**
+ * Scroll one page up
+ */
+ private void updateScrollUp() {
+ // null protection before calling private method
+ Table table = tableViewer.getTable();
+ int step = table.getItemHeight();
+
+ int hscrolly = 0;
+ ScrollBar hbar = scrollFrame.getHorizontalBar();
+ if (hbar != null) {
+ hscrolly = hbar.getSize().y;
+ }
+
+ Point origin = scrollFrame.getOrigin();
+ int visibleHeight = scrollFrame.getSize().y - hscrolly;
+ int pageUpPos = origin.y - visibleHeight + step;
+ pageUpPos = pageUpPos > 0 ? pageUpPos : 0;
+ scrollFrame.setOrigin(origin.x, pageUpPos);
+ }
+
+ });
+ // Describe table
+ applyTableLayout(table);
+
+ int borderWidth = table.getBorderWidth();
+
+ int itemHeight = table.getItemHeight() + checkForSWTBugItemHeightAdjustement();
+ int headerHeight = table.getHeaderHeight();
+ table.getVerticalBar().setVisible(false);
+
+ tsfviewer = TmfViewerFactory.createViewer(sash,
+ new TimeRangeViewerProvider());
+
+ tsfviewer.addWidgetSelectionListner(this);
+ tsfviewer.addWidgetTimeScaleSelectionListner(this);
+
+ // Traces shall not be grouped to allow synchronisation
+ tsfviewer.groupTraces(false);
+ tsfviewer.setItemHeight(itemHeight);
+ tsfviewer.setBorderWidth(borderWidth);
+ tsfviewer.setHeaderHeight(headerHeight);
+ tsfviewer.setVisibleVerticalScroll(false);
+ // Names provided by the table
+ tsfviewer.setNameWidthPref(0);
+ tsfviewer.setAcceptSelectionAPIcalls(true);
+
+ // Viewer to notify selection to this class
+ // This class will synchronise selections with table.
+ tsfviewer.addWidgetSelectionListner(this);
+ tsfviewer.addFilterSelectionListner(this);
+ tsfviewer.addWidgetTimeScaleSelectionListner(this);
+
+ sash.setWeights(new int[] { 1, 1 });
+ // Create the help context id for the viewer's control
+ // TODO: Associate with help system
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(
+ tableViewer.getControl(),
+ "org.eclipse.linuxtools.lttnng.ui.views.flow.viewer"); //$NON-NLS-1$
+
+ makeActions();
+ hookContextMenu();
+ hookDoubleClickAction();
+ contributeToActionBars();
+
+ // scrollFrame.addControlListener(new ControlAdapter() {
+ //
+ // @Override
+ // public void controlResized(ControlEvent e) {
+ // tsfviewer.resizeControls();
+ // updateScrolls(scrollFrame);
+ // }
+ // });
+
+ // set the initial view parameter values
+ // Experiment start and end time
+ // as well as time space width in pixels, used by the time analysis
+ // widget
+ // Read relevant values
+ int timeSpaceWidth = tsfviewer.getTimeSpace();
+ if (timeSpaceWidth < 0) {
+ timeSpaceWidth = -timeSpaceWidth;
+ }
+
+ TmfExperiment<?> experiment = TmfExperiment.getCurrentExperiment();
+ if (experiment != null) {
+ TmfTimeRange experimentTRange = experiment.getTimeRange();
+
+ // send request and received the adjusted time used
+ TmfTimeRange adjustedTimeRange = initialExperimentDataRequest(this,
+ experimentTRange);
+
+ // initialize widget time boundaries and filtering parameters
+ ModelUpdateInit(experimentTRange, adjustedTimeRange, this);
+ } else {
+ TraceDebug.debug("No selected experiment information available");
+ }
+ }
+
+ private void hookContextMenu() {
+ MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$
+ menuMgr.setRemoveAllWhenShown(true);
+ menuMgr.addMenuListener(new IMenuListener() {
+ public void menuAboutToShow(IMenuManager manager) {
+ ControlFlowView.this.fillContextMenu(manager);
+ }
+ });
+ Menu menu = menuMgr.createContextMenu(tableViewer.getControl());
+ tableViewer.getControl().setMenu(menu);
+ getSite().registerContextMenu(menuMgr, tableViewer);
+ }
+
+ private void contributeToActionBars() {
+ IActionBars bars = getViewSite().getActionBars();
+ fillLocalPullDown(bars.getMenuManager());
+ fillLocalToolBar(bars.getToolBarManager());
+ }
+
+ private void fillLocalPullDown(IMenuManager manager) {
+ manager.add(new Separator());
+ // manager.add(showLegend);
+ manager.add(new Separator());
+ manager.add(resetScale);
+ manager.add(nextEvent);
+ manager.add(prevEvent);
+ manager.add(nextTrace);
+ manager.add(prevTrace);
+ // manager.add(filterTraces);
+ manager.add(zoomIn);
+ manager.add(zoomOut);
+ manager.add(zoomFilter);
+ manager.add(new Separator());
+ }
+
+ private void fillContextMenu(IMenuManager manager) {
+ // manager.add(showLegend);
+ manager.add(new Separator());
+ manager.add(resetScale);
+ manager.add(nextEvent);
+ manager.add(prevEvent);
+ manager.add(nextTrace);
+ manager.add(prevTrace);
+ // manager.add(showLegend);
+ // manager.add(filterTraces);
+ manager.add(zoomIn);
+ manager.add(zoomOut);
+ manager.add(zoomFilter);
+ manager.add(new Separator());
+ manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
+ }
+
+ private void fillLocalToolBar(IToolBarManager manager) {
+ // manager.add(showLegend);
+ manager.add(new Separator());
+ manager.add(resetScale);
+ manager.add(nextEvent);
+ manager.add(prevEvent);
+ manager.add(nextTrace);
+ manager.add(prevTrace);
+ // manager.add(filterTraces);
+ manager.add(zoomIn);
+ manager.add(zoomOut);
+ manager.add(zoomFilter);
+ manager.add(new Separator());
+ }
+
+ private void makeActions() {
+ // resetScale
+ resetScale = new Action() {
+ @Override
+ public void run() {
+ if (tsfviewer != null) {
+ tsfviewer.resetStartFinishTime();
+ }
+
+ }
+ };
+ resetScale.setText(Messages.getString("ControlFlowView.Action.Reset")); //$NON-NLS-1$
+ resetScale.setToolTipText(Messages
+ .getString("ControlFlowView.Action.Reset.ToolTip")); //$NON-NLS-1$
+ resetScale.setImageDescriptor(AbstractUIPlugin
+ .imageDescriptorFromPlugin(Messages
+ .getString("ControlFlowView.tmf.UI"),
+ "icons/home_nav.gif"));
+
+ // nextEvent
+ nextEvent = new Action() {
+ @Override
+ public void run() {
+ if (tsfviewer != null) {
+ tsfviewer.selectNextEvent();
+ }
+ }
+ };
+ nextEvent.setText(Messages
+ .getString("ControlFlowView.Action.NextEvent")); //$NON-NLS-1$
+ nextEvent.setToolTipText(Messages
+ .getString("ControlFlowView.Action.NextEvent.Tooltip")); //$NON-NLS-1$
+ nextEvent.setImageDescriptor(AbstractUIPlugin
+ .imageDescriptorFromPlugin(Messages
+ .getString("ControlFlowView.tmf.UI"),
+ "icons/next_event.gif"));
+
+ // prevEvent
+ prevEvent = new Action() {
+ @Override
+ public void run() {
+ if (tsfviewer != null) {
+ tsfviewer.selectPrevEvent();
+ }
+ }
+ };
+ prevEvent.setText(Messages
+ .getString("ControlFlowView.Action.PrevEvent")); //$NON-NLS-1$
+ prevEvent.setToolTipText(Messages
+ .getString("ControlFlowView.Action.PrevEvent.Tooltip")); //$NON-NLS-1$
+ prevEvent.setImageDescriptor(AbstractUIPlugin
+ .imageDescriptorFromPlugin(Messages
+ .getString("ControlFlowView.tmf.UI"),
+ "icons/prev_event.gif"));
+
+ // nextTrace
+ nextTrace = new Action() {
+ @Override
+ public void run() {
+ if (tsfviewer != null) {
+ tsfviewer.selectNextTrace();
+ }
+ }
+ };
+ nextTrace.setText(Messages
+ .getString("ControlFlowView.Action.NextProcess")); //$NON-NLS-1$
+ nextTrace.setToolTipText(Messages
+ .getString("ControlFlowView.Action.NextProcess.ToolTip")); //$NON-NLS-1$
+ nextTrace.setImageDescriptor(AbstractUIPlugin
+ .imageDescriptorFromPlugin(Messages
+ .getString("ControlFlowView.tmf.UI"),
+ "icons/next_item.gif"));
+
+ // prevTrace
+ prevTrace = new Action() {
+ @Override
+ public void run() {
+ if (tsfviewer != null) {
+ tsfviewer.selectPrevTrace();
+ }
+ }
+ };
+ prevTrace.setText(Messages
+ .getString("ControlFlowView.Action.PreviousProcess")); //$NON-NLS-1$
+ prevTrace.setToolTipText(Messages
+ .getString("ControlFlowView.Action.PreviousProcess.Tooltip")); //$NON-NLS-1$
+ prevTrace.setImageDescriptor(AbstractUIPlugin
+ .imageDescriptorFromPlugin(Messages
+ .getString("ControlFlowView.tmf.UI"),
+ "icons/prev_item.gif"));
+
+ // showLegend
+ showLegend = new Action() {
+ @Override
+ public void run() {
+ if (tsfviewer != null) {
+ tsfviewer.showLegend();
+ }
+ }
+ };
+ showLegend.setText(Messages.getString("ControlFlowView.Action.Legend")); //$NON-NLS-1$
+ showLegend.setToolTipText(Messages
+ .getString("ControlFlowView.Action.Legend.ToolTip")); //$NON-NLS-1$
+
+ // filterTraces
+ filterTraces = new Action() {
+ @Override
+ public void run() {
+ if (tsfviewer != null) {
+ tsfviewer.filterTraces();
+ }
+ }
+ };
+ filterTraces.setText(Messages
+ .getString("ControlFlowView.Action.Filter")); //$NON-NLS-1$
+ filterTraces.setToolTipText(Messages
+ .getString("ControlFlowView.Action.Filter.ToolTip")); //$NON-NLS-1$
+ filterTraces.setImageDescriptor(AbstractUIPlugin
+ .imageDescriptorFromPlugin(Messages
+ .getString("ControlFlowView.tmf.UI"),
+ "icons/filter_items.gif"));
+
+ // zoomIn
+ zoomIn = new Action() {
+ @Override
+ public void run() {
+ if (tsfviewer != null) {
+ tsfviewer.zoomIn();
+ }
+ }
+ };
+ zoomIn.setText(Messages.getString("ControlFlowView.Action.ZoomIn")); //$NON-NLS-1$
+ zoomIn.setToolTipText(Messages
+ .getString("ControlFlowView.Action.ZoomIn.Tooltip")); //$NON-NLS-1$
+ zoomIn.setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(
+ Messages.getString("ControlFlowView.tmf.UI"),
+ "icons/zoomin_nav.gif"));
+
+ // zoomOut
+ zoomOut = new Action() {
+ @Override
+ public void run() {
+ if (tsfviewer != null) {
+ tsfviewer.zoomOut();
+ }
+ }
+ };
+ zoomOut.setText(Messages.getString("ControlFlowView.Action.ZoomOut")); //$NON-NLS-1$
+ zoomOut.setToolTipText(Messages
+ .getString("ControlFlowView.Action.ZoomOut.tooltip")); //$NON-NLS-1$
+ zoomOut.setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(
+ Messages.getString("ControlFlowView.tmf.UI"),
+ "icons/zoomout_nav.gif"));
+
+ // zoomFilter
+ zoomFilter = new Action() {
+ @Override
+ public void run() {
+ // Nothing to do, however the selection status is needed by the
+ // application
+ }
+ };
+ zoomFilter.setText(Messages
+ .getString("ControlFlowView.Action.ZoomFilter")); //$NON-NLS-1$
+ zoomFilter.setToolTipText(Messages
+ .getString("ControlFlowView.Action.ZoomFilter.tooltip")); //$NON-NLS-1$
+ zoomFilter.setImageDescriptor(AbstractUIPlugin
+ .imageDescriptorFromPlugin(Messages
+ .getString("ControlFlowView.tmf.UI"),
+ "icons/filter_items.gif"));
+ zoomFilter.setChecked(false);
+
+ // PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_ELCL_SYNCED);
+
+ doubleClickAction = new Action() {
+ @Override
+ public void run() {
+ ISelection selection = tableViewer.getSelection();
+ Object obj = ((IStructuredSelection) selection)
+ .getFirstElement();
+ showMessage("Double-click detected on " + obj.toString()); //$NON-NLS-1$
+ }
+ };
+ }
+
+ private void hookDoubleClickAction() {
+ tableViewer.addDoubleClickListener(new IDoubleClickListener() {
+ public void doubleClick(DoubleClickEvent event) {
+ doubleClickAction.run();
+ }
+ });
+ }
+
+ private void showMessage(String message) {
+ MessageDialog.openInformation(tableViewer.getControl().getShell(),
+ Messages.getString("ControlFlowView.msgSlogan"), message); //$NON-NLS-1$
+ }
+
+ /**
+ * Passing the focus request to the viewer's control.
+ */
+ @Override
+ public void setFocus() {
+ tableViewer.getControl().setFocus();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView#
+ * tsfTmProcessSelEvent
+ * (org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeSelectionEvent
+ * )
+ */
+ public void tsfTmProcessSelEvent(TmfTimeSelectionEvent event) {
+ // common implementation
+ super.tsfTmProcessSelEvent(event);
+
+ // Reselect the table viewer to widget selection
+ ISelection sel = tsfviewer.getSelectionTrace();
+ if (sel != null && !sel.isEmpty()) {
+ tableViewer.setSelection(sel);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.
+ * ITmfTimeScaleSelectionListener
+ * #tsfTmProcessTimeScaleEvent(org.eclipse.linuxtools
+ * .tmf.ui.viewers.timeAnalysis.TmfTimeScaleSelectionEvent)
+ */
+ public synchronized void tsfTmProcessTimeScaleEvent(TmfTimeScaleSelectionEvent event) {
+ super.tsfTmProcessTimeScaleEvent(event);
+ }
+
+ private void applyTableLayout(Table table) {
+ for (int i = 0; i < columnNames.length; i++) {
+ TableColumn tableColumn = new TableColumn(table, SWT.LEFT);
+ tableColumn.setText(columnNames[i]);
+ tableColumn.pack();
+ }
+ table.setHeaderVisible(true);
+ table.setLinesVisible(true);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView#displayModel
+ * (org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.
+ * ITmfTimeAnalysisEntry[], long, long, boolean, long, long,
+ * java.lang.Object)
+ */
+ public void displayModel(final ITmfTimeAnalysisEntry[] items,
+ final long startBoundTime, final long endBoundTime,
+ final boolean updateTimeBounds, final long startVisibleWindow,
+ final long endVisibleWindow, final Object source) {
+ final Table table = tableViewer.getTable();
+ Display display = table.getDisplay();
+
+ // Perform the updates on the UI thread)
+ display.asyncExec(new Runnable() {
+ public void run() {
+
+ tableViewer.setInput(items); // This shall be the minimal
+ // initial
+ tableFilter = new ViewProcessFilter(tableViewer);
+ tableViewer.setFilters(new ViewerFilter[] { tableFilter });
+
+ resizeTableColumns(table);
+ table.update();
+ tableViewer.refresh();
+
+ tsfviewer.display(items, startBoundTime, endBoundTime,
+ updateTimeBounds);
+
+ // validate visible boundaries
+ if (startVisibleWindow > -1 && endVisibleWindow > -1) {
+ tsfviewer.setSelectVisTimeWindow(startVisibleWindow,
+ endVisibleWindow, source);
+ }
+
+ tsfviewer.resizeControls();
+
+ // Adjust the size of the vertical scroll bar to fit the
+ // contents
+ if (scrollFrame != null) {
+ updateScrolls(scrollFrame);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void dispose() {
+ // dispose parent resources
+ super.dispose();
+
+ tsfviewer.removeFilterSelectionListner(this);
+ tsfviewer.removeWidgetSelectionListner(this);
+ tsfviewer.removeWidgetTimeScaleSelectionListner(this);
+ tableViewer = null;
+ tsfviewer = null;
+ }
+
+ /**
+ * @param tableComposite
+ * @param table
+ */
+ private synchronized void resizeTableColumns(Table table) {
+ if (table != null) {
+ Composite parent = table.getParent();
+ int tableWidthSum = parent.getBorderWidth();
+
+ TableColumn[] columns = table.getColumns();
+ for (TableColumn column : columns) {
+ column.pack();
+ tableWidthSum += column.getWidth();
+ }
+ }
+ }
+
+ // @Override
+ public void tmfTaProcessFilterSelection(TmfTimeFilterSelectionEvent event) {
+ if (tableFilter != null) {
+ Vector<ITmfTimeAnalysisEntry> filteredout = event.getFilteredOut();
+ if (filteredout != null) {
+ tableFilter.setFilter(filteredout);
+ } else {
+ tableFilter.setFilter(new Vector<ITmfTimeAnalysisEntry>());
+ }
+ tableViewer.refresh();
+ }
+ }
+
+ /**
+ * @param scrollFrame
+ * @param wrapper
+ */
+ private void updateScrolls(final ScrolledComposite scrollFrame) {
+ scrollFrame.setMinSize(tableViewer.getTable().computeSize(SWT.DEFAULT, SWT.DEFAULT));
+ }
+
+ /**
+ * Registers as listener of time selection from other views
+ *
+ * @param signal
+ */
+ @TmfSignalHandler
+ public void synchToTime(TmfTimeSynchSignal signal) {
+ super.synchToTime(signal);
+ }
+
+ /**
+ * Annotation Registers as listener of time range selection from other views
+ * The implementation handles the entry of the signal.
+ *
+ * @param signal
+ */
+ @TmfSignalHandler
+ public void synchToTimeRange(TmfRangeSynchSignal signal) {
+ if (zoomFilter != null) {
+ synchToTimeRange(signal, zoomFilter.isChecked());
+ }
+ }
+
+ @Override
+ public void modelIncomplete(ILttngSyntEventRequest request) {
+ // Nothing to do
+ // The data will be refreshed on the next request
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView#
+ * getEventProcessor()
+ */
+ @Override
+ public ITransEventProcessor getEventProcessor() {
+ return FlowEventToHandlerFactory.getInstance();
+ }
+
+ /**
+ * @param signal
+ */
+ @TmfSignalHandler
+ public void experimentSelected(
+ TmfExperimentSelectedSignal<? extends TmfEvent> signal) {
+ if (signal != null) {
+ TmfTimeRange experimentTRange = signal.getExperiment()
+ .getTimeRange();
+
+ // prepare time intervals in widget
+ ModelUpdateInit(experimentTRange, experimentTRange, signal
+ .getSource());
+
+ // request initial data
+ initialExperimentDataRequest(signal
+ .getSource(), experimentTRange);
+ }
+ }
+
+ /**
+ * @param source
+ * @param experimentTRange
+ * @return Adjusted time window used for the request (smaller window to
+ * initialize view)
+ */
+ private TmfTimeRange initialExperimentDataRequest(Object source,
+ TmfTimeRange experimentTRange) {
+ // Adjust the initial time window to a shorter interval to allow
+ // user to select the interesting area based on the perspective
+ TmfTimeRange initTimeWindow = getInitTRange(experimentTRange);
+
+ dataRequest(initTimeWindow, experimentTRange, true);
+ if (TraceDebug.isDEBUG()) {
+ TraceDebug.debug("Initialization request time range is: "
+ + initTimeWindow.getStartTime().toString() + "-"
+ + initTimeWindow.getEndTime().toString());
+ }
+
+ return initTimeWindow;
+ }
+
+ // *** HACK ***
+ //
+ //
+ //
+ public int checkForSWTBugItemHeightAdjustement() {
+ int returnedAjustement = 0;
+ String desktopSessionName = System.getenv("DESKTOP_SESSION");
+
+ // Gnome : most common case, no adjustement
+ if ( desktopSessionName.equals("gnome") ) {
+ returnedAjustement = 0;
+ }
+ // Kde : ajustement of 2 is needed
+ else if ( desktopSessionName.equals("kde") ) {
+ returnedAjustement = 2;
+ }
+
+ return returnedAjustement;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView#
+ * getParamsUpdater()
+ */
+ @Override
+ protected ParamsUpdater getParamsUpdater() {
+ return FlowModelFactory.getParamsUpdater();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView#
+ * getItemContainer()
+ */
+ @Override
+ protected ItemContainer<?> getItemContainer() {
+ return FlowModelFactory.getProcContainer();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2009 Ericsson\r
+ * \r
+ * All rights reserved. This program and the accompanying materials are\r
+ * made available under the terms of the Eclipse Public License v1.0 which\r
+ * accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ * \r
+ * Contributors:\r
+ * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation\r
+ *******************************************************************************/\r
+package org.eclipse.linuxtools.lttng.ui.views.controlflow;\r
+\r
+import java.util.MissingResourceException;\r
+import java.util.ResourceBundle;\r
+\r
+public class Messages {\r
+ private static final String BUNDLE_NAME = "org.eclipse.linuxtools.lttng.ui.views.controlflow.messages"; //$NON-NLS-1$\r
+\r
+ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle\r
+ .getBundle(BUNDLE_NAME);\r
+\r
+ private Messages() {\r
+ }\r
+\r
+ public static String getString(String key) {\r
+ try {\r
+ return RESOURCE_BUNDLE.getString(key);\r
+ } catch (MissingResourceException e) {\r
+ return '!' + key + '!';\r
+ }\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors: Alvaro Sanchez-Leon - Initial implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.controlflow.evProcessor;
+
+import java.util.Vector;
+
+import org.eclipse.linuxtools.lttng.state.StateStrings.ProcessStatus;
+import org.eclipse.linuxtools.lttng.state.evProcessor.ILttngEventProcessor;
+import org.eclipse.linuxtools.lttng.state.model.LttngProcessState;
+import org.eclipse.linuxtools.lttng.state.model.LttngTraceState;
+import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeComponent;
+import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEvent;
+import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEventProcess;
+import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEvent.Type;
+import org.eclipse.linuxtools.lttng.ui.views.common.AbsTRangeUpdate;
+import org.eclipse.linuxtools.lttng.ui.views.common.ParamsUpdater;
+import org.eclipse.linuxtools.lttng.ui.views.controlflow.model.FlowModelFactory;
+import org.eclipse.linuxtools.lttng.ui.views.controlflow.model.FlowProcessContainer;
+
+public abstract class AbsFlowTRangeUpdate extends AbsTRangeUpdate implements ILttngEventProcessor {
+
+ // ========================================================================
+ // Data
+ // =======================================================================
+
+ protected FlowProcessContainer procContainer = FlowModelFactory.getProcContainer();
+ protected ParamsUpdater params = FlowModelFactory.getParamsUpdater();
+ protected static final Long ANY_CPU = 0L;
+
+
+ // ========================================================================
+ // Methods
+ // =======================================================================
+ protected TimeRangeEventProcess addLocalProcess(LttngProcessState stateProcess, long traceStartTime, long traceEndTime, String traceId) {
+ // TimeRangeEventProcess localProcess = new TimeRangeEventProcess(id, name, startTime, stopTime, groupName, className)
+ TimeRangeEventProcess localProcess = new TimeRangeEventProcess(
+ procContainer.getUniqueId(), stateProcess.getName(),
+ traceStartTime, traceEndTime, "", stateProcess.getType()
+ .getInName(), stateProcess.getCpu(), stateProcess
+ .getInsertion_time());
+
+
+ localProcess.setCreationTime(stateProcess.getCreation_time());
+ localProcess.setPid(stateProcess.getPid());
+ localProcess.setTgid(stateProcess.getTgid());
+ localProcess.setPpid(stateProcess.getPpid());
+ localProcess.setName(stateProcess.getName());
+ localProcess.setBrand(stateProcess.getBrand());
+ localProcess.setTraceID(traceId);
+ localProcess.setProcessType(stateProcess.getType().getInName());
+ procContainer.addItem(localProcess);
+ return localProcess;
+ }
+
+ /**
+ * Used to check if the event is visible within the current visible time
+ * window
+ *
+ * @return
+ */
+ protected boolean withinViewRange(long stime, long etime) {
+ long windowStartTime = params.getStartTime();
+ long windowEndTime = params.getEndTime();
+
+ // start time is within window
+ if (stime >= windowStartTime && stime <= windowEndTime) {
+ // The event or part of it shall be displayed.
+ return true;
+ }
+
+ // end time is within window
+ if (etime >= windowStartTime && etime <= windowEndTime) {
+ // The event or part of it shall be displayed.
+ return true;
+ }
+
+ // check that a portion is within the window
+ if (stime < windowStartTime && etime > windowEndTime) {
+ // The time range is bigger than the selected time window and
+ // crosses it
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * @param traceSt
+ * @param startTime
+ * @param endTime
+ * @param localProcess
+ * @param params
+ * @param stateMode
+ * @return
+ */
+ protected boolean makeDraw(LttngTraceState traceSt, long startTime,
+ long endTime, TimeRangeEventProcess localProcess,
+ ParamsUpdater params, String stateMode) {
+
+ // Determine start and end times to establish duration
+ Long stime = startTime;
+ Long etime = endTime;
+
+ if (etime < stime) {
+ // Validate the sequential order of events
+ params.incrementEventsDiscardedWrongOrder();
+ return false;
+ }
+
+ // Store the next good time to start drawing the next event
+ // this is done this early to display an accurate start time of the
+ // first event
+ // within the display window
+ // ****** moved at the end since it produces gaps among the coloured rectangles
+ // localProcess.setNext_good_time(etime);
+ if (!withinViewRange(stime, etime)) {
+ // No use to process the event since it's outside
+ // the visible time range of the window
+ params.incrementEventsDiscarded();
+ return false;
+ }
+
+ // Determine if the time range event will fit it the current
+ // pixel map
+ double duration = etime - stime;
+ double k = getPixelsPerNs(traceSt, params);
+ double pixels = duration * k;
+
+ // Visibility check
+ // Display a "more information" indication by allowing non visible event
+ // as long as its previous event is visible.
+ boolean visible = true;
+ if (pixels < 1) {
+ boolean prevEventVisibility = true;
+ // Get the visibility indication on previous event for
+ // this process
+ Vector<TimeRangeComponent> inMemEvents = localProcess
+ .getTraceEvents();
+ if (inMemEvents.size() != 0) {
+ TimeRangeComponent prevEvent = inMemEvents.get(inMemEvents
+ .size() - 1);
+ prevEventVisibility = prevEvent.isVisible();
+
+ // if previous event visibility is false and the time span
+ // between events less than two pixels, there is no need to
+ // load it in memory i.e. not visible and a more indicator is
+ // within two pixels.
+ // return i.e. event discarded to free up memory
+ Long eventSpan = stime - prevEvent.getStartTime();
+ if (prevEventVisibility == false
+ && ((double) eventSpan * k) < 2) {
+
+ // discard the item
+ params.incrementEventsDiscarded();
+ return false;
+
+ }
+ }
+
+ // if previous event is visible, set this one to not
+ // visible and continue
+ visible = false;
+ }
+
+ // Create the time-range event
+ TimeRangeEvent time_window = new TimeRangeEvent(stime, etime,
+ localProcess, Type.PROCESS_MODE, stateMode);
+
+ time_window.setVisible(visible);
+ localProcess.getTraceEvents().add(time_window);
+ localProcess.setNext_good_time(etime);
+
+ return false;
+ }
+
+ /**
+ * @param traceSt
+ * @param evTime
+ * @param process
+ * @param localProcess
+ * @param params
+ * @return
+ */
+ protected boolean makeDraw(LttngTraceState traceSt, long evTime,
+ LttngProcessState process, TimeRangeEventProcess localProcess,
+ ParamsUpdater params) {
+
+ // TmfTimestamp stime = process.getState().getChange_LttTime();
+ long stime = localProcess.getNext_good_time();
+
+ String stateMode;
+ ProcessStatus procStatus = process.getState().getProc_status();
+ // Use Execution mode if process state is RUN otherwise use the actual
+ // process state,
+ // this selection will determine the actual color selected for the event
+ if (procStatus == ProcessStatus.LTTV_STATE_RUN) {
+ stateMode = process.getState().getExec_mode().getInName();
+ } else {
+ stateMode = procStatus.getInName();
+ }
+
+ return makeDraw(traceSt, stime, evTime, localProcess, params, stateMode);
+
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.controlflow.evProcessor;
+
+import org.eclipse.linuxtools.lttng.event.LttngEvent;
+import org.eclipse.linuxtools.lttng.state.StateStrings.Fields;
+import org.eclipse.linuxtools.lttng.state.evProcessor.ILttngEventProcessor;
+import org.eclipse.linuxtools.lttng.state.model.LttngProcessState;
+import org.eclipse.linuxtools.lttng.state.model.LttngTraceState;
+import org.eclipse.linuxtools.lttng.ui.TraceDebug;
+import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEventProcess;
+import org.eclipse.linuxtools.tmf.event.TmfTimeRange;
+
+/**
+ * Creates instances of specific after state update handlers, per corresponding
+ * event.
+ *
+ * @author alvaro
+ *
+ */
+class FlowAfterUpdateHandlers {
+ /**
+ * <p>
+ * Handles: LTT_EVENT_SCHED_SCHEDULE
+ * </p>
+ * Replace C function "after_schedchange_hook" in eventhooks.c
+ * <p>
+ * Fields: LTT_FIELD_PREV_PID, LTT_FIELD_NEXT_PID
+ * </p>
+ *
+ * @return
+ */
+ final ILttngEventProcessor getSchedChangeHandler() {
+ AbsFlowTRangeUpdate handler = new AbsFlowTRangeUpdate() {
+
+ // @Override
+ public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) {
+
+ // get event time, cpu, trace_number, process, pid
+ LttngProcessState process_in = traceSt.getRunning_process().get(trcEvent.getCpuId());
+
+ // pid_out is never used, even in LTTv!
+ //Long pid_out = getAFieldLong(trcEvent, traceSt, Fields.LTT_FIELD_PREV_PID);
+ Long pid_in = getAFieldLong(trcEvent, traceSt, Fields.LTT_FIELD_NEXT_PID);
+
+ if ( !(pid_in.equals(process_in.getPid())) ) {
+ TraceDebug.debug("pid_in != PID! (getSchedChangeHandler)");
+ }
+
+ //hashed_process_data = processlist_get_process_data(process_list,pid_out,process->cpu,&birth,trace_num);
+ TimeRangeEventProcess localProcess = procContainer.findProcess(process_in.getPid(), process_in.getCpu(), traceSt.getTraceId(),process_in.getCreation_time() );
+
+ if ( localProcess == null ) {
+ if ( (pid_in == 0) || (pid_in != process_in.getPpid()) ) {
+ TmfTimeRange timeRange = traceSt.getContext().getTraceTimeWindow();
+ localProcess = addLocalProcess(process_in, timeRange.getStartTime().getValue(), timeRange.getEndTime().getValue(), traceSt.getTraceId());
+ }
+ else {
+ TraceDebug
+ .debug("pid_in is not 0 or pid_in == PPID! (getSchedChangeHandler)");
+ }
+ }
+
+ // There is no drawing done by the C code below, only refreshing
+ // the references to the current hash data to make it ready for
+ // next event
+
+ // This current implementation does not support the use of
+ // current hashed data
+ // although an equivalent would be good in order to improve the
+ // time to find the currently running process per cpu.
+ /*
+ if(ltt_time_compare(hashed_process_data_in->next_good_time, evtime) <= 0)
+ {
+ TimeWindow time_window = lttvwindow_get_time_window(control_flow_data->tab);
+
+ #ifdef EXTRA_CHECK
+ if(ltt_time_compare(evtime, time_window.start_time) == -1 || ltt_time_compare(evtime, time_window.end_time) == 1)
+ return FALSE;
+ #endif //EXTRA_CHECK
+
+ Drawing_t *drawing = control_flow_data->drawing;
+ guint width = drawing->width;
+ guint new_x;
+
+ convert_time_to_pixels(time_window,evtime,width,&new_x);
+
+ if(hashed_process_data_in->x.middle != new_x) {
+ hashed_process_data_in->x.middle = new_x;
+ hashed_process_data_in->x.middle_used = FALSE;
+ hashed_process_data_in->x.middle_marked = FALSE;
+ }
+ }*/
+
+ return false;
+
+ }
+ };
+ return handler;
+ }
+
+ /**
+ * <p>
+ * Handles: LTT_EVENT_PROCESS_FORK
+ * </p>
+ * Replace C function "after_process_fork_hook" in eventhooks.c
+ * <p>
+ * Fields: LTT_FIELD_CHILD_PID
+ * </p>
+ *
+ * @return
+ */
+ final ILttngEventProcessor getProcessForkHandler() {
+ AbsFlowTRangeUpdate handler = new AbsFlowTRangeUpdate() {
+
+ // @Override
+ public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) {
+
+ Long child_pid = getAFieldLong(trcEvent, traceSt, Fields.LTT_FIELD_CHILD_PID);
+ LttngProcessState process_child = lttv_state_find_process(traceSt, trcEvent.getCpuId(), child_pid );
+
+ if ( process_child != null ) {
+ TimeRangeEventProcess localProcess = procContainer.findProcess(process_child.getPid(), process_child.getCpu(), traceSt.getTraceId(), process_child.getCreation_time() );
+
+ if ( localProcess == null ) {
+ if ( (child_pid == 0) || (child_pid != process_child.getPpid()) ) {
+ TmfTimeRange timeRange = traceSt.getContext().getTraceTimeWindow();
+ localProcess = addLocalProcess(process_child, timeRange.getStartTime().getValue(), timeRange.getEndTime().getValue(), traceSt.getTraceId());
+ }
+ else {
+ TraceDebug.debug("localProcess is null with child_pid not 0 or child_pid equals PPID (getProcessForkHandler)");
+ }
+ } else {
+ // If we found the process, the Ppid and the Tgid might
+ // be missing, let's add them
+ localProcess.setPpid(process_child.getPpid());
+ localProcess.setTgid(process_child.getTgid());
+ }
+ }
+ else {
+ TraceDebug.debug("process_child is null! (getProcessForkHandler)");
+ }
+
+ return false;
+ }
+ };
+ return handler;
+ }
+
+ /**
+ * <p>
+ * Handles: LTT_EVENT_PROCESS_EXIT
+ * </p>
+ * Replace C function "after_process_exit_hook" in eventhooks.c
+ *
+ * @return
+ */
+ final ILttngEventProcessor getProcessExitHandler() {
+ AbsFlowTRangeUpdate handler = new AbsFlowTRangeUpdate() {
+
+ // @Override
+ public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) {
+
+ LttngProcessState process = traceSt.getRunning_process().get(trcEvent.getCpuId());
+
+ if ( process != null ) {
+
+ // *** TODO: ***
+ // We shall look into a way to find the current process
+ // faster, see the c library
+ // (current_hash) in order to speed up the find. see c-code
+ // if(likely(process_list->current_hash_data[trace_num][cpu] != NULL) ){
+ // hashed_process_data = process_list->current_hash_data[trace_num][cpu];
+ // }
+ TimeRangeEventProcess localProcess = procContainer.findProcess(process.getPid(), process.getCpu(), traceSt.getTraceId(), process.getCreation_time());
+
+ if ( localProcess == null ) {
+ if ( (process.getPid() == 0) || (process.getPid() != process.getPpid()) ) {
+ TmfTimeRange timeRange = traceSt.getContext().getTraceTimeWindow();
+ localProcess = addLocalProcess(process, timeRange.getStartTime().getValue(), timeRange.getEndTime().getValue(), traceSt.getTraceId());
+ }
+ else {
+ TraceDebug.debug("process pid is not 0 or pid equals ppid! (getProcessExitHandler)");
+ }
+ }
+ }
+ else {
+ TraceDebug.debug("process is null! (getProcessExitHandler)");
+ }
+
+ return false;
+ }
+ };
+ return handler;
+ }
+
+
+ /**
+ * <p>
+ * Handles: LTT_EVENT_EXEC
+ * </p>
+ * Replace C function "after_fs_exec_hook" in eventhooks.c
+ *
+ * @return
+ */
+ final ILttngEventProcessor getProcessExecHandler() {
+ AbsFlowTRangeUpdate handler = new AbsFlowTRangeUpdate() {
+
+ // @Override
+ public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) {
+
+ LttngProcessState process = traceSt.getRunning_process().get(trcEvent.getCpuId());
+
+ if ( process != null ) {
+
+ TimeRangeEventProcess localProcess = procContainer.findProcess(process.getPid(), process.getCpu(), traceSt.getTraceId(), process.getCreation_time());
+
+ if ( localProcess == null ) {
+ if ( (process.getPid() == 0) || (process.getPid() != process.getPpid()) ) {
+ TmfTimeRange timeRange = traceSt.getContext().getTraceTimeWindow();
+ localProcess = addLocalProcess(process, timeRange.getStartTime().getValue(), timeRange.getEndTime().getValue(), traceSt.getTraceId());
+ }
+ else {
+ TraceDebug.debug("process pid is not 0 or pid equals ppid! (getProcessExecHandler)");
+ }
+ }
+ else {
+ // If we found the process, the name might be missing. Let's add it here.
+ localProcess.setName(process.getName());
+ }
+ }
+ else {
+ TraceDebug.debug("process is null! (getProcessExecHandler)");
+ }
+
+ return false;
+ }
+ };
+ return handler;
+ }
+
+ /**
+ * <p>
+ * LTT_EVENT_THREAD_BRAND
+ * </p>
+ * Replace C function "after_user_generic_thread_brand_hook" in eventhooks.c
+ *
+ * @return
+ */
+ final ILttngEventProcessor GetThreadBrandHandler() {
+ AbsFlowTRangeUpdate handler = new AbsFlowTRangeUpdate() {
+
+ // @Override
+ public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) {
+
+ LttngProcessState process = traceSt.getRunning_process().get(trcEvent.getCpuId());
+
+ if ( process != null ) {
+
+ // Similar to above comments, implement a faster way to find
+ // the local process
+ // if(likely(process_list->current_hash_data[trace_num][cpu] != NULL) ){
+ // hashed_process_data = process_list->current_hash_data[trace_num][cpu];
+ // }
+ TimeRangeEventProcess localProcess = procContainer.findProcess(process.getPid(), process.getCpu(), traceSt.getTraceId(), process.getCreation_time());
+
+ if ( localProcess == null ) {
+ if ( (process.getPid() == 0) || (process.getPid() != process.getPpid()) ) {
+ TmfTimeRange timeRange = traceSt.getContext().getTraceTimeWindow();
+ localProcess = addLocalProcess(process, timeRange.getStartTime().getValue(), timeRange.getEndTime().getValue(), traceSt.getTraceId());
+ }
+ else {
+ TraceDebug.debug("process pid is not 0 or pid equals ppid! (GetThreadBrandHandler)");
+ }
+ }
+ else {
+ // If we found the process, the brand might be missing
+ // on it, add it.
+ localProcess.setBrand(process.getBrand());
+ }
+ }
+ else {
+ TraceDebug.debug("process is null! (GetThreadBrandHandler)");
+ }
+
+ return false;
+
+ }
+ };
+ return handler;
+ }
+
+ /**
+ * <p>
+ * LTT_EVENT_PROCESS_STATE
+ * </p>
+ * Replace C function "after_event_enum_process_hook" in eventhooks.c
+ * <p>
+ * <p>
+ * Creates the processlist entry for the child process. Put the last
+ * position in x at the current time value.
+ * </p>
+ *
+ * <p>
+ * Fields: LTT_FIELD_PID
+ * </p>
+ *
+ * @return
+ */
+ final ILttngEventProcessor getEnumProcessStateHandler() {
+ AbsFlowTRangeUpdate handler = new AbsFlowTRangeUpdate() {
+
+ // @Override
+ public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) {
+
+ int first_cpu;
+ int nb_cpus;
+
+ Long pid_in = getAFieldLong(trcEvent, traceSt,
+ Fields.LTT_FIELD_PID);
+
+ // Lttv assume that pid_in will NEVER be null or incoherent
+ // What if ... ? (let's add some debug)
+ if ( pid_in != null ) {
+ if(pid_in == 0L) {
+ first_cpu = 0;
+ nb_cpus = traceSt.getNumberOfCPUs();
+ }
+ else {
+ first_cpu = ANY_CPU.intValue();
+ nb_cpus = ANY_CPU.intValue() + 1;
+ }
+
+ for (int cpu = first_cpu; cpu < nb_cpus; cpu++) {
+ LttngProcessState process_in = lttv_state_find_process(traceSt, trcEvent.getCpuId(), pid_in );
+
+ if ( process_in != null ) {
+ TimeRangeEventProcess localProcess = procContainer.findProcess(process_in.getPid(), process_in.getCpu(), traceSt.getTraceId(), process_in.getCreation_time());
+
+ if (localProcess == null) {
+ if ( (process_in.getPid() == 0) || (process_in.getPid() != process_in.getPpid()) ) {
+ TmfTimeRange timeRange = traceSt.getContext().getTraceTimeWindow();
+ localProcess = addLocalProcess(process_in, timeRange.getStartTime().getValue(), timeRange.getEndTime().getValue(), traceSt.getTraceId());
+ }
+ else {
+ TraceDebug.debug("process pid is not 0 or pid equals ppid! (getEnumProcessStateHandler)");
+ }
+ }
+ else {
+ // If the process was found, it might be missing informations, add it here
+ localProcess.setName(process_in.getName());
+ localProcess.setPpid(process_in.getPpid());
+ localProcess.setTgid(process_in.getTgid());
+ }
+ }
+ else {
+ TraceDebug.debug("process_in is null! This should never happen. (getEnumProcessStateHandler)");
+ }
+ }
+ }
+ else {
+ TraceDebug.debug("pid_in is null! This should never happen, really... (getEnumProcessStateHandler)");
+ }
+
+ return false;
+ }
+ };
+ return handler;
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.controlflow.evProcessor;
+
+import org.eclipse.linuxtools.lttng.event.LttngEvent;
+import org.eclipse.linuxtools.lttng.state.StateStrings.Fields;
+import org.eclipse.linuxtools.lttng.state.evProcessor.ILttngEventProcessor;
+import org.eclipse.linuxtools.lttng.state.model.LttngProcessState;
+import org.eclipse.linuxtools.lttng.state.model.LttngTraceState;
+import org.eclipse.linuxtools.lttng.ui.TraceDebug;
+import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEventProcess;
+import org.eclipse.linuxtools.tmf.event.TmfTimeRange;
+
+/**
+ * Creates instances of specific before state update handlers, per corresponding
+ * event.
+ *
+ * @author alvaro
+ *
+ */
+class FlowBeforeUpdateHandlers {
+ /**
+ * <p>
+ * Handles: LTT_EVENT_SYSCALL_ENTRY
+ * </p>
+ * Replace C function named "before_execmode_hook" in eventhooks.c
+ *
+ * @return
+ */
+ final ILttngEventProcessor getStateModesHandler() {
+ AbsFlowTRangeUpdate handler = new AbsFlowTRangeUpdate() {
+
+ // @Override
+ public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) {
+
+ Long cpu = trcEvent.getCpuId();
+ LttngProcessState stateProcess = traceSt.getRunning_process()
+ .get(cpu);
+ // TraceDebug.debug("Before handler called");
+ String traceId = traceSt.getTraceId();
+
+ if (stateProcess != null) {
+ // Find process within the list of registered time-range
+ // related
+ // processes
+
+ // key process attributes to look for it or store it
+ // are: pid, birth, trace_num, note: cpu not relevant since
+ // it
+ // may change
+ TimeRangeEventProcess localProcess = procContainer
+ .findProcess(stateProcess.getPid(), stateProcess.getCpu(), traceId, stateProcess
+ .getCreation_time());
+
+ // Add process to process list if not present
+ if (localProcess == null) {
+ TmfTimeRange timeRange = traceSt.getContext()
+ .getTraceTimeWindow();
+ localProcess = addLocalProcess(stateProcess, timeRange
+ .getStartTime().getValue(), timeRange
+ .getEndTime().getValue(), traceId);
+ }
+
+ // Do the actual drawing
+ makeDraw(traceSt, trcEvent.getTimestamp().getValue(),
+ stateProcess, localProcess, params);
+ } else {
+ TraceDebug
+ .debug("Running state process is null! (getStateModesHandler)");
+ }
+
+ return false;
+ }
+ };
+ return handler;
+ }
+
+ /**
+ * <p>
+ * Handles: LTT_EVENT_SCHED_SCHEDULE
+ * </p>
+ * Replace C function named "before_schedchange_hook" in eventhooks.c
+ * <p>
+ * Fields: LTT_FIELD_PREV_PID, LTT_FIELD_NEXT_PID, LTT_FIELD_PREV_STATE (?)
+ * </p>
+ *
+ * @return
+ */
+ final ILttngEventProcessor getBeforeSchedChangeHandler() {
+ AbsFlowTRangeUpdate handler = new AbsFlowTRangeUpdate() {
+
+ // @Override
+ public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) {
+
+ Long pid_out = getAFieldLong(trcEvent, traceSt,
+ Fields.LTT_FIELD_PREV_PID);
+ Long pid_in = getAFieldLong(trcEvent, traceSt,
+ Fields.LTT_FIELD_NEXT_PID);
+
+ // This is useless even in Lttv !!
+ // Long state_out = getAFieldLong(trcEvent, traceSt,
+ // Fields.LTT_FIELD_PREV_STATE);
+
+ // We need to process information.
+ LttngProcessState process = traceSt.getRunning_process().get(
+ trcEvent.getCpuId());
+
+ if (process != null) {
+ if (process.getPid().equals(pid_out) == false) {
+ // To replace :
+ // process = lttv_state_find_process(ts,tfs->cpu,
+ // pid_out);
+ process = lttv_state_find_process(traceSt, trcEvent
+ .getCpuId(), pid_out);
+ // Also, removed :
+ // guint trace_num = ts->parent.index;
+ }
+
+ if (process != null) {
+ // TODO: Implement something similar to current hash in
+ // order to keep track of the current process and speed
+ // up finding the local resource.
+
+ // HashedProcessData *hashed_process_data = NULL;
+ // hashed_process_data =
+ // processlist_get_process_data(process_list,pid_out,process->cpu,&birth,trace_num);
+ TimeRangeEventProcess localProcess = procContainer
+ .findProcess(process.getPid(), process.getCpu(), traceSt
+ .getTraceId(), process.getCreation_time());
+
+ // Add process to process list if not present
+ // Replace C Call :
+ // processlist_add(process_list,drawing,pid_out,process->tgid,process->cpu,process->ppid,&birth,trace_num,process->name,process->brand,&pl_height,&process_info,&hashed_process_data);
+ if (localProcess == null) {
+ TmfTimeRange timeRange = traceSt.getContext()
+ .getTraceTimeWindow();
+ localProcess = addLocalProcess(process, timeRange
+ .getStartTime().getValue(), timeRange
+ .getEndTime().getValue(), traceSt
+ .getTraceId());
+ }
+
+ // Do the actual drawing
+ makeDraw(traceSt, trcEvent.getTimestamp().getValue(),
+ process,
+ localProcess, params);
+ } else {
+ // Process may be null if the process started BEFORE the
+ // trace start
+ // TraceDebug.debug("Process is null for pid_out! (getBeforeSchedChangeHandler)");
+ }
+
+ // PID_IN section
+ process = lttv_state_find_process(traceSt, trcEvent
+ .getCpuId(), pid_in);
+
+ if (process != null) {
+ // HashedProcessData *hashed_process_data = NULL;
+ // hashed_process_data =
+ // processlist_get_process_data(process_list, pid_in,
+ // tfs->cpu, &birth, trace_num);
+ TimeRangeEventProcess localProcess = procContainer
+ .findProcess(process.getPid(), process.getCpu(), traceSt
+ .getTraceId(), process.getCreation_time());
+
+ // Add process to process list if not present
+ // Replace C Call :
+ // processlist_add(process_list, drawing, pid_in,
+ // process->tgid, tfs->cpu, process->ppid, &birth,
+ // trace_num, process->name, process->brand, &pl_height,
+ // &process_info, &hashed_process_data);
+ if (localProcess == null) {
+ TmfTimeRange timeRange = traceSt.getContext()
+ .getTraceTimeWindow();
+ localProcess = addLocalProcess(process, timeRange
+ .getStartTime().getValue(), timeRange
+ .getEndTime().getValue(), traceSt
+ .getTraceId());
+ }
+
+ // Do the actual drawing
+ makeDraw(traceSt, trcEvent.getTimestamp().getValue(),
+ process,
+ localProcess, params);
+
+ } else {
+ // Process can be null if it started AFTER the trace
+ // end. Do nothing...
+ // TraceDebug.debug("No process found for pid_in! Something is wrong? (getBeforeSchedChangeHandler)");
+ }
+ } else {
+ TraceDebug
+ .debug("Running process is null! (getBeforeSchedChangeHandler)");
+ }
+
+ return false;
+ }
+ };
+
+ return handler;
+ }
+
+ /**
+ * <p>
+ * Handles: LTT_EVENT_PROCESS_EXIT
+ * </p>
+ * Replace C function named "before_process_exit_hook" in eventhooks.c
+ *
+ * @return
+ */
+ final ILttngEventProcessor getProcessExitHandler() {
+ AbsFlowTRangeUpdate handler = new AbsFlowTRangeUpdate() {
+
+ // @Override
+ public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) {
+
+ // We need to process information.
+ LttngProcessState process = traceSt.getRunning_process().get(
+ trcEvent.getCpuId());
+
+ if (process != null) {
+ // TODO: Implement a similar method to track the current
+ // local process in order to speed up finding the local
+ // resource
+
+ // hashed_process_data =
+ // processlist_get_process_data(process_list, pid,
+ // process->cpu, &birth,trace_num);
+ TimeRangeEventProcess localProcess = procContainer
+ .findProcess(process.getPid(), process.getCpu(), traceSt
+ .getTraceId(), process.getCreation_time());
+
+ // Add process to process list if not present
+ // Replace C Call :
+ // processlist_add(process_list, drawing, pid,
+ // process->tgid, process->cpu, process->ppid, &birth,
+ // trace_num, process->name, process->brand,&pl_height,
+ // &process_info, &hashed_process_data);
+ if (localProcess == null) {
+ TmfTimeRange timeRange = traceSt.getContext()
+ .getTraceTimeWindow();
+ localProcess = addLocalProcess(process, timeRange
+ .getStartTime().getValue(), timeRange
+ .getEndTime().getValue(), traceSt.getTraceId());
+ }
+
+ // Call the function that does the actual drawing
+ makeDraw(traceSt, trcEvent.getTimestamp().getValue(),
+ process, localProcess, params);
+
+ } else {
+ TraceDebug
+ .debug("Running process is null! (getProcessExitHandler)");
+ }
+
+ return false;
+ }
+ };
+ return handler;
+ }
+
+ /**
+ * <p>
+ * Handles: LTT_EVENT_PROCESS_FREE
+ * </p>
+ * Replace C function named "before_process_release_hook" in eventhooks.c
+ * <p>
+ * Fields: LTT_FIELD_PID
+ * </p>
+ *
+ * @return
+ */
+ final ILttngEventProcessor getProcessFreeHandler() {
+ AbsFlowTRangeUpdate handler = new AbsFlowTRangeUpdate() {
+
+ // @Override
+ public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) {
+ // PID of the process to release
+ Long release_pid = getAFieldLong(trcEvent, traceSt,
+ Fields.LTT_FIELD_PID);
+
+ if ((release_pid != null)) {
+ LttngProcessState process = lttv_state_find_process(
+ traceSt, ANY_CPU, release_pid);
+ if (process != null) {
+
+ // Replace the C call :
+ // hashed_process_data =
+ // processlist_get_process_data(process_list,pid,process->cpu,&birth,trace_num);
+ TimeRangeEventProcess localProcess = procContainer
+ .findProcess(process.getPid(), process.getCpu(), traceSt
+ .getTraceId(), process
+ .getCreation_time());
+
+ // This is as it was in the C ... ?
+ if (localProcess == null) {
+ return false;
+ }
+
+ // Perform the drawing
+ makeDraw(traceSt, trcEvent.getTimestamp().getValue(),
+ process,
+ localProcess, params);
+ }
+ } else {
+ TraceDebug
+ .debug("Release_pid is null! (getProcessFreeHandler)");
+ }
+
+ return false;
+ }
+ };
+ return handler;
+ }
+
+ /**
+ * <p>
+ * Handles: LTT_EVENT_STATEDUMP_END
+ * </p>
+ * Replace C function named "before_statedump_end" in eventhooks.c
+ *
+ * @return
+ */
+ final ILttngEventProcessor getStateDumpEndHandler() {
+ AbsFlowTRangeUpdate handler = new AbsFlowTRangeUpdate() {
+
+ // @Override
+ public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) {
+
+ // What's below should replace the following call in C :
+ // ClosureData closure_data;
+ // closure_data.events_request = events_request;
+ // closure_data.tss = tss;
+ // closure_data.end_time = evtime;
+ // convert_time_to_pixels(time_window,evtime,width,&closure_data.x_end);
+ // g_hash_table_foreach(process_list->process_hash,
+ // draw_closure,(void*)&closure_data);
+ //
+ // And the draw is always the same then...
+
+ // The c-library loops through the local processes, search for
+ // the local processes in the state provider and then draws
+ // If it's present is the local processes why shuldn't they be
+ // present in the state provider?
+ // This seems more direct. and makes sure all processes are
+ // reflected in the control flow view.
+ LttngProcessState[] processes = traceSt.getProcesses();
+ for (int pos=0; pos < processes.length; pos++) {
+ LttngProcessState process = processes[pos];
+
+ // Replace the C call :
+ // hashed_process_data =
+ // processlist_get_process_data(process_list,pid,process->cpu,&birth,trace_num);
+ TimeRangeEventProcess localProcess = procContainer
+ .findProcess(process.getPid(), process.getCpu(), traceSt
+ .getTraceId(), process
+ .getCreation_time());
+
+ // Add process to process list if not present
+ if (localProcess == null) {
+ TmfTimeRange timeRange = traceSt.getContext()
+ .getTraceTimeWindow();
+ localProcess = addLocalProcess(process, timeRange
+ .getStartTime().getValue(), timeRange
+ .getEndTime().getValue(), traceSt.getTraceId());
+ }
+
+ // Call the function that will does the actual
+ // drawing
+ makeDraw(traceSt, trcEvent.getTimestamp().getValue(),
+ process, localProcess, params);
+ }
+
+ return false;
+ }
+ };
+
+ return handler;
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.controlflow.evProcessor;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.linuxtools.lttng.state.StateStrings;
+import org.eclipse.linuxtools.lttng.state.evProcessor.AbsEventToHandlerResolver;
+import org.eclipse.linuxtools.lttng.state.evProcessor.ILttngEventProcessor;
+
+/**
+ * Builds a Map from string event name to a processing handler object, the
+ * processors implement the same interface to facilitate transparent methods
+ * call,
+ *
+ * The map key STring is the entry point of the raw events, using a hash speeds
+ * up the resolution of the appropriate processor
+ *
+ * @author alvaro
+ *
+ */
+public class FlowEventToHandlerFactory extends AbsEventToHandlerResolver {
+ // ========================================================================
+ // Data
+ // =======================================================================
+ private final Map<String, ILttngEventProcessor> eventNametoBeforeProcessor = new HashMap<String, ILttngEventProcessor>();
+ private final Map<String, ILttngEventProcessor> eventNametoAfterProcessor = new HashMap<String, ILttngEventProcessor>();
+ private ILttngEventProcessor finishProcesor = null;
+ private static FlowEventToHandlerFactory instance = null;
+ private FlowBeforeUpdateHandlers instantiateBeforeHandler = new FlowBeforeUpdateHandlers();
+ private FlowAfterUpdateHandlers instantiateAfterHandler = new FlowAfterUpdateHandlers();
+
+ // ========================================================================
+ // Constructors
+ // =======================================================================
+ private FlowEventToHandlerFactory() {
+ super();
+ // Create one instance of each individual event handler and add the
+ // instance to the map
+
+ // BEFORE HOOKS
+ eventNametoBeforeProcessor.put(
+ StateStrings.Events.LTT_EVENT_SYSCALL_ENTRY.getInName(),
+ instantiateBeforeHandler.getStateModesHandler());
+
+ eventNametoBeforeProcessor.put(
+ StateStrings.Events.LTT_EVENT_SYSCALL_EXIT.getInName(),
+ instantiateBeforeHandler.getStateModesHandler());
+
+ eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_TRAP_ENTRY
+ .getInName(), instantiateBeforeHandler.getStateModesHandler());
+
+ eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_TRAP_EXIT
+ .getInName(), instantiateBeforeHandler.getStateModesHandler());
+
+ eventNametoBeforeProcessor.put(
+ StateStrings.Events.LTT_EVENT_PAGE_FAULT_ENTRY.getInName(),
+ instantiateBeforeHandler.getStateModesHandler());
+
+ eventNametoBeforeProcessor.put(
+ StateStrings.Events.LTT_EVENT_PAGE_FAULT_EXIT.getInName(),
+ instantiateBeforeHandler.getStateModesHandler());
+
+ eventNametoBeforeProcessor.put(
+ StateStrings.Events.LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
+ .getInName(), instantiateBeforeHandler
+ .getStateModesHandler());
+
+ eventNametoBeforeProcessor
+ .put(StateStrings.Events.LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
+ .getInName(), instantiateBeforeHandler
+ .getStateModesHandler());
+
+ eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_IRQ_ENTRY
+ .getInName(), instantiateBeforeHandler.getStateModesHandler());
+
+ eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_IRQ_EXIT
+ .getInName(), instantiateBeforeHandler.getStateModesHandler());
+
+ eventNametoBeforeProcessor.put(
+ StateStrings.Events.LTT_EVENT_SOFT_IRQ_ENTRY.getInName(),
+ instantiateBeforeHandler.getStateModesHandler());
+
+ eventNametoBeforeProcessor.put(
+ StateStrings.Events.LTT_EVENT_SOFT_IRQ_EXIT.getInName(),
+ instantiateBeforeHandler.getStateModesHandler());
+
+ eventNametoBeforeProcessor.put(
+ StateStrings.Events.LTT_EVENT_SCHED_SCHEDULE.getInName(),
+ instantiateBeforeHandler.getBeforeSchedChangeHandler());
+
+ eventNametoBeforeProcessor.put(
+ StateStrings.Events.LTT_EVENT_PROCESS_EXIT.getInName(),
+ instantiateBeforeHandler.getProcessExitHandler());
+
+ eventNametoBeforeProcessor.put(
+ StateStrings.Events.LTT_EVENT_PROCESS_FREE.getInName(),
+ instantiateBeforeHandler.getProcessFreeHandler());
+
+ eventNametoBeforeProcessor.put(
+ StateStrings.Events.LTT_EVENT_STATEDUMP_END.getInName(),
+ instantiateBeforeHandler.getStateDumpEndHandler());
+
+
+ // AFTER HOOKS
+ eventNametoAfterProcessor.put(
+ StateStrings.Events.LTT_EVENT_SCHED_SCHEDULE.getInName(),
+ instantiateAfterHandler.getSchedChangeHandler());
+
+ eventNametoAfterProcessor.put(
+ StateStrings.Events.LTT_EVENT_PROCESS_FORK.getInName(),
+ instantiateAfterHandler.getProcessForkHandler());
+
+ eventNametoAfterProcessor.put(
+ StateStrings.Events.LTT_EVENT_PROCESS_EXIT.getInName(),
+ instantiateAfterHandler.getProcessExitHandler());
+
+ eventNametoAfterProcessor.put(StateStrings.Events.LTT_EVENT_EXEC
+ .getInName(), instantiateAfterHandler.getProcessExecHandler());
+
+ eventNametoAfterProcessor.put(
+ StateStrings.Events.LTT_EVENT_THREAD_BRAND.getInName(),
+ instantiateAfterHandler.GetThreadBrandHandler());
+
+ eventNametoAfterProcessor.put(
+ StateStrings.Events.LTT_EVENT_PROCESS_STATE.getInName(),
+ instantiateAfterHandler.getEnumProcessStateHandler());
+
+ finishProcesor = new FlowFinishUpdateHandler();
+ }
+
+ // ========================================================================
+ // Public methods
+ // =======================================================================
+ /**
+ * The event processors are common to all traces an multiple instances will
+ * use more memory unnecessarily
+ *
+ * @return
+ */
+ public static AbsEventToHandlerResolver getInstance() {
+ if (instance == null) {
+ instance = new FlowEventToHandlerFactory();
+ }
+ return instance;
+ }
+
+ @Override
+ public ILttngEventProcessor getAfterProcessor(String eventType) {
+ return eventNametoAfterProcessor.get(eventType);
+ }
+
+ @Override
+ public ILttngEventProcessor getBeforeProcessor(String eventType) {
+ return eventNametoBeforeProcessor.get(eventType);
+ }
+
+ @Override
+ public ILttngEventProcessor getfinishProcessor() {
+ return finishProcesor;
+ }
+
+ @Override
+ public ILttngEventProcessor getStateUpdaterProcessor(String eventType) {
+ return null;
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors: Alvaro Sanchez-Leon - Initial implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.controlflow.evProcessor;
+
+import java.util.Vector;
+
+import org.eclipse.linuxtools.lttng.event.LttngEvent;
+import org.eclipse.linuxtools.lttng.state.StateStrings.Events;
+import org.eclipse.linuxtools.lttng.state.evProcessor.ILttngEventProcessor;
+import org.eclipse.linuxtools.lttng.state.model.LttngProcessState;
+import org.eclipse.linuxtools.lttng.state.model.LttngTraceState;
+import org.eclipse.linuxtools.lttng.ui.TraceDebug;
+import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeComponent;
+import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEvent;
+import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEventProcess;
+
+/**
+ * Creates specific finish state data request
+ *
+ * @author alvaro
+ *
+ */
+public class FlowFinishUpdateHandler extends AbsFlowTRangeUpdate
+ implements ILttngEventProcessor {
+
+ public Events getEventHandleType() {
+ // No specific event
+ return null;
+ }
+
+ public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) {
+ // Draw a last known state to the end of the trace
+ long endReqTime = traceSt.getContext().getTraceTimeWindow()
+ .getEndTime().getValue();
+ TraceDebug.debug("Number of localProcesses: "
+ + procContainer.readItems().length);
+ // to identify the process relevant to the traceState
+ String traceId = traceSt.getTraceId();
+ int numLocalFound = 0;
+ int numLocalNotFound = 0;
+ int numWithNoChildren = 0;
+ for (TimeRangeEventProcess localProcess : procContainer.readItems()) {
+ LttngProcessState stateProcess = lttv_state_find_process(traceSt,
+ localProcess.getCpu(), localProcess.getPid());
+
+ // Drawing the last state for processes related to the current trace
+ // id.
+ if (!localProcess.getTraceID().equals(traceId)) {
+ continue;
+ }
+
+ // Check if the process is in the state provider, it is the case
+ // when the requested time frame did not include any events for a
+ // process
+ if (stateProcess == null) {
+ // Get Start time from the end time of previous event
+ Vector<TimeRangeComponent> childrenEvents = localProcess
+ .getTraceEvents();
+ long nextGoodTime;
+ String stateMode;
+ if (childrenEvents.size() > 0) {
+ TimeRangeComponent prevEvent = childrenEvents
+ .get(childrenEvents.size() - 1);
+ if (prevEvent instanceof TimeRangeEvent) {
+ TimeRangeEvent prevTimeRange = (TimeRangeEvent) prevEvent;
+ // calculate the next good time to draw the event
+ // nextGoodTime = prevTimeRange.getStopTime() + 1;
+ nextGoodTime = localProcess.getNext_good_time();
+ stateMode = prevTimeRange.getStateMode();
+
+ // Draw with the Local information since the current
+ // request did
+ // not contain events related to this process
+ makeDraw(traceSt, nextGoodTime,
+ endReqTime, localProcess, params, stateMode);
+ } else {
+ TraceDebug
+ .debug("previous event not instance of TimeRangeEvent?: "
+ + prevEvent.getClass().getSimpleName());
+ }
+ } else {
+ numWithNoChildren++;
+ }
+
+ numLocalNotFound++;
+ continue;
+ }
+ numLocalFound++;
+ // Draw the last state for this process
+
+ makeDraw(traceSt, endReqTime, stateProcess, localProcess, params);
+ }
+
+ TraceDebug.debug("Print Last Event: NumLocalFound " + numLocalFound
+ + "; NumLocalNotFound: " + numLocalNotFound
+ + "; NumWithNoChildren: " + numWithNoChildren);
+
+ return false;
+ }
+
+}
--- /dev/null
+ControlFlowView.Action.Filter=Filter\r
+ControlFlowView.Action.Filter.ToolTip=Process Filter options\r
+ControlFlowView.Action.Legend=Legend\r
+ControlFlowView.Action.Legend.ToolTip=Show Legend\r
+ControlFlowView.Action.LoadData=LoadData\r
+ControlFlowView.Action.LoadData.ToolTip=Load data from external plug-in\r
+ControlFlowView.Action.NextEvent=NextEv\r
+ControlFlowView.Action.NextEvent.Tooltip=Next Event\r
+ControlFlowView.Action.NextProcess=NextProcess\r
+ControlFlowView.Action.NextProcess.ToolTip=Select Next Process\r
+ControlFlowView.Action.PrevEvent=PrevEv\r
+ControlFlowView.Action.PrevEvent.Tooltip=Previous Event\r
+ControlFlowView.Action.PreviousProcess=PreviousProcess\r
+ControlFlowView.Action.PreviousProcess.Tooltip=Select Previous Process\r
+ControlFlowView.Action.Reset=Reset\r
+ControlFlowView.Action.Reset.ToolTip=Reset the Time Scale to Default\r
+ControlFlowView.Action.Synchronize=Synchronise\r
+ControlFlowView.Action.Synchronize.ToolTip=Synchronise by listening to external API selection calls\r
+ControlFlowView.Action.ZoomIn=Zoom In\r
+ControlFlowView.Action.ZoomIn.Tooltip=Zoom In\r
+ControlFlowView.Action.ZoomOut=Zoom Out\r
+ControlFlowView.Action.ZoomOut.tooltip=Zoom Out\r
+ControlFlowView.Action.ZoomFilter=Zoom Filter\r
+ControlFlowView.Action.ZoomFilter.tooltip=Display elements with events within the zoomed time window\r
+ControlFlowView.msgSlogan=Control Flow View\r
+ControlFlowView.tmf.UI=org.eclipse.linuxtools.tmf.ui\r
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.controlflow.model;
+
+import org.eclipse.linuxtools.lttng.ui.views.common.ParamsUpdater;
+
+/**
+ * Instantiates the entry point classes to build the data model for this view
+ *
+ * @author alvaro
+ *
+ */
+public class FlowModelFactory {
+ // ========================================================================
+ // Data
+ // ========================================================================
+ private static FlowProcessContainer procContainer = null;
+ private static ParamsUpdater updater = null;
+
+
+ // ========================================================================
+ // Methods
+ // ========================================================================
+ /**
+ * Get Process data container
+ * @return
+ */
+ public static FlowProcessContainer getProcContainer() {
+ if (procContainer == null) {
+ procContainer = new FlowProcessContainer();
+ }
+ return procContainer;
+ }
+
+ public static ParamsUpdater getParamsUpdater() {
+ if (updater == null) {
+ updater = new ParamsUpdater();
+ }
+ return updater;
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Alvaro Sanchez-Leon - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.controlflow.model;
+
+import java.util.HashMap;
+import java.util.Iterator;
+
+import org.eclipse.linuxtools.lttng.TraceDebug;
+import org.eclipse.linuxtools.lttng.ui.model.trange.ItemContainer;
+import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEventProcess;
+
+/**
+ * Contains the processes in use by the Control flow view
+ *
+ * @author alvaro
+ *
+ */
+public class FlowProcessContainer implements ItemContainer<TimeRangeEventProcess> {
+ // ========================================================================
+ // Data
+ // ========================================================================
+ private final HashMap<ProcessKey, TimeRangeEventProcess> allProcesses = new HashMap<ProcessKey, TimeRangeEventProcess>();
+ private static Integer uniqueId = 0;
+
+ // ========================================================================
+ // Constructor
+ // ========================================================================
+
+ /**
+ * Package level constructor
+ */
+ FlowProcessContainer() {
+
+ }
+
+ // ========================================================================
+ // Methods
+ // ========================================================================
+ /**
+ * Interface to add a new process.<p>
+ *
+ * Note : Process with the same key will be overwritten, it's calling function job to make sure the new process is unique.
+ *
+ * @param newProcess The process to add
+ */
+ public void addItem(TimeRangeEventProcess newItem) {
+ if (newItem != null) {
+ allProcesses.put(new ProcessKey(newItem), newItem);
+ }
+ }
+
+ /**
+ * Request a unique ID
+ *
+ * @return Integer
+ */
+ public Integer getUniqueId() {
+ return uniqueId++;
+ }
+
+ /**
+ * This method is intended for read only purposes in order to keep the
+ * internal data structure in synch
+ *
+ * @return TimeRangeEventProcess[]
+ */
+ public TimeRangeEventProcess[] readItems() {
+
+ // This allow us to return an Array of the correct type of the exact correct dimension, without looping
+ return allProcesses.values().toArray(new TimeRangeEventProcess[allProcesses.size()]);
+ }
+
+ /**
+ * Clear the children information for processes e.g. just before refreshing
+ * data with a new time range
+ */
+ public void clearChildren() {
+ TimeRangeEventProcess process = null;
+ Iterator<ProcessKey> iterator = allProcesses.keySet().iterator();
+
+ while (iterator.hasNext()) {
+ process = allProcesses.get(iterator.next());
+ process.reset();
+ }
+ }
+
+ /**
+ * Clear all process items
+ */
+ public void clearItems() {
+ allProcesses.clear();
+ }
+
+ /**
+ * Remove the process related to a specific trace e.g. during trace
+ * removal
+ *
+ * @param traceId The trace unique id (trace name?) on which we want to remove process
+ */
+ public void removeItems(String traceId) {
+ ProcessKey iterKey = null;
+
+ Iterator<ProcessKey> iterator = allProcesses.keySet().iterator();
+ while (iterator.hasNext()) {
+ iterKey = iterator.next();
+
+ if (allProcesses.get(iterKey).getTraceID().equals(traceId)) {
+ allProcesses.remove(iterKey);
+ }
+ }
+ }
+
+ /**
+ * Search by keys (pid, cpuId, traceId and creationTime)<p>
+ *
+ * A match is returned if the four arguments received match an entry
+ * Otherwise null is returned
+ *
+ * @param searchedPid The processId (Pid) we are looking for
+ * @param searchedCpuId The cpu Id we are looking for
+ * @param searchedTraceID The traceId (trace name?) we are looking for
+ * @param searchedCreationtime The creation time we are looking for
+ *
+ * @return TimeRangeEventProcess
+ */
+ public TimeRangeEventProcess findProcess(Long searchedPid, Long searchedCpuId, String searchedTraceID, Long searchedCreationtime) {
+ // Get the TimeRangeEventProcess associated to a key we create here
+ TimeRangeEventProcess foundProcess = allProcesses.get( new ProcessKey(searchedPid, searchedCpuId, searchedTraceID, searchedCreationtime) );
+
+ return foundProcess;
+ }
+}
+
+
+class ProcessKey {
+ private TimeRangeEventProcess valueRef = null;
+
+ private Long pid = null;
+ private Long cpuId = null;
+ private String traceId = null;
+ private Long creationtime = null;
+
+ @SuppressWarnings("unused")
+ private ProcessKey() { }
+
+ public ProcessKey(TimeRangeEventProcess newRef) {
+ valueRef = newRef;
+ }
+
+ public ProcessKey(Long newPid, Long newCpuId, String newTraceId, Long newCreationTime) {
+ pid = newPid;
+ cpuId = newCpuId;
+ traceId = newTraceId;
+ creationtime = newCreationTime;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ boolean isSame = false;
+
+ if ( obj instanceof ProcessKey ) {
+ ProcessKey procKey = (ProcessKey) obj;
+
+ if ( valueRef != null ) {
+ if ( (procKey.getPid().equals(valueRef.getPid()) ) &&
+ (procKey.getTraceId().equals(valueRef.getTraceID()) ) &&
+ (procKey.getCpuId().equals(valueRef.getCpu()) ) &&
+ (procKey.getCreationtime().equals(valueRef.getCreationTime()) ) )
+ {
+ isSame = true;
+ }
+ }
+ else {
+ if ( (procKey.getPid().equals(this.pid ) ) &&
+ (procKey.getTraceId().equals(this.traceId ) ) &&
+ (procKey.getCpuId().equals(this.cpuId ) ) &&
+ (procKey.getCreationtime().equals(this.creationtime ) ) )
+ {
+ isSame = true;
+ }
+ }
+ }
+ else {
+ TraceDebug.debug("ERROR : The given key is not of the type ProcessKey!" + obj.getClass().toString());
+ }
+
+ return isSame;
+ }
+
+ // *** WARNING : Everything in there work because the check "valueRef != null" is the same for ALL getter
+ // Do NOT change this check without checking.
+ public Long getPid() {
+ if ( valueRef != null ) {
+ return valueRef.getPid();
+ }
+ else {
+ return pid;
+ }
+ }
+
+ public Long getCpuId() {
+ if ( valueRef != null ) {
+ return valueRef.getCpu();
+ }
+ else {
+ return cpuId;
+ }
+ }
+
+ public String getTraceId() {
+ if ( valueRef != null ) {
+ return valueRef.getTraceID();
+ }
+ else {
+ return traceId;
+ }
+ }
+
+ public Long getCreationtime() {
+ if ( valueRef != null ) {
+ return valueRef.getCreationTime();
+ }
+ else {
+ return creationtime;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return this.toString().hashCode();
+ }
+
+
+ @Override
+ public String toString() {
+ if ( valueRef != null ) {
+ return (valueRef.getPid().toString() + ":" + valueRef.getCpu().toString() + ":" + valueRef.getTraceID().toString() + ":" + valueRef.getCreationTime().toString());
+ }
+
+ return (pid.toString() + ":" + cpuId.toString() + ":" + traceId.toString() + ":" + creationtime.toString());
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.events;
+
+import org.eclipse.linuxtools.lttng.event.LttngEventContent;
+import org.eclipse.linuxtools.tmf.event.TmfEvent;
+import org.eclipse.linuxtools.tmf.ui.views.TmfEventsView;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+
+/**
+ * <b><u>EventsView</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+public class EventsView extends TmfEventsView {
+
+ public static final String ID = "org.eclipse.linuxtools.lttng.ui.views.events";
+
+ // ------------------------------------------------------------------------
+ // Table data
+ // ------------------------------------------------------------------------
+
+ // Table column names
+ private final String TIMESTAMP_COLUMN = "Timestamp";
+ private final String SOURCE_COLUMN = "Source";
+ private final String TYPE_COLUMN = "Type";
+ private final String REFERENCE_COLUMN = "Reference";
+ private final String CONTENT_COLUMN = "Content";
+ private final String[] columnProperties = new String[] {
+ TIMESTAMP_COLUMN,
+ SOURCE_COLUMN,
+ TYPE_COLUMN,
+ REFERENCE_COLUMN,
+ CONTENT_COLUMN
+ };
+
+ // Column data
+ private class ColumnData {
+ public final String header;
+ public final int width;
+ public final int alignment;
+
+ public ColumnData(String h, int w, int a) {
+ header = h;
+ width = w;
+ alignment = a;
+ }
+ };
+
+ private ColumnData[] columnData = new ColumnData[] {
+ new ColumnData(columnProperties[0], 125, SWT.LEFT),
+ new ColumnData(columnProperties[1], 100, SWT.LEFT),
+ new ColumnData(columnProperties[2], 200, SWT.LEFT),
+ new ColumnData(columnProperties[3], 200, SWT.LEFT),
+ new ColumnData(columnProperties[4], 100, SWT.LEFT)
+ };
+
+ // ------------------------------------------------------------------------
+ // Constructor
+ // ------------------------------------------------------------------------
+
+ public EventsView() {
+ super(1);
+ }
+
+ /**
+ * @param table
+ *
+ * FIXME: Add support for column selection
+ */
+ @Override
+ protected void createColumnHeaders(Table table) {
+ for (int i = 0; i < columnData.length; i++) {
+ final TableColumn column = new TableColumn(table, columnData[i].alignment, i);
+ column.setText(columnData[i].header);
+ column.setWidth(columnData[i].width);
+ // TODO: Investigate why the column resizing doesn't work by default
+ // Anything to do with SWT_VIRTUAL?
+ column.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ // TODO Auto-generated method stub
+ }
+ public void widgetSelected(SelectionEvent e) {
+ column.pack();
+ }
+ });
+ }
+ }
+
+ /**
+ * @param event
+ * @return
+ */
+ @Override
+ protected String[] extractItemFields(TmfEvent event) {
+ String[] fields = new String[0];
+
+ if (event != null) {
+ fields = new String[] {
+ event.getTimestamp().toString(),
+ event.getSource().toString(),
+ event.getType().toString(),
+ event.getReference().toString(),
+ ((LttngEventContent)event.getContent()).toString()
+ };
+ }
+ return fields;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return "[EventsView]";
+ }
+
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * William Bourque - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.histogram;
+
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * <b><u>ChildrenHistogramCanvas</u></b>
+ * <p>
+ * Extended implementation of the HistogramCanvas.
+ * <p>
+ * This canvas goal is to display the "SelectionWindow" in details.
+ */
+public class ChildrenHistogramCanvas extends HistogramCanvas {
+
+ protected HistogramView parentHistogramWindow = null;
+
+ /**
+ * ChildrenHistogramCanvas constructor.<p>
+ * Same as HistogramCanvas, but receive a parent HistogramView that we can call from here.
+ *
+ * @param parent Composite control which will be the parent of the new instance (cannot be null)
+ * @param Style the style of control to construct
+ */
+ public ChildrenHistogramCanvas(HistogramView newParentWindow, Composite parent, int style) {
+ super(parent, style);
+
+ parentHistogramWindow = newParentWindow;
+ }
+
+ /**
+ * Notify the parent HistogramView that we have updated information.<p>
+ * This is intended to be called at the end of the request when we know we have up-to-date information.
+ */
+ @Override
+ public void notifyParentUpdatedInformation() {
+ parentHistogramWindow.updateSelectedWindowInformation();
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * William Bourque - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.histogram;
+
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * <b><u>HistogramCanvas</u></b>
+ * <p>
+ * Canvas implementation aimed to draw histograms.
+ * <p>
+ * This canvas goal is to display certain "HistogramContent" onto an histogram.<p>
+ * Several method exist to extend it so it should suit most needs.
+ */
+public class HistogramCanvas extends Canvas
+{
+ protected AsyncCanvasRedrawer canvasRedrawer = null;
+ protected HistogramContent histogramContent = null;
+
+ protected HistogramCanvasPaintListener paintListener = null;
+ protected HistogramCanvasMouseListener mouseListener = null;
+ protected HistogramCanvasKeyListener keyListener = null;
+ protected HistogramCanvasFocusListener focusListener = null;
+ protected HistogramCanvasControlListener controlListener = null;
+
+ protected HistogramSelectedWindow currentWindow = null;
+
+
+ /**
+ * HistogramCanvas constructor
+ *
+ * @param parent Composite control which will be the parent of the new instance (cannot be null)
+ * @param Style the style of control to construct
+ */
+ public HistogramCanvas(Composite parent, int style) {
+ super(parent, style);
+ addNeededListeners();
+
+ // New selected window, not visible by default
+ createNewSelectedWindow(0L);
+ }
+
+ /*
+ * Create the needed "event listeners" and hook them to the Canvas.
+ */
+ protected void addNeededListeners() {
+ createAndAddCanvasRedrawer();
+ createAndAddPaintListener();
+ createAndAddMouseListener();
+ createAndAddKeyListener();
+ createAndAddFocusListener();
+ createAndAddControlListener();
+ }
+
+ /*
+ * Create a canvas redrawer and bind it to this canvas.<p>
+ *
+ * Note : AsyncCanvasRedrawer is an internal class
+ * This is used to redraw the canvas from a different thread
+ * without^H^H^H with less danger.
+ */
+ protected void createAndAddCanvasRedrawer() {
+ canvasRedrawer = new AsyncCanvasRedrawer(this);
+ }
+
+ /*
+ * Create a histogram paint listener and bind it to this canvas.<p>
+ *
+ * @see org.eclipse.linuxtools.lttng.ui.views.histogram.HistogramCanvasPaintListener
+ */
+ protected void createAndAddPaintListener() {
+ paintListener = new HistogramCanvasPaintListener(this);
+ this.addPaintListener( paintListener );
+ }
+
+ /*
+ * Create a histogram mouse listener and bind it to this canvas.<p>
+ * Note : this mouse listener handle the mouse, the move and the wheel at once.
+ *
+ * @see org.eclipse.linuxtools.lttng.ui.views.histogram.HistogramCanvasMouseListener
+ */
+ protected void createAndAddMouseListener() {
+ mouseListener = new HistogramCanvasMouseListener(this);
+ this.addMouseListener(mouseListener);
+ this.addMouseMoveListener(mouseListener);
+ this.addMouseWheelListener(mouseListener);
+ }
+
+ /*
+ * Create a histogram key listener and bind it to this canvas.<p>
+ *
+ * @see org.eclipse.linuxtools.lttng.ui.views.histogram.HistogramCanvasKeyListener
+ */
+ protected void createAndAddKeyListener() {
+ keyListener = new HistogramCanvasKeyListener(this);
+ this.addKeyListener(keyListener);
+ }
+
+ /*
+ * Create a histogram focus listener and bind it to this canvas.<p>
+ *
+ * @see org.eclipse.linuxtools.lttng.ui.views.histogram.HistogramCanvasFocusListener
+ */
+ protected void createAndAddFocusListener() {
+ focusListener = new HistogramCanvasFocusListener(this);
+ this.addFocusListener(focusListener);
+ }
+
+ /*
+ * Create a histogram control listener and bind it to this canvas.<p>
+ *
+ * @see org.eclipse.linuxtools.lttng.ui.views.histogram.HistogramCanvasControlListener
+ */
+ protected void createAndAddControlListener() {
+ controlListener = new HistogramCanvasControlListener(this);
+ this.addControlListener(controlListener);
+ }
+
+ /**
+ * Create a new HistogramContent for this HistogramCanvas<p>
+ * A new <I>empty</I> content will then be created.
+ *
+ * IMPORTANT NOTE : Canvas size, bar width and bar height need to be known at this point, as these dimension are used to create a content
+ * of the correct size.
+ *
+ * @param canvasSize Size of the parent canvas.
+ * @param widthPerBar Width of the histogram "bars"
+ * @param barsHeight Height of the histogram "bars"
+ * @param maxBarsDifferenceToAverage Factor used to "chop" bars that are too tall. Set to something big (100.0?) if not needed.
+ */
+ public void createNewHistogramContent(int canvasSize, int widthPerBar, int barsHeight, double maxBarsDifferenceToAverage) {
+ histogramContent = new HistogramContent( canvasSize / widthPerBar, canvasSize, widthPerBar, barsHeight, maxBarsDifferenceToAverage);
+ }
+
+ /**
+ * Create a new selection window of the size (time width) given.<p>
+ * The window initial position is at X = 0.
+ * The window is created hidden, it won't be draw unless it is set to visible.<p>
+ *
+ * @param windowTimeDuration Time width (in nanosecond) of the window.
+ */
+ public void createNewSelectedWindow(long windowTimeDuration) {
+ currentWindow = new HistogramSelectedWindow(histogramContent);
+
+ currentWindow.setWindowTimeWidth(windowTimeDuration);
+ currentWindow.setWindowXPositionCenter(0);
+ }
+
+ public HistogramContent getHistogramContent() {
+ return histogramContent;
+ }
+
+ /**
+ * Getter for the selection window<p>
+ *
+ * @return the current selection window
+ *
+ * @see org.eclipse.linuxtools.lttng.ui.views.histogram.HistogramSelectedWindow
+ */
+ public HistogramSelectedWindow getCurrentWindow() {
+ return currentWindow;
+ }
+
+ /**
+ * Getter for the selection window width<p>
+ *
+ * @return Time width (in nanosecond) of the selection window.
+ */
+ public long getSelectedWindowSize() {
+ return currentWindow.getWindowTimeWidth();
+ }
+
+ /**
+ * Setter for the selection window width<p>
+ * The window size will be ajusted if it does not respect one of these constraints :
+ * - The window size cannot be smaller than a single histogram content interval.<p>
+ * - The window size cannot be larger than twice the histogram content complete time interval.<p>
+ *
+ * @param newSelectedWindowSize New time width (in nanosecond) of the selection window.
+ */
+ public void setSelectedWindowSize(long newSelectedWindowSize) {
+
+ if ( newSelectedWindowSize <= 0 ) {
+ newSelectedWindowSize = 1L;
+ }
+ else if ( newSelectedWindowSize > (2*histogramContent.getCompleteTimeInterval()) ) {
+ newSelectedWindowSize = (2*histogramContent.getCompleteTimeInterval());
+ }
+
+ currentWindow.setWindowTimeWidth(newSelectedWindowSize);
+ }
+
+ /**
+ * Method to call the "Asynchronous redrawer" for this canvas<p>
+ * This allow safe redraw from different threads.
+ *
+ */
+ public void redrawAsynchronously() {
+ // Create a new redrawer in case it doesn't exist yet (we never know with thread!)
+ if ( canvasRedrawer == null ) {
+ canvasRedrawer = new AsyncCanvasRedrawer(this);
+ }
+
+ canvasRedrawer.asynchronousRedraw();
+ }
+
+ /**
+ * Method to call the "Asynchronous NotifyParentSelectionWindowChanged" for this canvas<p>
+ * This allow safe update UI objects from different threads.
+ *
+ */
+ public void notifyParentSelectionWindowChangedAsynchronously() {
+ // Create a new redrawer in case it doesn't exist yet (we never know with thread!)
+ if ( canvasRedrawer == null ) {
+ canvasRedrawer = new AsyncCanvasRedrawer(this);
+ }
+
+ canvasRedrawer.asynchronousNotifyParentSelectionWindowChanged();
+ }
+
+ /**
+ * Method to call the "Asynchronous NotifyParentUpdatedInformation" for this canvas<p>
+ * This allow safe redraw from different threads.
+ *
+ */
+ public void notifyParentUpdatedInformationAsynchronously() {
+ // Create a new redrawer in case it doesn't exist yet (we never know with thread!)
+ if ( canvasRedrawer == null ) {
+ canvasRedrawer = new AsyncCanvasRedrawer(this);
+ }
+
+ canvasRedrawer.asynchronousNotifyParentUpdatedInformation();
+ }
+
+ /**
+ * Function that is called when the selection window is moved.<p>
+ * Note: Given position should be relative to the previous (centered) absolute position.
+ *
+ * <B>METHOD INTENDED TO BE EXTENDED</B>
+ *
+ * @param newRelativeXPosition New position relative to the last known absolute position.
+ */
+ public void moveWindow(int newRelativeXPosition) {
+ // Nothing : function is a place holder
+ }
+
+ /**
+ * Function that is called when the selection window is re-centered.<p>
+ * Note: Given position should be absolute to the window and need to be the selection window center.
+ *
+ * <B>METHOD INTENDED TO BE EXTENDED</B>
+ *
+ * @param newRelativeXPosition New absolute position.
+ */
+ public void setWindowCenterPosition(int newAbsoluteXPosition) {
+ // Nothing : function is a place holder
+ }
+
+ /**
+ * Function that is called when the selection window size (time width) changed by an absolute time.<p>
+ * Note: Given time should be in nanoseconds, positive.
+ *
+ * <B>METHOD INTENDED TO BE EXTENDED</B>
+ *
+ * @param newTime New absoulte time (in nanoseconds) to apply to the window.
+ */
+ public void resizeWindowByAbsoluteTime(long newTime) {
+ // Nothing : function is a place holder
+ }
+
+ /**
+ * Function that is called to tell the parent that the selection window changed.<p>
+ *
+ * <B>METHOD INTENDED TO BE EXTENDED</B>
+ *
+ */
+ public void notifyParentSelectionWindowChanged() {
+ // Nothing : function is a place holder
+ }
+
+ /**
+ * Function that is called to tell the parent that some information changed.<p>
+ *
+ * <B>METHOD INTENDED TO BE EXTENDED</B>
+ *
+ */
+ public void notifyParentUpdatedInformation() {
+ // Nothing : function is a place holder
+ }
+}
+
+
+/**
+ * <b><u>AsyncCanvasRedrawer Inner Class</u></b>
+ * <p>
+ * Asynchronous redrawer for the HistogramCanvas
+ * <p>
+ * This class role is to call method that update the UI on asynchronously.
+ * This should prevent any "invalid thread access" exception when trying to update UI from a different thread.
+ */
+class AsyncCanvasRedrawer {
+
+ private HistogramCanvas parentCanvas = null;
+
+ /**
+ * AsyncCanvasRedrawer constructor.
+ *
+ * @param newCanvas Related histogram canvas.
+ */
+ public AsyncCanvasRedrawer(HistogramCanvas newCanvas) {
+ parentCanvas = newCanvas;
+ }
+
+ /**
+ * Function to redraw the related canvas asynchonously.<p>
+ *
+ * Basically, it just run "canvas.redraw()" in asyncExec.
+ *
+ */
+ public void asynchronousRedraw() {
+ Display display = parentCanvas.getDisplay();
+ display.asyncExec(new Runnable() {
+ public void run() {
+ parentCanvas.redraw();
+ }
+ });
+ }
+
+ /**
+ * Function to asynchonously notify the parent of the related canvas that the window changed.<p>
+ *
+ * Basically, it just run "notifyParentSelectionWindowChanged()" in asyncExec.
+ *
+ */
+ public void asynchronousNotifyParentSelectionWindowChanged() {
+ Display display = parentCanvas.getDisplay();
+ display.asyncExec(new Runnable() {
+ public void run() {
+ parentCanvas.notifyParentSelectionWindowChanged();
+ }
+ });
+ }
+
+ /**
+ * Function to asynchonously notify the parent of the related canvas that information changed.<p>
+ *
+ * Basically, it just run "notifyParentUpdatedInformation()" in asyncExec.
+ *
+ */
+ public void asynchronousNotifyParentUpdatedInformation() {
+ Display display = parentCanvas.getDisplay();
+ display.asyncExec(new Runnable() {
+ public void run() {
+ parentCanvas.notifyParentUpdatedInformation();
+ }
+ });
+ }
+}
--- /dev/null
+package org.eclipse.linuxtools.lttng.ui.views.histogram;
+
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.ControlListener;
+
+/**
+ * <b><u>HistogramCanvasControlListener</u></b>
+ * <p>
+ * Implementation of a ControlListener for the need of the HistogramCanvas
+ * <p>
+ */
+public class HistogramCanvasControlListener implements ControlListener {
+
+ protected HistogramCanvas parentCanvas = null;
+
+ /**
+ * HistogramCanvasControlListener constructor
+ *
+ * @param newCanvas Related canvas
+ */
+ public HistogramCanvasControlListener(HistogramCanvas newCanvas) {
+ parentCanvas = newCanvas;
+ }
+
+
+ /**
+ * Method called when the canvas is moved.<p>
+ *
+ * Just redraw the canvas...
+ *
+ * @param event The controle event generated by the move.
+ */
+ public void controlMoved(ControlEvent event) {
+ parentCanvas.redraw();
+ }
+
+ /**
+ * Method called when the canvas is resized.<p>
+ *
+ * We need to tell the content that the canvas size changed and to recenter the windows
+ *
+ * @param event The control event generated by the resize.
+ */
+ public void controlResized(ControlEvent event) {
+
+ if ( (parentCanvas != null) && (parentCanvas.getHistogramContent() != null) ) {
+ int newSize = parentCanvas.getSize().x;
+ int oldSize = parentCanvas.getHistogramContent().getCanvasWindowSize();
+
+ // Set the new canvas size
+ parentCanvas.getHistogramContent().setCanvasWindowSize(newSize);
+
+ // Try to recenter to window at the same place it was
+ // Note : this is a best hope approach and is not intended to be precise;
+ // the idea is to avoid issuing a (maybe) long request fo the selection window;
+ // There WILL be slight discrepancy between the "window values" (timestamp, etc...) showed
+ // and what it really points to. The user should reclick by himself to refresh it.
+ int oldWindowCenter = parentCanvas.getCurrentWindow().getWindowXPositionCenter();
+ int newWindowCenter = (int)Math.ceil((double)newSize * ((double)oldWindowCenter / (double)oldSize));
+ parentCanvas.setWindowCenterPosition(newWindowCenter);
+ }
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * William Bourque - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.histogram;
+
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
+
+/**
+ * <b><u>HistogramCanvasFocusListener</u></b>
+ * <p>
+ * Implementation of a FocusListener for the need of the HistogramCanvas
+ * <p>
+ */
+public class HistogramCanvasFocusListener implements FocusListener {
+
+ protected HistogramCanvas parentCanvas = null;
+
+ /**
+ * HistogramCanvasFocusListener constructor
+ *
+ * @param newCanvas Related canvas
+ */
+ public HistogramCanvasFocusListener(HistogramCanvas newCanvas) {
+ parentCanvas = newCanvas;
+ }
+
+ /**
+ * Function that is called when the canvas get focus.<p>
+ *
+ * Redraw the screen to make sure everything is sane.
+ *
+ * @param event The focus event generated.
+ */
+ public void focusGained(FocusEvent event) {
+ parentCanvas.redrawAsynchronously();
+ }
+
+ /**
+ * Function that is called when the canvas loose focus.<p>
+ *
+ * Doesn't do anything yet...
+ *
+ * @param event The focus event generated.
+ */
+ public void focusLost(FocusEvent event) {
+ // Nothing to do yet
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * William Bourque - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.histogram;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+
+/**
+ * <b><u>HistogramCanvasKeyListener</u></b>
+ * <p>
+ * Implementation of a KeyListener for the need of the HistogramCanvas
+ * <p>
+ */
+public class HistogramCanvasKeyListener implements KeyListener
+{
+ protected HistogramCanvas parentCanvas = null;
+ protected boolean isShiftPressed = false;
+
+ /**
+ * HistogramCanvasKeyListener constructor
+ *
+ * @param newCanvas Related canvas
+ */
+ public HistogramCanvasKeyListener(HistogramCanvas newCanvas) {
+ parentCanvas = newCanvas;
+ }
+
+ /**
+ * Function that is called when a key is pressed.<p>
+ * Possible actions :
+ * - Left arrow : move the selection window left.<p>
+ * - Right arrow : move the selection window right.<p>
+ * - Shift : turn on "fast move" mode.<p>
+ *
+ * @param event The KeyEvent generated when the key was pressed.
+ */
+ public void keyPressed(KeyEvent event) {
+ switch (event.keyCode) {
+ case SWT.SHIFT:
+ isShiftPressed = true;
+ break;
+ case SWT.ARROW_LEFT:
+ moveWindowPosition(HistogramConstant.BASIC_DISPLACEMENT_FACTOR * -1);
+ break;
+ case SWT.ARROW_RIGHT:
+ moveWindowPosition(HistogramConstant.BASIC_DISPLACEMENT_FACTOR);
+ break;
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Function that is called when a key is released.<p>
+ * Possible actions :
+ * - Shift : turn off "fast move" mode.
+ *
+ * @param event The KeyEvent generated when the key was pressed.
+ */
+ public void keyReleased(KeyEvent event) {
+ switch (event.keyCode) {
+ case SWT.SHIFT:
+ isShiftPressed = false;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Function to move the window position of a given displacemnt.<p>
+ *
+ * @param displacementFactor The basic displacement to perform (positive or negative value)
+ */
+ public void moveWindowPosition(int displacementFactor) {
+
+ // If we are in "fast move mode", multiply the basic displacement by a factor
+ if ( isShiftPressed == true ) {
+ displacementFactor = (int)((double)displacementFactor * HistogramConstant.FAST_DISPLACEMENT_MULTIPLE);
+ }
+
+ parentCanvas.moveWindow(displacementFactor);
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * William Bourque - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.histogram;
+
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.MouseMoveListener;
+import org.eclipse.swt.events.MouseWheelListener;
+
+/**
+ * <b><u>HistogramCanvasMouseListener</u></b>
+ * <p>
+ * Implementation of a MouseListener for the need of the HistogramCanvas
+ * <p>
+ */
+public class HistogramCanvasMouseListener implements MouseMoveListener, MouseListener, MouseWheelListener
+{
+ protected DelayedMouseScroll mouseScrollListener = null;
+ protected HistogramCanvas parentCanvas = null;
+
+ protected boolean isWindowMoving = false;
+
+ /**
+ * HistogramCanvasMouseListener constructor
+ *
+ * @param newCanvas Related canvas
+ */
+ public HistogramCanvasMouseListener(HistogramCanvas newCanvas) {
+ parentCanvas = newCanvas;
+ }
+
+ /**
+ * Function called when the mouse is moved.<p>
+ * If the mouse button is clicked, we will move the selection window.
+ *
+ * @param event The generated mouse event when the mouse moved.
+ */
+ public void mouseMove(MouseEvent event) {
+ if ( isWindowMoving == true ) {
+ parentCanvas.setWindowCenterPosition(event.x);
+ }
+ }
+
+ /**
+ * Function called when the mouse buttons are clicked.<p>
+ * If the button is the first one (left button), turn on the "move window" mode
+ *
+ * @param event The generated mouse event when the mouse button was pressed.
+ */
+ public void mouseDown(MouseEvent event) {
+ if ( event.button == 1) {
+ isWindowMoving = true;
+ parentCanvas.setWindowCenterPosition(event.x);
+ }
+ }
+
+ /**
+ * Function called when the mouse buttons are released.<p>
+ * If the button is the first one (left button), turn off the "move window" mode
+ *
+ * @param event The generated mouse event when the mouse button was released.
+ */
+ public void mouseUp(MouseEvent event) {
+ if ( event.button == 1) {
+ isWindowMoving = false;
+ parentCanvas.notifyParentSelectionWindowChangedAsynchronously();
+ }
+ }
+
+ /**
+ * Function called when the mouse perform a double-click.<p>
+ * Don't do anything yet...
+ *
+ * @param event The generated mouse event when the mouse double-click was issued.
+ */
+ public void mouseDoubleClick(MouseEvent event) {
+ System.out.println("mouseDoubleClick");
+ }
+
+ /**
+ * Function called when the mouse scroll button is used.<p>
+ * Start a "ScrollListener" that will wait for more scroll clicks as they are asynchonous.
+ * After a certain delay, the parent canvas will get notified.
+ *
+ * @param event The generated mouse event when the mouse scroll was spinned.
+ */
+ public void mouseScrolled(MouseEvent event) {
+
+ // Start a scrollListener if none exist yet and start its thread
+ // Otherwise, we will just notify the one that is currenly alive...
+ // Badly timed event could happen while the thread is dying but we can live with loss scroll events, I believe.
+ if ( mouseScrollListener == null ) {
+ mouseScrollListener = new DelayedMouseScroll(this, HistogramConstant.FULL_WAIT_MS_TIME_BETWEEN_MOUSE_SCROLL, HistogramConstant.INTERVAL_WAIT_MS_TIME_BETWEEN_POLL );
+ mouseScrollListener.start();
+ }
+
+ // *** NOTE ***
+ // We need to refer to the "count" to know if the scroll is done backward or forward.
+ // Positive count mean it is done backward (from the wall in the direction of the hand)
+ // Negative count mean it is done backward (from the hand in the direction of the wall)
+ if ( event.count > 0) {
+ mouseScrollListener.incrementMouseScroll();
+ }
+ else {
+ mouseScrollListener.decrementMouseScroll();
+ }
+ }
+
+ /**
+ * Function that will be called at the end of the "wait time" for scroll events.<p>
+ * This will calculate the correct zoom time and call the canvas to resize its selection window.
+ *
+ * @param nbMouseScroll
+ */
+ public void receiveMouseScrollCount(int nbMouseScroll) {
+ mouseScrollListener = null;
+
+ long ajustedTime = 0;
+
+ // If we received Negative scroll event, ZoomOut by ZOOM_OUT_FACTOR * the number of scroll events received.
+ if ( nbMouseScroll < 0 ) {
+ ajustedTime = (long)((double)parentCanvas.getSelectedWindowSize() * HistogramConstant.ZOOM_OUT_FACTOR);
+ ajustedTime = ajustedTime * Math.abs(nbMouseScroll);
+ ajustedTime = parentCanvas.getSelectedWindowSize() + ajustedTime;
+ }
+ // If we received Positive scroll event, ZoomIn by ZOOM_IN_FACTOR * the number of scroll events received.
+ else {
+ ajustedTime = (long)((double)parentCanvas.getSelectedWindowSize() * HistogramConstant.ZOOM_IN_FACTOR);
+ ajustedTime = ajustedTime * Math.abs(nbMouseScroll);
+ ajustedTime = parentCanvas.getSelectedWindowSize() - ajustedTime;
+ }
+
+ // Resize the canvas selection window
+ parentCanvas.resizeWindowByAbsoluteTime(ajustedTime);
+ }
+
+}
+
+/**
+ * <b><u>DelayedMouseScroll Inner Class</u></b>
+ * <p>
+ * Asynchronous "Mouse Scroll Listener"
+ * <p>
+ * This class role is to wait for mouse scroll and count them during a certain delay.<p>
+ * Once the time is up, it will notify the mouse listener of the number of scroll events received.<p>
+ *
+ * Note that a new scroll event received will reset the wait timer.
+ */
+class DelayedMouseScroll extends Thread {
+
+ private HistogramCanvasMouseListener mouseListener = null;
+
+ private long waitTimeBetweenScroll = 0;
+ private long waitTimeBetweenCheck = 0;
+
+ private long lastScrollTime = 0L;
+ private int nbScrollClick = 0;
+
+ /**
+ * Constructor of the DelayedMouseScroll listener.<p>
+ * Object will be initialized but start() need to be called for it start listening for scroll.
+ *
+ * @param newListener The parent mouse listener
+ * @param newWaitFullTime The time to wait for scroll events
+ * @param newWaitBeforeCheck The delay between polling for scroll events
+ */
+ public DelayedMouseScroll(HistogramCanvasMouseListener newListener, long newWaitFullTime, long newWaitBeforePoll) {
+
+ mouseListener = newListener;
+
+ // Get the current system time.
+ // This will be used to determine since how long we wait for click
+ lastScrollTime = System.currentTimeMillis();
+
+ waitTimeBetweenScroll = newWaitFullTime;
+ waitTimeBetweenCheck = newWaitBeforePoll;
+ }
+
+ /**
+ * Increment the counter for the number of scroll events received.<p>
+ * This is intended to be called by the MouseListener.
+ *
+ * Note : A new scroll event receive will reset the wait timer.
+ */
+ public void incrementMouseScroll() {
+ // Reset the wait timer
+ lastScrollTime = System.currentTimeMillis();
+ nbScrollClick++;
+ }
+
+ /**
+ * Decrement the counter for the number of scroll events received.<p>
+ * This is intended to be called by the MouseListener.
+ *
+ * Note : A new scroll event receive will reset the wait timer.
+ */
+ public void decrementMouseScroll() {
+ // Reset the wait timer
+ lastScrollTime = System.currentTimeMillis();
+ nbScrollClick--;
+ }
+
+ /**
+ * Threaded execution method.<p>
+ * This is the real "wait" method that will wait for mouse scroll events.<p>
+ *
+ * The function will wake every "waitTimeBetweenCheck" to check if we exhausted the timer.<p>
+ * So, the "longest" we could wait after the last event is "waitTimeBetweenScroll" + "waitTimeBetweenCheck"
+ *
+ */
+ @Override
+ public void run() {
+ // Check if we waited more than "waitTimeBetweenScroll"
+ while ( (System.currentTimeMillis() - lastScrollTime) < waitTimeBetweenScroll ) {
+ try {
+ Thread.sleep(waitTimeBetweenCheck);
+ }
+ catch (Exception e) { }
+ }
+
+ // Tell the mouse listener the number of click received
+ mouseListener.receiveMouseScrollCount(nbScrollClick);
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * William Bourque - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.histogram;
+
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.Rectangle;
+
+/**
+ * <b><u>HistogramCanvasPaintListener</u></b>
+ * <p>
+ * Implementation of a PaintListener for the need of the HistogramCanvas
+ * <p>
+ */
+public class HistogramCanvasPaintListener implements PaintListener
+{
+ protected HistogramCanvas parentCanvas = null;
+
+ /**
+ * HistogramCanvasPaintListener constructor
+ *
+ * @param parentCanvas Related canvas
+ */
+ public HistogramCanvasPaintListener(HistogramCanvas newParentCanvas) {
+ parentCanvas = newParentCanvas;
+ }
+
+ /**
+ * Function called when the canvas need to redraw.<p>
+ *
+ * @param event The generated paint event when redraw is called.
+ */
+ public void paintControl(PaintEvent event) {
+
+ // First clear the whole canvas to have a clean section where to draw
+ clearDrawingSection(event);
+
+ // If the content is null or has rady to draw we quit the function here
+ if ( (parentCanvas.getHistogramContent() == null) || (parentCanvas.getHistogramContent().getReadyUpToPosition() == 0) ) {
+ return;
+ }
+
+ // Call the function that draw the bars
+ drawHistogram(event);
+
+ // Pinpoint a position if set
+ if (parentCanvas.getHistogramContent().getSelectedEventTimeInWindow() > 0 ) {
+ drawSelectedEventInWindow(event);
+ }
+
+ // If we have a selected window set to visible, call the function to draw it
+ if ( (parentCanvas.getCurrentWindow() != null) && (parentCanvas.getCurrentWindow().getSelectedWindowVisible() == true) ) {
+ drawSelectedWindow(event);
+ }
+ }
+
+ /**
+ * Clear the drawing section of the canvas<p>
+ * This paint the whole background in EMPTY_BACKGROUND_COLOR, so we have something clean to draw on.
+ *
+ * @param event The generated paint event when redraw is called.
+ */
+ public void clearDrawingSection(PaintEvent event) {
+ event.gc.setForeground(event.display.getSystemColor(HistogramConstant.EMPTY_BACKGROUND_COLOR));
+ event.gc.setBackground(event.display.getSystemColor(HistogramConstant.EMPTY_BACKGROUND_COLOR));
+ Rectangle allSection = new Rectangle(0, 0, event.width, event.height);
+ event.gc.fillRectangle(allSection);
+ event.gc.drawRectangle(allSection);
+ }
+
+ // *** VERIFY ***
+ // Is it good to put this synchronized?
+ //
+ /**
+ * Draw the histogram bars in the canvas.<p>
+ * Use existing elements in HistogramContent to draw bars on the cancas;
+ * the element table in content need to be populated and have consistent value.
+ *
+ * @param event The generated paint event when redraw is called.
+ */
+ public synchronized void drawHistogram(PaintEvent event) {
+ HistogramContent tmpContent = parentCanvas.getHistogramContent();
+ int tmpBarWidth = tmpContent.getBarsWidth();
+
+ // This will be the color for all the bars that wil be draw below.
+ event.gc.setBackground(event.display.getSystemColor(HistogramConstant.HISTOGRAM_BARS_COLOR));
+
+ // *** NOTE ***
+ // Y Position in a canvas is REVERSED, so "0" is on top of the screen and "MAX" is on bottom.
+ // Not very instinctive, isn't it?
+
+ // Draw a bar from the left (pos X=0) until the pos=(NbBars*barWidth). If space is left, it will be blanked after.
+ for ( int x=0; x<tmpContent.getReadyUpToPosition(); x++) {
+ Rectangle rect = new Rectangle(tmpBarWidth*x, event.height - tmpContent.getElementByIndex(x).intervalHeight, tmpBarWidth, tmpContent.getElementByIndex(x).intervalHeight);
+ event.gc.fillRectangle(rect);
+ }
+
+ // Clear the remaining space in the canvas (if any) so it appears clean.
+ event.gc.setBackground(event.display.getSystemColor(HistogramConstant.EMPTY_BACKGROUND_COLOR));
+ Rectangle rect = new Rectangle(tmpBarWidth*tmpContent.getNbElement(), 0, event.width, event.height);
+ event.gc.fillRectangle(rect);
+ }
+
+ /**
+ * Draw a certain event selected in the window.<p>
+ *
+ * @param event The generated paint event when redraw is called.
+ */
+ public synchronized void drawSelectedEventInWindow(PaintEvent event) {
+ HistogramContent tmpContent = parentCanvas.getHistogramContent();
+ int tmpBarWidth = tmpContent.getBarsWidth();
+
+ // This will be the color for all the bars that wil be draw below.
+ event.gc.setBackground(event.display.getSystemColor(HistogramConstant.SELECTED_EVENT_COLOR));
+
+ int position = tmpContent.getClosestXPositionFromTimestamp(tmpContent.getSelectedEventTimeInWindow());
+
+ Rectangle rect = new Rectangle(tmpBarWidth*position, 0, tmpBarWidth, event.height);
+ event.gc.fillRectangle(rect);
+ }
+
+ /**
+ * Draw the selection window in the canvas.<p>
+ * This draw a square around the selected section with a crosshair in the middle.
+ * The square cannot be smaller than "MINIMUM_WINDOW_WIDTH"
+ *
+ * @param event The generated paint event when redraw is called.
+ */
+ public void drawSelectedWindow(PaintEvent event) {
+ HistogramSelectedWindow tmpWindow = parentCanvas.getCurrentWindow();
+
+ // Attributes (color and width) of the lines
+ event.gc.setForeground(event.display.getSystemColor(HistogramConstant.SELECTION_WINDOW_COLOR));
+ event.gc.setLineWidth(HistogramConstant.SELECTION_LINE_WIDTH);
+
+ // Get the window position... this would fail if the window is not initialized yet
+ int positionCenter = tmpWindow.getWindowXPositionCenter();
+ int positionLeft = tmpWindow.getWindowXPositionLeft();
+ int positionRight = tmpWindow.getWindowXPositionRight();
+
+ // Minimal size verification.
+ if ( (positionRight - positionLeft) < HistogramConstant.MINIMUM_WINDOW_WIDTH ) {
+ positionLeft = positionCenter - (HistogramConstant.MINIMUM_WINDOW_WIDTH/2);
+ positionRight = positionCenter + (HistogramConstant.MINIMUM_WINDOW_WIDTH/2);
+ }
+
+ // Draw the selection window square
+ event.gc.drawLine(positionLeft , 0 , positionLeft , event.height);
+ event.gc.drawLine(positionLeft , event.height, positionRight, event.height);
+ event.gc.drawLine(positionRight, event.height, positionRight, 0);
+ event.gc.drawLine(positionLeft , 0 , positionRight, 0);
+
+ // Draw the crosshair section
+ event.gc.drawLine(positionCenter + HistogramConstant.SELECTION_CROSSHAIR_LENGTH, event.height/2, positionCenter - HistogramConstant.SELECTION_CROSSHAIR_LENGTH, event.height/2);
+ event.gc.drawLine(positionCenter, (event.height/2) + HistogramConstant.SELECTION_CROSSHAIR_LENGTH, positionCenter, (event.height/2) - HistogramConstant.SELECTION_CROSSHAIR_LENGTH);
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * William Bourque - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.histogram;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * <b><u>HistogramConstant</u></b>
+ * <p>
+ * Empty interface class to hold the different constants needed by the histogram.
+ * <p>
+ */
+public abstract class HistogramConstant {
+ // Constants relative to requests
+ public final static int MAX_EVENTS_PER_READ = 1;
+ public final static int REDRAW_EVERY_NB_EVENTS = 10000;
+ public final static Boolean SKIP_EMPTY_INTERVALS_WHEN_CALCULATING_AVERAGE = true;
+
+
+ // Constant relative to the content
+ public final static double DEFAULT_DIFFERENCE_TO_AVERAGE = 1000.0;
+
+
+
+ // Constants relative to zoom. Factors need to be a percentage ( 0 < factors < 1 )
+ public final static double ZOOM_IN_FACTOR = 0.1;
+ public final static double ZOOM_OUT_FACTOR = 0.1;
+
+
+ // Constants relative to wait time while listening for scroll events
+ // "FULL" is time to wait to stop "to count" mouse scroll click events
+ // "INTERVAL" is time to wait between polling for scroll click events
+ public final static long FULL_WAIT_MS_TIME_BETWEEN_MOUSE_SCROLL = 500L;
+ public final static long INTERVAL_WAIT_MS_TIME_BETWEEN_POLL = 100L;
+
+
+ // Constants relative to the displacement in the trace
+ // Factor represent a number of HistogramContent interval
+ // Multiple is the factor to multiply to basic during "fast" displacement
+ public final static int BASIC_DISPLACEMENT_FACTOR = 1;
+ public final static double FAST_DISPLACEMENT_MULTIPLE = 10.0;
+
+
+ // Constants relative to the drawing of the Histogram
+ // Colors for the histogram. Background should be the same as the background in use
+ public final static int EMPTY_BACKGROUND_COLOR = SWT.COLOR_WHITE;
+ public final static int HISTOGRAM_BARS_COLOR = SWT.COLOR_DARK_CYAN;
+ public final static int SELECTED_EVENT_COLOR = SWT.COLOR_RED;
+ public final static int SELECTION_WINDOW_COLOR = SWT.COLOR_RED;
+
+ // Dimension for the line of the "Selection Window"
+ public final static int MINIMUM_WINDOW_WIDTH = 3;
+ public final static int SELECTION_LINE_WIDTH = 2;
+ public final static int SELECTION_CROSSHAIR_LENGTH = 3;
+
+
+ /**
+ * Method to format a long representing nanosecond into a proper String.<p>
+ * The returned String will always be like "0.000000000", missing decimal will be added.
+ *
+ * @param nanosecTime This time to format
+ *
+ * @return The formatted string
+ */
+ public static String formatNanoSecondsTime(long nanosecTime) {
+ String returnedTime = Long.toString(nanosecTime);
+
+ // If our number has over 9 digits, just add a dot after the ninth digits
+ if ( returnedTime.length() > 9 ) {
+ returnedTime = returnedTime.substring(0, returnedTime.length() - 9 ) + "." + returnedTime.substring( returnedTime.length() - 9 );
+ }
+ // Otherwise, patch missing decimal with 0
+ else {
+ int curSize = returnedTime.length();
+ for (int l=0; (curSize+l)< 9; l++) {
+ returnedTime = "0" + returnedTime;
+ }
+ returnedTime = "0." + returnedTime;
+ }
+
+ return returnedTime;
+ }
+
+ /**
+ * Convert a String representing nanoseconds into a valid long.<p>
+ * This can handle number like "0.5", "0.123456789" as well as plain number like "12".<p>
+ *
+ * Note : This function ALWAYS return a number, if conversion failed, 0 will be returned.<p>
+ *
+ * @param timeString The string to convert
+ *
+ * @return The converted nanoseconds time as long
+ */
+ public static long convertStringToNanoseconds( String timeString ) {
+ long returnedNumber = 0L;
+
+ try {
+ // Avoid simple commat/dot mistake
+ timeString = timeString.replace(",", ".");
+
+ // If we have a dot, we have a decimal number to convert
+ int dotPosition = timeString.indexOf(".");
+
+ // If the user begun the line with a dot, we add a zero
+ if ( dotPosition == 0 ) {
+ timeString = "0" + timeString;
+ dotPosition = 1;
+ }
+
+ // If we found a dot, verify that we have 9 digits
+ if ( dotPosition != -1 ) {
+ int decimalNumber = (timeString.length() - dotPosition -1);
+
+ // If we have less than 9 digits, we fill with 0
+ if ( decimalNumber <= 9 ) {
+ StringBuffer strBuffer = new StringBuffer(timeString);
+ for ( int nbDec=decimalNumber; nbDec<9; nbDec++) {
+ strBuffer.append("0");
+ }
+ timeString = strBuffer.toString();
+ }
+ // We have OVER 9 digits, skip the useless part
+ else {
+ timeString = timeString.substring(dotPosition, 9);
+ }
+ }
+
+ // Conversion into decimal seconds
+ double dblMaxTimerange = Double.parseDouble(timeString);
+ // Conversion into nanoseconds
+ returnedNumber = (long)(dblMaxTimerange * 1000000000.0);
+ }
+ catch (NumberFormatException e) {
+ System.out.println("Warning : Could not convert string into nanoseconds (convertStringToLong)");
+ }
+
+ return returnedNumber;
+ }
+
+ /**
+ * Calculate the correcte width of a String.<p>
+ * Useful to set a control to its maximum size; since the size depends on characters,
+ * this will calculate the correct sum... should be platform independant (we hope).
+ *
+ * @param parent Parent control we will use as a reference. Could be any composite.
+ * @param text The Text to measure the size from
+ *
+ * @return The size calculated.
+ */
+ public static int getTextSizeInControl(Composite parent, String text) {
+ GC graphicContext = new GC(parent);
+ int textSize = 0;
+ for ( int pos=0; pos<text.length(); pos++ ) {
+ textSize += graphicContext.getAdvanceWidth( text.charAt(pos) );
+ }
+ // Add an extra space in case there was trailing whitespace in the message
+ textSize += graphicContext.getAdvanceWidth( ' ' );
+
+ return textSize;
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * William Bourque - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.histogram;
+
+
+/**
+ * <b><u>HistogramContent</u></b>
+ * <p>
+ * This class hold the content that will be used to draw the Histograms.
+ * <p>
+ */
+public class HistogramContent {
+
+ // Start and end time of the content
+ protected long startTime = 0L;
+ protected long endTime = 0L;
+
+ // Some information about the content
+ // Most of them are required to calculate position and/or draw
+ // Make sure they stay consistent!
+ protected long elementsTimeInterval = 1L;
+ protected double heightFactor = 100.0;
+ protected long heighestEventCount = 0L;
+ protected int maxHeight = 0;
+ protected int canvasWindowSize = 0;
+ protected int barsWidth = 0;
+
+ // This value is used to calculate at which point we should "cut" bar that are too tall.
+ // Default value is large enought so that no bar should be cut
+ protected double maxDifferenceToAverage = HistogramConstant.DEFAULT_DIFFERENCE_TO_AVERAGE;
+ // This is a factor we might apply on the max difference to average, as example if we concatenate interval together
+ protected double maxDifferenceFactor = 1.0;
+
+ // By default we will only consider element up to this position
+ protected int readyUpToPosition = 0;
+
+ // The average number of events in the content
+ // Note : this IS needed to draw
+ protected int averageNumberOfEvents = 0;
+
+ // This is to draw the selected event of the TMF framework in another color
+ // Set the 0 to ignore
+ protected long selectedEventTimeInWindow = -1L;
+
+ // The table that hold the elements
+ protected HistogramElement[] elementTable;
+
+
+ /**
+ * Default constructor for the HistogramContent.
+ *
+ * @param tableSize The size ofthe element table that will be created.
+ * @param newCanvasSize The full size of the canvas. Used for positionning; need to be consistent with canvas.
+ * @param newMaxHeight The maximum height of a bar, usually same as the height of the canvas.
+ */
+ public HistogramContent(int tableSize, int newCanvasSize, int newBarWidth, int newMaxHeight) {
+ this(tableSize, newCanvasSize, newBarWidth, newMaxHeight, HistogramConstant.DEFAULT_DIFFERENCE_TO_AVERAGE);
+ }
+
+ /**
+ * Default constructor for the HistogramContent.
+ *
+ * @param tableSize The size ofthe element table that will be created.
+ * @param newCanvasSize The full size of the canvas. Used for positionning; need to be consistent with canvas.
+ * @param newMaxHeight The maximum height of a bar, usually same as the height of the canvas.
+ * @param newDiffToAverage This value at which point we "cut" bar that are too tall.
+ */
+ public HistogramContent(int tableSize, int newCanvasSize, int newBarWidth, int newMaxHeight, double newDiffToAverage) {
+ canvasWindowSize = newCanvasSize;
+ barsWidth = newBarWidth;
+ maxHeight = newMaxHeight;
+ maxDifferenceToAverage = newDiffToAverage;
+
+ // Create a new element table from the above value
+ // The table will not get initialized until resetTable() is called.
+ createNewTable(tableSize);
+ }
+
+ /**
+ * Create a new table to hold the content element.<p>
+ * Note that the table is not initialized (and so unusable) until resetTable() is called.
+ *
+ * @param newTableSize The size (number of element) of the table.
+ */
+ public void createNewTable(int newTableSize) {
+ elementTable = new HistogramElement[newTableSize];
+
+ for ( int x=0; x<elementTable.length; x++) {
+ elementTable[x] = new HistogramElement();
+ elementTable[x].index = x;
+ }
+ }
+
+ /**
+ * Reset all HistogramContent attributes, but keep the elements table untouched.<p>
+ */
+ public void clearContentData() {
+ startTime = 0L;
+ endTime = 0L;
+
+ elementsTimeInterval = 1L;
+ heightFactor = 100.0;
+ heighestEventCount = 0L;
+
+ readyUpToPosition = 0;
+ }
+
+ /**
+ * Reset the data in the elements table.<p>
+ * NOTE : For this to be consistent and usuable, "startTime", "endTime" and "intervalTime" need to be set already.
+ */
+ public void resetTable() {
+ for ( int x=0; x<elementTable.length; x++) {
+ elementTable[x].index = x;
+ elementTable[x].firstIntervalTimestamp = startTime + (x*elementsTimeInterval);
+ elementTable[x].intervalNbEvents = 0L;
+ elementTable[x].intervalHeight = 0;
+ }
+ }
+
+ /**
+ * Reset the data in the elements table.<p>
+ * Start and EndTime will be used to calculate elementsTimeInterval.<p>
+ *
+ * @param newStartTime The new start time to use
+ * @param newEndTime The new stop time to use
+ */
+ public void resetTable(long newStartTime, long newEndTime) {
+ recalculateElementsTimeInterval(newStartTime, newEndTime);
+ resetTable(newStartTime, newEndTime, elementsTimeInterval);
+ }
+
+ /**
+ * Reset the data in the elements table.<p>
+ * elementsTimeInterval will be set to the one give, use this for fixed interval.<p>
+ *
+ * @param newStartTime The new start time to use
+ * @param newEndTime The new stop time to use
+ * @param newTimeInterval The new time interval to use
+ */
+ public void resetTable(long newStartTime, long newEndTime, long newTimeInterval) {
+
+ startTime = newStartTime;
+ endTime = newEndTime;
+ recalculateElementsTimeInterval(newStartTime, newEndTime);
+
+ for ( int x=0; x<elementTable.length; x++) {
+ elementTable[x].index = x;
+ elementTable[x].firstIntervalTimestamp = startTime + (x*elementsTimeInterval);
+ elementTable[x].intervalNbEvents = 0L;
+ elementTable[x].intervalHeight = 0;
+ }
+ }
+
+ /**
+ * Clear (zeroed) the data in the elements table.<p>
+ * NOTE : Unlike reset, this does not recalculate the content,
+ * so it should be done either by hand or by calling reset table after.
+ */
+ public void clearTable() {
+ for ( int x=0; x<elementTable.length; x++) {
+ elementTable[x].index = x;
+ elementTable[x].firstIntervalTimestamp = 0L;
+ elementTable[x].intervalNbEvents = 0L;
+ elementTable[x].intervalHeight = 0;
+ }
+ }
+
+ /**
+ * Print all HistogramContent attributes, but the elements table.
+ */
+ public void printContentInfo() {
+ System.out.println("startTime : " + startTime);
+ System.out.println("endTime : " + endTime );
+ System.out.println();
+ System.out.println("intervalTime : " + elementsTimeInterval);
+ System.out.println("heightFactor : " + heightFactor);
+ System.out.println("heighestEventCount : " + heighestEventCount);
+ System.out.println();
+ System.out.println("readyUpToPosition : " + readyUpToPosition);
+ }
+
+ /**
+ * Print the data in the elements table.<p>
+ */
+ public void printTable() {
+ for ( int x=0; x<elementTable.length; x++) {
+ System.out.println("X:" + x + " -> " + elementTable[x].intervalNbEvents + ":" + elementTable[x].intervalHeight + " (" + elementTable[x].firstIntervalTimestamp + ")");
+ }
+ }
+
+ /**
+ * Getter for the timestamp of the selected event in the window.<p>
+ *
+ * @return The time of the event.
+ */
+ public long getSelectedEventTimeInWindow() {
+ return selectedEventTimeInWindow;
+ }
+
+ /**
+ * Setter for the timestamp of the selected event in the window.<p>
+ *
+ * This allow to pinpoint a certain event or position in the window.
+ * Set to 0 or lower to ignore.
+ *
+ * @param newPosition The new event time.
+ */
+ public void setSelectedEventTimeInWindow(long newTime) {
+ this.selectedEventTimeInWindow = newTime;
+ }
+
+ /**
+ * Get an element in the table by its index.<p>
+ * Null is returned if the index is out of range.<p>
+ * Note that you can get an element past "readyUpToPosition", the index is NOT tested against it.
+ *
+ * @param index The index of the element (0 < index < nbElement)
+ *
+ * @return The element found or null if the index is wrong.
+ */
+ public HistogramElement getElementByIndex(int index) {
+ HistogramElement returnedElement = null;
+
+ if ( (index >= 0) && (index < elementTable.length) ) {
+ returnedElement = elementTable[index];
+ }
+
+ return returnedElement;
+ }
+
+ /**
+ * Return the closest element to a X position on the canvas.<p>
+ * Note : canvasWindowSize need to be set correctly here, otherwise unexpected element might be returned.<p>
+ * <p>
+ * NOTE : This <b>ALWAYS</b> return an element;
+ * If calculation lead outside the table, the first or the last element will be returned.
+ *
+ * @param position The X position we are looking at (0 < pos < canvasWidth)
+ *
+ * @return The <i>closest</i> element found.
+ */
+ public HistogramElement getClosestElementFromXPosition(int position) {
+
+ int index = (int)Math.round((double)elementTable.length * ((double)position / (double)canvasWindowSize) );
+
+ // If we are out of bound, return the closest border (first or last element)
+ if ( index < 0) {
+ index = 0;
+ }
+ else if ( index >= elementTable.length ) {
+ index = (elementTable.length -1);
+ }
+
+ return elementTable[index];
+ }
+
+ /**
+ * Return the closest element's timestamp to a X position on the canvas.<p>
+ * Note : canvasWindowSize need to be set correctly here, otherwise unexpected timestamp might be returned.<p>
+ * <p>
+ * NOTE : This <b>ALWAYS</b> return a timestamp;
+ * If calculation lead outside the table, the first or the last timestamp will be returned.
+ *
+ * @param position The X position we are looking at (0 < pos < canvasWidth)
+ *
+ * @return The <i>closest</i> timestamp found.
+ */
+ public long getClosestTimestampFromXPosition(int position) {
+ return getClosestElementFromXPosition(position).firstIntervalTimestamp;
+ }
+
+ /**
+ * Return the X position (relative to the canvas) of a certain element.<p>
+ * Note : canvasWindowSize need to be set correctly here, otherwise unexpected element might be returned.<p>
+ *
+ * NOTE : This <b>ALWAYS</b> return an element;
+ * If calculation lead outside the table, the first or the last element will be returned.
+ *
+ * @param targetElement The element we are looking to find the position
+ *
+ * @return The <i>closest</i> found element.
+ */
+ public int getXPositionFromElement(HistogramElement targetElement) {
+ return (int)Math.round( ((double)targetElement.index / (double)elementTable.length)*(double)canvasWindowSize );
+ }
+
+ /**
+ * Return the closest element to a timestamp (long) given.<p>
+ * Note : startTime and intervalTime need to be set correctly here, otherwise unexpected element might be returned.<p>
+ * <p>
+ * NOTE : This <b>ALWAYS</b> return an element;
+ * If calculation lead outside the table, the first or the last element will be returned.
+ *
+ * @param timestamp The timestamp (in nanosecond, as long) of the element we are looking for (startTime < timestamp < endTime)
+ *
+ * @return The <i>closest</i> element found.
+ */
+ public HistogramElement getClosestElementFromTimestamp(long timestamp) {
+ int index = (int)Math.round( (double)(timestamp - startTime)/(double)elementsTimeInterval );
+
+ // If we are out of bound, return the closest border (first or last element)
+ if ( index < 0) {
+ index = 0;
+ }
+ else if ( index >= elementTable.length ) {
+ index = (elementTable.length -1);
+ }
+
+ return elementTable[index];
+ }
+
+ /**
+ * Return the closest X position to a timestamp (long) given.<p>
+ * Note : startTime and intervalTime need to be set correctly here, otherwise unexpected position might be returned.<p>
+ * <p>
+ * NOTE : This <b>ALWAYS</b> return a position;
+ * If calculation lead outside the table, the first or the last position will be returned.
+ *
+ * @param timestamp The timestamp (in nanosecond, as long) of the element we are looking for (startTime < timestamp < endTime)
+ *
+ * @return The <i>closest</i> position found.
+ */
+ public int getClosestXPositionFromTimestamp(long timestamp) {
+ return getXPositionFromElement(getClosestElementFromTimestamp(timestamp));
+ }
+
+ /**
+ * Return the closest element to an element and a time interval to this element.<p>
+ * The time interval can be negative or positive (before or after the element).
+ *
+ * Note : IntervalTime and StartTime need to be set correctly here, otherwise unexpected result might be returned.<p>
+ *
+ * @param targetElement The element we compare the interval with.
+ * @param intervalToElement Time negative or positive time interval (in nanosecond) to this element.
+ *
+ * @return The <i>closest</i> found element, or null if given data are wrong.
+ */
+ public HistogramElement getClosestElementByElementAndTimeInterval(HistogramElement targetElement, long intervalToElement) {
+
+ // Get the timestamp of the target element
+ // This should always be valid as long the table is initialized
+ long elementTime = targetElement.firstIntervalTimestamp;
+ elementTime = elementTime + intervalToElement;
+
+ return getClosestElementFromTimestamp(elementTime);
+ }
+
+ /**
+ * Return the closest element to an element's timestamp (as long) and a time interval to this element.<p>
+ * The time interval can be negative or positive (before or after the element).
+ *
+ * Note : IntervalTime and StartTime need to be set correctly here, otherwise unexpected result might be returned.<p>
+ *
+ * @param timestamp The timestamp (in nanoseconds, as long) of the element we want to compare from.
+ * @param intervalToElement Time negative or positive time interval (in nanosecond) to this element.
+ *
+ * @return The <i>closest</i> found element, or null if given data are wrong.
+ */
+ public int getClosestElementByTimestampAndTimeInterval(long timestamp, long intervalToElement) {
+ HistogramElement targetElement = getClosestElementFromTimestamp(timestamp);
+ HistogramElement newElement = getClosestElementByElementAndTimeInterval(targetElement, intervalToElement);
+
+ return getXPositionFromElement(newElement);
+ }
+
+ /**
+ * Return the closest element to an element's position and a time interval to this element.<p>
+ * The time interval can be negative or positive (before or after the element).
+ *
+ * Note : IntervalTime and StartTime need to be set correctly here, otherwise unexpected result might be returned.<p>
+ *
+ * @param targetPosition The position (relative to the canvas) of the element we want to compare from.
+ * @param intervalToElement Time negative or positive time interval (in nanosecond) to this element.
+ *
+ * @return The <i>closest</i> found element, or null if given data are wrong.
+ */
+ public int getXPositionByPositionAndTimeInterval(int targetPosition, long intervalToElement) {
+ HistogramElement targetElement = getClosestElementFromXPosition(targetPosition);
+ HistogramElement newElement = getClosestElementByElementAndTimeInterval(targetElement, intervalToElement);
+
+ return getXPositionFromElement(newElement);
+ }
+
+ /**
+ * Getter for the number of element.<p>
+ * The same as the value of tableSize given at construction.
+ *
+ * @return The number of element in the elements table.
+ */
+ public int getNbElement() {
+ return elementTable.length;
+ }
+
+ /**
+ * Getter for the average number of events by interval in the content.<p>
+ *
+ * Note : Might be set externally (instead of calculated internally), so consistency with the content is not guarantee.
+ *
+ * @return Average number of events we currently use in
+ */
+ public int getAverageNumberOfEvents() {
+ return averageNumberOfEvents;
+ }
+
+ /**
+ * Setter for averageNumberOfEvents.<p>
+ *
+ * Note : this is used in some drawing calculation so make sure this number make sense.
+ * Note : you might want to call recalculateEventHeight() if you change this.
+ *
+ * @param newAverageNumberOfEvents The new average number of events to use.
+ */
+ public void setAverageNumberOfEvents(int newAverageNumberOfEvents) {
+ this.averageNumberOfEvents = newAverageNumberOfEvents;
+ }
+
+ /**
+ * Recalculate the average number of events by time interval.<p>
+ *
+ * Note : This run over all the element so this is quite cpu intensive, use with care.
+ */
+ public void recalculateAverageNumberOfEvents() {
+
+ int nbInterval = 0;
+ int totalNbEvents = 0;
+
+ // Go over the element up to readyUpToPosition (further position might not be ready)
+ for ( int x=0; x<readyUpToPosition; x++) {
+ // Skip the empty interval if we were asked to do so.
+ if ( HistogramConstant.SKIP_EMPTY_INTERVALS_WHEN_CALCULATING_AVERAGE ) {
+ if ( elementTable[x].intervalNbEvents > 0 ) {
+ nbInterval++;
+ }
+ }
+ else {
+ nbInterval++;
+ }
+
+ totalNbEvents += elementTable[x].intervalNbEvents;
+ }
+ // Calculate the average here
+ averageNumberOfEvents = (int)Math.round((double)totalNbEvents / (double)nbInterval);
+ }
+
+ /**
+ * Getter for the start time of the content.<p>
+ *
+ * @return The start time we currently use.
+ */
+ public long getStartTime() {
+ return startTime;
+ }
+
+ /**
+ * Setter for the start time of the content.<p>
+ * Note : You probably want to call "resetTable()" if you change this, otherwise data might be inconsistent.
+ *
+ * @param newStartTime the new start time
+ */
+ public void setStartTime(long newStartTime) {
+ this.startTime = newStartTime;
+ }
+
+
+ /**
+ * Getter for the end time of the content.<p>
+ *
+ * @return The end time we currently use.
+ */
+ public long getEndTime() {
+ return endTime;
+ }
+
+ /**
+ * Setter for the end time of the content.<p>
+ * Note : You probably want to call "resetTable()" if you change this, otherwise data might be inconsistent.
+ *
+ * @param newStartTime the new end time
+ */
+ public void setEndTime(long newEndTime) {
+ this.endTime = newEndTime;
+ }
+
+ /**
+ * Getter for the complete time interval of the content.<p>
+ * Note : This return "endTime" minus "startTime", unlike getReadyTimeInterval() it won't check the actual time of elements.
+ *
+ * @return The complete time interval
+ */
+ public long getCompleteTimeInterval() {
+ return ( endTime - startTime );
+ }
+
+ /**
+ * Getter for the time interval for the element between first and readyUpToPosition<p>
+ * Note : This return element[readyPosition].time - element[first].time , not the full interval like getCompleteTimeInterval()
+ *
+ * @return The time interval of the position that are ready.
+ */
+ public long getReadyTimeInterval() {
+ return ( elementTable[readyUpToPosition].firstIntervalTimestamp - elementTable[0].firstIntervalTimestamp );
+ }
+
+ /**
+ * Getter for the height factor of the bar.<p>
+ * Note : height = "nb events in interval" * heightFactor
+ *
+ * @return Height factor currently used.
+ */
+ public double getHeightFactor() {
+ return heightFactor;
+ }
+
+ /**
+ * Recalculate the height factor of the element table.<p>
+ * Assume values of "maxHeight", "heighestEventCount" or "averageNumberOfEvents" are set correctly.
+ */
+ public void recalculateHeightFactor() {
+ // Recalculate the new HeightFactor for the element;
+ // the highest bar will get "maxHeight" and other bar a fraction of it.
+ double diffToConsider = (maxDifferenceToAverage * maxDifferenceFactor * (double)barsWidth);
+
+ if ( heighestEventCount > (long)(diffToConsider * (double)averageNumberOfEvents) ) {
+ heightFactor = (double)maxHeight/( diffToConsider * (double)averageNumberOfEvents);
+ }
+ else {
+ heightFactor = (double)maxHeight/(double)heighestEventCount;
+ }
+ }
+
+ /**
+ * Recalculate the height of each bar in the elements table.<p>
+ * This assume "heightFactor" is already set correctly.<p>
+ *
+ * NOTE : if "maxHeight", "heighestEventCount" or "averageNumberOfEvents" changes,
+ * recalculateHeightFactor() should be recalled.
+ */
+ public void recalculateEventHeight() {
+ // Recalculate the height of the bars up to "readyUpToPosition"
+ for ( int x=0; x<readyUpToPosition; x++) {
+ elementTable[x].intervalHeight = (int)Math.ceil((double)elementTable[x].intervalNbEvents * heightFactor);
+ }
+ }
+
+ /**
+ * Recalculate the height of each bar in a certain interval of the elements table.<p>
+ * Unlike recalculateEventHeight(), this only recalculate for the given range, not the whole table.
+ *
+ */
+ public void recalculateEventHeightInInterval(int startPosition, int stopPosition) {
+ // Basic error checking on start : should be bigger than 0
+ if ( startPosition < 0 ) {
+ startPosition = 0;
+ }
+
+ // Basic error checking on start : should be smaller than length - 1
+ if ( stopPosition >= elementTable.length) {
+ stopPosition = (elementTable.length-1);
+ }
+
+ // Recalculate the height of the bars from startPosition to stopPosition
+ for ( int x=startPosition; x<stopPosition; x++) {
+ elementTable[x].intervalHeight = (int)Math.ceil((double)elementTable[x].intervalNbEvents * heightFactor);
+ }
+ }
+
+ /**
+ * Getter for the full size of the canvas.<p>
+ * This is used for the positionnal calculation so should be consistent with the real canvas size.
+ *
+ * @return Size of the canvas we currently use.
+ */
+ public int getCanvasWindowSize() {
+ return canvasWindowSize;
+ }
+
+ /**
+ * Set a new full size of the canvas.<p>
+ * This is used for the positionnal calculation so should be consistent with the real canvas size.
+ *
+ * @param newSize New canvas size;
+ */
+ public void setCanvasWindowSize(int newSize) {
+ canvasWindowSize = newSize;
+ }
+
+ /**
+ * Getter for the heighest event count recorded so far for an interval.<p>
+ *
+ * Note : Might be set externally (instead of calculated internally), so consistency with the content is not guarantee.
+ *
+ * @return Current heighestEventCount
+ */
+ public long getHeighestEventCount() {
+ return heighestEventCount;
+ }
+
+ /**
+ * Setter for setHeighestEventCount.<p>
+ *
+ * Note : this is used in some drawing calculation so make sure this number make sense.
+ * Note : you might want to call recalculateEventHeight() if you change this.
+ *
+ * @param newHeighestEventCount Heighest event count for a single interval.
+ */
+ public void setHeighestEventCount(long newHeighestEventCount) {
+ this.heighestEventCount = newHeighestEventCount;
+ }
+
+ /**
+ * Recalculate the heightest event count for a single time interval.<p>
+ *
+ * Note : This run over all the element so this is quite cpu intensive, use with care.
+ */
+ public void recalculateHeighestEventCount() {
+ // Go over the element up to readyUpToPosition (further position might not be ready)
+ for ( int x=0; x<readyUpToPosition; x++) {
+ if ( elementTable[x].intervalNbEvents > heighestEventCount ) {
+ this.heighestEventCount = elementTable[x].intervalNbEvents;
+ }
+ }
+ }
+
+ /**
+ * Getter for the max height of a bar in the content.<p>
+ *
+ * @return maximum height for a bar we currently use.
+ */
+ public int getMaxHeight() {
+ return maxHeight;
+ }
+
+ /**
+ * Setter for maxHeight.<p>
+ *
+ * Note : this is used in some drawing calculation so make sure this number make sense.
+ * Note : you might want to call recalculateEventHeight() if you change this.
+ *
+ * @param maxHeight The new maximum height for a bar to use.
+ */
+ public void setMaxHeight(int maxHeight) {
+ this.maxHeight = maxHeight;
+ }
+
+ /**
+ * Getter for the max difference to the average height a bar can have.<p>
+ * This determine at which point a bar too tall is "cut". Set a very large value (like 1000.0) to ignore.
+ *
+ * @return maximum difference to the average we currently use.
+ */
+ public double getMaxDifferenceToAverage() {
+ return maxDifferenceToAverage;
+ }
+
+ /**
+ * Setter for the max difference to the average height a bar can have.<p>
+ * This determine at which point a bar too tall is "cut". Set a very large value (like 1000.0) to ignore.
+ *
+ * Note : this is used in some drawing calculation so make sure this number make sense.
+ * Note : you might want to call recalculateEventHeight() if you change this.
+ *
+ * @param newDiffToAverage The new maximum difference to the average to use.
+ */
+ public void setMaxDifferenceToAverage(double newDiffToAverage) {
+ maxDifferenceToAverage = newDiffToAverage;
+ }
+
+
+ /**
+ * Getter for a factor applied to the max difference to the average height a bar can have.<p>
+ * This is muliplied to maxDifferenceToAverage. Set to value 1.0 to ignore.
+ *
+ * Note : this is useful if you concatenate some intervals to gether but want the average to be consistent
+ *
+ * @return maximum difference to the average we currently use.
+ */
+ public double getMaxDifferenceToAverageFactor() {
+ return maxDifferenceFactor;
+ }
+
+ /**
+ * Setter for a factor applied to the max difference to the average height a bar can have.<p>
+ *
+ * Note : this is used in some drawing calculation so make sure this number make sense.
+ * Note : you might want to call recalculateEventHeight() if you change this.
+ * Note : setting to 0 will cause bar to have a zero size... use 1.0 to desactivate
+ *
+ * @param newFactor The new factor to use.
+ */
+ public void setMaxDifferenceToAverageFactor(double newFactor) {
+ maxDifferenceFactor = newFactor;
+ }
+
+
+ /**
+ * Getter for the interval time of each interval.<p>
+ * This is usually "(EndTime - StartTime) / NbElement"
+ *
+ * @return Currently used interval time.
+ */
+ public long getElementsTimeInterval() {
+ return elementsTimeInterval;
+ }
+
+
+ /**
+ * Setter for the interval time of each interval.<p>
+ *
+ * Note : this is used in some drawing calculation so make sure this number make sense.
+ * Note : you migth want to call resetTable() to to fill the element's table again if you change this.
+ *
+ * @return New interval time.
+ */
+ public void setElementsTimeInterval(long newInterval) {
+ this.elementsTimeInterval = newInterval;
+ }
+
+
+ /**
+ * Calculate the correct time interval of each element from the given time.<p>
+ *
+ * @return The complete time interval
+ */
+ public void recalculateElementsTimeInterval(long startTime, long endTime) {
+ long tmpInterval = (long)Math.ceil((double)(endTime - startTime)/ (double)getNbElement());
+
+ if ( tmpInterval <= 0 ) {
+ tmpInterval = 1L;
+ }
+
+ this.elementsTimeInterval = tmpInterval;
+ }
+
+
+ /**
+ * Getter for readyUpToPosition.<p>
+ * This should tell to which point the content is filled, calculated and ready to use.
+ *
+ * @return Last position processed so far.
+ */
+ public int getReadyUpToPosition() {
+ return readyUpToPosition;
+ }
+
+ /**
+ * Setter for readyUpToPosition.<p>
+ * Set a new point (position) up to where the content is filled, calculated and ready to use.
+ *
+ * @param newReadyUpToPosition The new position to use.
+ */
+ public void setReadyUpToPosition(int newReadyUpToPosition) {
+ this.readyUpToPosition = newReadyUpToPosition;
+ }
+
+ /**
+ * Getter for the bar width.<p>
+ * This is needed by the paint listener usually.
+ *
+ * @return current bars width;
+ */
+ public int getBarsWidth() {
+ return barsWidth;
+ }
+
+ /**
+ * Setter for the bar width.<p>
+ * Setting this to 0 will hide all the bar in the histogram.
+ *
+ * @param newBarsWidth new bars width;
+ */
+ public void setBarsWidth(int newBarsWidth) {
+ this.barsWidth = newBarsWidth;
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * William Bourque - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.histogram;
+
+/**
+ * <b><u>HistogramElement</u></b>
+ * <p>
+ * This is used by the content to keep its data.
+ * It would be a struct if such a thing would exist in java.
+ * <p>
+ * Each "element" should represent a certain time interval
+ */
+public class HistogramElement {
+ public int index = 0; // Position of the element in the table (table index, obviously)
+ public long firstIntervalTimestamp = 0L; // The first timestamp recorded for this interval
+ public long intervalNbEvents = 0L; // Number of events recorded in this interval
+ public int intervalHeight = 0; // Height (in the canvas) of this element. Should be smaller than the canvas height.
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * William Bourque - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.histogram;
+
+import org.eclipse.linuxtools.lttng.event.LttngEvent;
+import org.eclipse.linuxtools.tmf.event.TmfEvent;
+import org.eclipse.linuxtools.tmf.event.TmfTimeRange;
+import org.eclipse.linuxtools.tmf.request.TmfEventRequest;
+
+/**
+ * <b><u>HistogramRequest</u></b>
+ * <p>
+ * Request class, to perform a request to TMF for the histograms.
+ * <p>
+ */
+public class HistogramRequest extends TmfEventRequest<LttngEvent> {
+ protected HistogramContent histogramContent = null;
+
+ protected int lastInterval = 0;
+ protected long lastRangeTime = 0L;
+ protected long nbEventsInInterval = 0L;
+
+ protected int nbIntervalNotEmpty = 1;
+ protected int nbEventRead = 0;
+
+ protected int lastDrawPosition = 0;
+
+ protected HistogramCanvas parentCanvas = null;
+
+ /**
+ * Constructor for HistogramRequest.<p>
+ * Prepare the request in TMF and reset the histogram content.
+ *
+ * @param range Range of the request.
+ * @param nbRequested Nb events requested. Can be "Infinity" for all.
+ * @param newParentCanvas HistogramCanvas related to the request.
+ * @param timeInterval Time interval to consider (i.e. : 1 interval is 1 bar in the histogram)
+ *
+ * @see org.eclipse.linuxtools.tmf.request.TmfEventRequest
+ */
+ public HistogramRequest(TmfTimeRange range, int nbRequested, HistogramCanvas newParentCanvas, long timeInterval) {
+ super((Class<LttngEvent>)LttngEvent.class, range, nbRequested, HistogramConstant.MAX_EVENTS_PER_READ);
+
+ // *** FIXME ***
+ // This does not work! The request won't be processed or the number of events returned is wrong!
+ // We cannot use this !
+ //super((Class<LttngEvent>)dataType, range);
+
+ parentCanvas = newParentCanvas;
+ histogramContent = parentCanvas.getHistogramContent();
+
+ // Reset the content of the HistogramContent... the given data better be valid or this will fail.
+ histogramContent.clearContentData();
+ histogramContent.resetTable(range.getStartTime().getValue(), range.getEndTime().getValue(), timeInterval);
+
+ lastRangeTime = range.getStartTime().getValue();
+
+ // Notify the UI even before the request started, so we set the timestamp already.
+ parentCanvas.notifyParentUpdatedInformationAsynchronously();
+ }
+
+ /**
+ * HandleData function : will be called by TMF each time a new event is receive for the request.<p>
+ * Calculation for the content is done here.
+ */
+ @Override
+ public void handleData() {
+ TmfEvent[] result = getData();
+ TmfEvent[] evt = new TmfEvent[1];
+
+ evt[0] = (result.length > 0) ? result[0] : null;
+
+ // *** FIXME ***
+ // *** EVIL BUG ***
+ // The request by timerange only does not work! (see constructor above)
+ // However, the request with number of events will loop until it reach its number or EOF
+ // We have to filter out ourself the extra useless events!
+ //
+ if (evt[0] != null) {
+
+ LttngEvent tmpEvent = (LttngEvent)evt[0];
+
+ // This check is linked to the evil fix mentionned above
+ if ( ( tmpEvent.getTimestamp().getValue() >= histogramContent.getStartTime() ) &&
+ ( tmpEvent.getTimestamp().getValue() <= histogramContent.getEndTime() ) )
+ {
+
+ // Distance (in time) between this event and the last one we read
+ long distance = ( tmpEvent.getTimestamp().getValue() - lastRangeTime );
+
+ // Check if we changed of interval (the distance is higher than the interval time)
+ if ( distance > histogramContent.getElementsTimeInterval() ) {
+
+ histogramContent.getElementByIndex(lastInterval).intervalNbEvents = nbEventsInInterval;
+ lastRangeTime = tmpEvent.getTimestamp().getValue();
+
+ // * NOTE *
+ // We can skip several interval at once, so we need to find what was our interval now
+ lastInterval = (int)((lastRangeTime - histogramContent.getStartTime()) / histogramContent.getElementsTimeInterval() );
+
+ // *** HACK ***
+ // Because of the threads, weird phenomenons seem to happen here, like a position after the
+ // element range because another request was issued.
+ // This enforce the position but may result in slightly inconsistent result (i.e. a weird misplaced bar sometime).
+ if ( lastInterval < 0 ) {
+ lastInterval = 0;
+ }
+ else if ( lastInterval >= histogramContent.getNbElement() ) {
+ lastInterval = (histogramContent.getNbElement()-1);
+ }
+
+ // * NOTE *
+ // We save the time we have here. This mean only the FIRST time read in an interval will be saved.
+ histogramContent.getElementByIndex(lastInterval).firstIntervalTimestamp = lastRangeTime;
+ histogramContent.setReadyUpToPosition(lastInterval);
+
+ nbIntervalNotEmpty++;
+ nbEventsInInterval = 1L;
+ }
+ // We are still in the same interval, just keep counting
+ else {
+ nbEventsInInterval++;
+ }
+
+ if ( nbEventsInInterval > histogramContent.getHeighestEventCount() ) {
+ histogramContent.setHeighestEventCount(nbEventsInInterval);
+ }
+ nbEventRead++;
+
+ // Call an asynchronous redraw every REDRAW_EVERY_NB_EVENTS events
+ // That way we don't need to wait until to end to have something on the screen
+ if ( nbEventRead % HistogramConstant.REDRAW_EVERY_NB_EVENTS == 0 ) {
+ redrawAsyncronously();
+ }
+ }
+ }
+ // We got a null event! This mean we reach the end of the request.
+ // Save the last interval we had, so we won't miss the very last events at the end.
+ else {
+ // Save the last events
+ histogramContent.getElementByIndex(lastInterval).intervalNbEvents = nbEventsInInterval;
+ // We reached the end of the request, so assume we fill up the content as well
+ histogramContent.setReadyUpToPosition(histogramContent.getNbElement());
+
+ // If the interval wasn't null, count this as a "non empty" interval
+ if (nbEventsInInterval > 0) {
+ nbIntervalNotEmpty++;
+ }
+ }
+ }
+
+ /**
+ * Function that is called when the request completed (successful or not).<p>
+ * Update information and redraw the screen.
+ */
+ @Override
+ public void handleCompleted() {
+ parentCanvas.notifyParentUpdatedInformationAsynchronously();
+ redrawAsyncronously();
+ }
+
+ /**
+ * Function that is called when the request completed successfully.<p>
+ */
+ @Override
+ public void handleSuccess() {
+ // Nothing different from completed.
+ }
+
+ /**
+ * Function that is called when the request completed in failure.<p>
+ */
+ @Override
+ public void handleFailure() {
+ // Nothing different from cancel.
+ }
+
+ /**
+ * Function that is called when the request was cancelled.<p>
+ * Redraw and set the requestCompleted flag to true;
+ */
+ @Override
+ public void handleCancel() {
+ redrawAsyncronously();
+ }
+
+ /**
+ * Update the HistogramContent with the latest information.<p>
+ * This will perform some calculation that might be a bit harsh so it should'nt be called too often.
+ */
+ public void updateEventsInfo() {
+ // *** Note ***
+ // The average number of event is calculated while skipping empty interval if asked
+ int averageNumberOfEvents = 0;
+ if ( HistogramConstant.SKIP_EMPTY_INTERVALS_WHEN_CALCULATING_AVERAGE ) {
+ averageNumberOfEvents = (int)Math.ceil((double)nbEventRead / (double)nbIntervalNotEmpty);
+ }
+ else {
+ averageNumberOfEvents = (int)Math.ceil((double)nbEventRead / (double)histogramContent.getNbElement());
+ }
+
+ histogramContent.setAverageNumberOfEvents(averageNumberOfEvents);
+
+ // It is possible that the height factor didn't change;
+ // If not, we only need to redraw the updated section, no the whole content
+ // Save the actual height, recalculate the height and check if there was any changes
+ double previousHeightFactor = histogramContent.getHeightFactor();
+ histogramContent.recalculateHeightFactor();
+ if ( histogramContent.getHeightFactor() != previousHeightFactor ) {
+ histogramContent.recalculateEventHeight();
+ }
+ else {
+ histogramContent.recalculateEventHeightInInterval(lastDrawPosition, histogramContent.getReadyUpToPosition());
+ }
+
+ lastDrawPosition = histogramContent.getReadyUpToPosition();
+ }
+
+ /**
+ * Perform an asynchonous redraw of the screen.
+ */
+ public void redrawAsyncronously() {
+ updateEventsInfo();
+ // Canvas redraw is already asynchronous
+ parentCanvas.redrawAsynchronously();
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * William Bourque - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.histogram;
+
+/**
+ * <b><u>HistogramSelectedWindow</u></b>
+ * <p>
+ * Selection window represent the selected section of the trace in the HistogramCanvas.
+ * <p>
+ * The selected window have 3 important attributes :
+ * <ul>
+ * <li>Its central position
+ * <li>Its time width
+ * <li>Its visibility (to determine if we should draw it or not)
+ * </ul>
+ * The dimension are then deduced from the first 2 values.
+ * This mean the window is always a perfectly symetrical rectangle.
+ */
+public class HistogramSelectedWindow {
+
+ protected int windowCenterPosition = 0;
+ protected long windowTimeWidth = 0L;
+
+ protected Boolean isSelectedWindowVisible = false;
+
+ protected HistogramContent histogramContent = null;
+
+ /**
+ * Default constructor for HistogramSelectedWindow.<p>
+ * Position and TimeWidth are both set to 0
+ *
+ * @param newTraceContent HistogramContent to read window's data from
+ */
+ public HistogramSelectedWindow(HistogramContent newTraceContent) {
+ histogramContent = newTraceContent;
+ }
+
+ /**
+ * Default constructor for HistogramSelectedWindow.<p>
+ * Position and TimeWidth are set to given value.
+ *
+ * @param newTraceContent HistogramContent to read window's data from
+ * @param centralPosition Central X Position of the selection window in the canvas (0 to canvasWidth)
+ * @param newWindowWidth Time width (size) of the window. (0 or greater)
+ */
+ public HistogramSelectedWindow(HistogramContent newTraceContent, int centralPosition, long newWindowWidth) {
+ histogramContent = newTraceContent;
+ windowCenterPosition = centralPosition;
+ windowTimeWidth = newWindowWidth;
+ }
+
+ /**
+ * Getter for the HistogramContent used by the window.<p>
+ *
+ * @return HistogramContent tied to this selection window.
+ */
+ public HistogramContent getTraceContent() {
+ return histogramContent;
+ }
+
+ /**
+ * Setter for the HistogramContent used by the window.<p>
+ * This need to be a valid, initialized HistogramContent;
+ * the data in the content are needed for positionning the window.
+ *
+ * @param newTraceContent A new HistogramContent
+ */
+ public void setTraceContent(HistogramContent newTraceContent) {
+ this.histogramContent = newTraceContent;
+ }
+
+
+ /**
+ * Getter for the window visibility.<p>
+ *
+ * @return true if the window is visible (will be draw), false otherwise
+ */
+ public boolean getSelectedWindowVisible() {
+ return isSelectedWindowVisible;
+ }
+
+ /**
+ * Setter for the window visibility.<p>
+ * True means the window will be draw, false that it will be hidden.
+ *
+ * @param newIsSelectedWindowVisible The visibility value
+ */
+ public void setSelectedWindowVisible(Boolean newIsSelectedWindowVisible) {
+ this.isSelectedWindowVisible = newIsSelectedWindowVisible;
+ }
+
+
+ /**
+ * Getter for the window time width (size)
+ *
+ * @return Window time width (size)
+ */
+ public long getWindowTimeWidth() {
+ return windowTimeWidth;
+ }
+
+ /**
+ * Setter for the window time width (size).<p>
+ * Width need to be a time (in nanoseconds) that's coherent to the data we are looking at.
+ *
+ * @param newWindowTimeWidth The new time width
+ */
+ public void setWindowTimeWidth(long newWindowTimeWidth) {
+ this.windowTimeWidth = newWindowTimeWidth;
+ }
+
+
+ /**
+ * Getter for the central position of the window.<p>
+ *
+ * @return Center X position of this window on the canvas.
+ */
+ public int getWindowXPositionCenter() {
+ return windowCenterPosition;
+ }
+
+ /**
+ * Setter for the central position of the window.<p>
+ * The new position need to be valid on the canvas (0 to canvasWidth).
+ *
+ * @param newPosCenter The new central position.
+ */
+ public void setWindowXPositionCenter(int newPosCenter) {
+ this.windowCenterPosition = newPosCenter;
+ }
+
+ /**
+ * Getter for the left border of the window.<p>
+ * Compute the position from the HistogramContent data; may return 0 if the content data are wrong.
+ *
+ * @return The left position of the window, or 0 if it cannot compute it.
+ */
+ public int getWindowXPositionLeft() {
+
+ // If the timewidth is too small, we would pick the same position as the center one.
+ // To avoid this, we take a "full interval" when the window size is too small
+ if ( windowTimeWidth < histogramContent.getElementsTimeInterval() ) {
+ // Use intervalTime and not intervalTime/2 to make sure we step into the next interval
+ // Otherwise, if we are in the beginning of an interval, adding IntervalTime/2 could lead us into the same one
+ // The rounding operation will then return a correct position
+ return histogramContent.getXPositionByPositionAndTimeInterval(windowCenterPosition, -(histogramContent.getElementsTimeInterval() ) );
+ }
+ else {
+ return histogramContent.getXPositionByPositionAndTimeInterval(windowCenterPosition, -(windowTimeWidth / 2) );
+ }
+ }
+
+ /**
+ * Getter for the right border of the window.<p>
+ * Compute the position from the HistogramContent data; may return 0 if the content data are wrong.
+ *
+ * @return The right position of the window, or 0 if it cannot compute it.
+ */
+ public int getWindowXPositionRight() {
+ // If the timewidth is too small, we would pick the same position as the center one.
+ // To avoid this, we take a "full interval" when the window size is too small
+ if ( windowTimeWidth < histogramContent.getElementsTimeInterval() ) {
+ // Use intervalTime and not intervalTime/2 to make sure we step into the next interval
+ // Otherwise, if we are in the beginning of an interval, adding IntervalTime/2 could lead us into the same one
+ // The rounding operation will then return a correct position
+ return histogramContent.getXPositionByPositionAndTimeInterval(windowCenterPosition, +(histogramContent.getElementsTimeInterval() ) );
+ }
+ else {
+ return histogramContent.getXPositionByPositionAndTimeInterval(windowCenterPosition, +(windowTimeWidth / 2) );
+ }
+
+ }
+
+ /**
+ * Getter for the timestamp of left border of the window.<p>
+ * Compute the timestamp from the HistogramContent data; may return 0 if the content data are wrong.
+ *
+ * @return The left timestamp of the window, or 0 if it cannot compute it.
+ */
+ public long getTimestampOfLeftPosition() {
+ return histogramContent.getClosestElementFromXPosition( getWindowXPositionLeft() ).firstIntervalTimestamp;
+ }
+
+ /**
+ * Getter for the timestamp of the center of the window.<p>
+ * Compute the timestamp from the HistogramContent data; may return 0 if the content data are wrong.
+ *
+ * @return The center timestamp of the window, or 0 if it cannot compute it.
+ */
+ public long getTimestampOfCenterPosition() {
+ return histogramContent.getClosestElementFromXPosition( getWindowXPositionCenter() ).firstIntervalTimestamp;
+ }
+
+ /**
+ * Getter for the timestamp of right border of the window.<p>
+ * Compute the timestamp from the HistogramContent data; may return 0 if the content data are wrong.
+ *
+ * @return The right timestamp of the window, or 0 if it cannot compute it.
+ */
+ public long getTimestampOfRightPosition() {
+ return histogramContent.getClosestElementFromXPosition( getWindowXPositionRight() ).firstIntervalTimestamp;
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * William Bourque - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.histogram;
+
+import org.eclipse.linuxtools.lttng.event.LttngEvent;
+import org.eclipse.linuxtools.lttng.event.LttngTimestamp;
+import org.eclipse.linuxtools.tmf.event.TmfTimeRange;
+import org.eclipse.linuxtools.tmf.event.TmfTimestamp;
+import org.eclipse.linuxtools.tmf.experiment.TmfExperiment;
+import org.eclipse.linuxtools.tmf.signal.TmfExperimentSelectedSignal;
+import org.eclipse.linuxtools.tmf.signal.TmfExperimentUpdatedSignal;
+import org.eclipse.linuxtools.tmf.signal.TmfRangeSynchSignal;
+import org.eclipse.linuxtools.tmf.signal.TmfSignalHandler;
+import org.eclipse.linuxtools.tmf.signal.TmfTimeSynchSignal;
+import org.eclipse.linuxtools.tmf.ui.views.TmfView;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * <b><u>HistogramView</u></b>
+ * <p>
+ * View that contain an visual approach to the window that control the request.
+ * This is intended to replace the TimeFrameView
+ * <p>
+ * This view is composed of 2 canvas, one for the whole experiment and one for the selectionned window in the experiment.
+ * It also contain a certain number of controls to print or change informations about the experiment.
+ */
+public class HistogramView extends TmfView implements ControlListener {
+
+ // *** TODO ***
+ // Here is what's left to do in this view
+ //
+ // 1- Make sure the interval time is small enought on very big trace (bug 311930)
+ // The interval time of the content is dynamically assigned from the screen width and trace duration.
+ // However, on very big trace (more than 1 hour), we could end up with time interval that are > 1 seconds,
+ // which is not very precise.
+ // An algorithm need to be implemented to make sure we "increase" the number of interval in the content if
+ // their precision is getting too bad.
+ //
+ // 2- Make sure all control are thread safe (bug 309348)
+ // Right now, all the basic controls (i.e. Text and Label) are sensible to "Thread Access Exception" if
+ // updated from different threads; we need to carefully decide when/where to redraw them.
+ // This is a real problem since there is a lot of thread going on in this view.
+ // All basic control should be subclassed to offer "Asynchronous" functions.
+ //
+ // 3- Implement a "preferences view" for the HistogramView (bug 311935)
+ // There is a lot of ajustable preferences in the view, however there is no way to ajust them right now
+ // at run time. There should be a view of some kind of "menu" to allow the user to change them while executing.
+ // Most of the pertinent values are in HistogramConstant.java or in this file.
+
+ public static final String ID = "org.eclipse.linuxtools.lttng.ui.views.histogram";
+
+ // "Minimum" screen width size. On smaller screen, we will apply several space saving technique
+ private static final int SCREEN_SMALL_IF_SMALLER_THAN = 1600;
+
+ // Size of the "fulll trace" canvas
+ private static final int FULL_TRACE_CANVAS_HEIGHT = 25;
+ private static final int FULL_TRACE_BAR_WIDTH = 1;
+ private static final double FULL_TRACE_DIFFERENCE_TO_AVERAGE = 1.5;
+
+ // Size of the "Selected Window" canvas
+ private static final int SELECTED_WINDOW_CANVAS_WIDTH = 300;
+ private static final int SMALL_SELECTED_WINDOW_CANVAS_WIDTH = 200;
+ private static final int SELECTED_WINDOW_CANVAS_HEIGHT = 60;
+ private static final int SELECTED_WINDOW_BAR_WIDTH = 1;
+ private static final double SELECTED_WINDOW_DIFFERENCE_TO_AVERAGE = 10.0;
+
+ // For the two "events" label (Max and min number of events in the selection), we force a width
+ // This will prevent the control from moving horizontally if the number of events in the selection varies
+ private static final int NB_EVENTS_FIXED_WIDTH = 50;
+
+
+ // The "small font" height used to display time will be "default font" minus this constant
+ private static final int SMALL_FONT_MODIFIER = 2;
+ private static final int VERY_SMALL_FONT_MODIFIER = 4;
+
+ // *** TODO ***
+ // This need to be changed as soon the framework implement a "window"
+ private static long DEFAULT_WINDOW_SIZE = (1L * 100 * 1000 * 1000); // 0.1sec
+
+ // The last experiment received/used by the view
+ private TmfExperiment<LttngEvent> lastUsedExperiment = null;
+
+ // Parent of the view
+ private Composite parent = null;
+
+ // Request and canvas for the "full trace" part
+ private HistogramRequest dataBackgroundFullRequest = null;
+ private ParentHistogramCanvas fullExperimentCanvas = null;
+
+ // Request and canvas for the "selected window"
+ private HistogramRequest selectedWindowRequest = null;
+ private ChildrenHistogramCanvas selectedWindowCanvas = null;
+
+ // Content of the timeTextGroup
+ // Since the user can modify them with erroneous value,
+ // we will keep track of the value internally
+ private long selectedWindowTime = 0L;
+ private long selectedWindowTimerange = 0L;
+ private long currentEventTime = 0L;
+
+ // *** All the UI control below
+ //
+ // NOTE : All textboxes will be READ_ONLY.
+ // So the user will be able to select/copy the value in them but not to change it
+ private Text txtExperimentStartTime = null;
+ private Text txtExperimentStopTime = null;
+
+ private Text txtWindowStartTime = null;
+ private Text txtWindowStopTime = null;
+ private Text txtWindowMaxNbEvents = null;
+ private Text txtWindowMinNbEvents = null;
+
+ private static final String WINDOW_TIMERANGE_LABEL_TEXT = "Window Timerange ";
+ private static final String WINDOW_CURRENT_TIME_LABEL_TEXT = "Cursor Centered on ";
+ private static final String EVENT_CURRENT_TIME_LABEL_TEXT = "Current Event Time ";
+ private TimeTextGroup ntgTimeRangeWindow = null;
+ private TimeTextGroup ntgCurrentWindowTime = null;
+ private TimeTextGroup ntgCurrentEventTime = null;
+
+ /**
+ * Default contructor of the view
+ */
+ public HistogramView() {
+ super(ID);
+ }
+
+ /**
+ * Create the UI controls of this view
+ *
+ * @param parent The composite parent of this view
+ */
+ @Override
+ public void createPartControl(Composite newParent) {
+ // Save the parent
+ parent = newParent;
+
+ // Default font
+ Font font = parent.getFont();
+ FontData tmpFontData = font.getFontData()[0];
+
+
+ Font smallFont = null;
+ int nbEventWidth = -1;
+ int selectedCanvasWidth = -1;
+ boolean doesTimeTextGroupNeedAdjustment = false;
+
+ // Calculate if we need "small screen" fixes
+ if ( parent.getDisplay().getBounds().width < SCREEN_SMALL_IF_SMALLER_THAN ) {
+ // A lot smaller font for timstampe
+ smallFont = new Font(font.getDevice(), tmpFontData.getName(), tmpFontData.getHeight() - VERY_SMALL_FONT_MODIFIER, tmpFontData.getStyle());
+
+ // Smaller selection window canvas
+ selectedCanvasWidth = SMALL_SELECTED_WINDOW_CANVAS_WIDTH;
+ // Smaller event number text field
+ nbEventWidth = NB_EVENTS_FIXED_WIDTH/2;
+
+ // Tell the text group to ajust
+ doesTimeTextGroupNeedAdjustment = true;
+ }
+ else {
+ // Slightly smaller font for timestamp
+ smallFont = new Font(font.getDevice(), tmpFontData.getName(), tmpFontData.getHeight() - SMALL_FONT_MODIFIER, tmpFontData.getStyle());
+ // Usual size for selected window and event number text field
+ nbEventWidth = NB_EVENTS_FIXED_WIDTH;
+ selectedCanvasWidth = SELECTED_WINDOW_CANVAS_WIDTH;
+ // No ajustement needed by the text group
+ doesTimeTextGroupNeedAdjustment = false;
+ }
+
+ // Layout for the whole view, other elements will be in a child composite of this one
+ // Contains :
+ // Composite layoutSelectionWindow
+ // Composite layoutTimesSpinner
+ // Composite layoutExperimentHistogram
+ Composite layoutFullView = new Composite(parent, SWT.NONE);
+ GridLayout gridFullView = new GridLayout();
+ gridFullView.numColumns = 2;
+ gridFullView.horizontalSpacing = 0;
+ gridFullView.verticalSpacing = 0;
+ gridFullView.marginHeight = 0;
+ gridFullView.marginWidth = 0;
+ layoutFullView.setLayout(gridFullView);
+
+
+ // Layout that contain the SelectionWindow
+ // Contains :
+ // Label lblWindowStartTime
+ // Label lblWindowStopTime
+ // Label lblWindowMaxNbEvents
+ // Label lblWindowMinNbEvents
+ // ChildrenHistogramCanvas selectedWindowCanvas
+ Composite layoutSelectionWindow = new Composite(layoutFullView, SWT.NONE);
+ GridLayout gridSelectionWindow = new GridLayout();
+ gridSelectionWindow.numColumns = 3;
+ gridSelectionWindow.marginHeight = 0;
+ gridSelectionWindow.marginWidth = 0;
+ gridSelectionWindow.horizontalSpacing = 0;
+ gridSelectionWindow.verticalSpacing = 0;
+ layoutSelectionWindow.setLayout(gridSelectionWindow);
+ GridData gridDataSelectionWindow = new GridData(SWT.FILL, SWT.TOP, false, false, 1, 1);
+ layoutSelectionWindow.setLayoutData(gridDataSelectionWindow);
+
+
+ // Layout that contain the time spinner
+ // Contains :
+ // NanosecTextGroup spTimeRangeWindow
+ // NanosecTextGroup spCurrentWindowTime
+ // NanosecTextGroup spCurrentEventTime
+ Composite layoutTimesSpinner = new Composite(layoutFullView, SWT.NONE);
+ GridLayout gridTimesSpinner = new GridLayout();
+ gridTimesSpinner.numColumns = 3;
+ gridTimesSpinner.marginHeight = 0;
+ gridTimesSpinner.marginWidth = 0;
+ gridTimesSpinner.horizontalSpacing = 0;
+ gridTimesSpinner.verticalSpacing = 0;
+ layoutTimesSpinner.setLayout(gridTimesSpinner);
+ GridData gridDataTimesSpinner = new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1);
+ layoutTimesSpinner.setLayoutData(gridDataTimesSpinner);
+
+
+ // Layout that contain the complete experiment histogram and related controls.
+ // Contains :
+ // Label lblExperimentStartTime
+ // Label lblExperimentStopTime
+ // ParentHistogramCanvas fullTraceCanvas
+ Composite layoutExperimentHistogram = new Composite(layoutFullView, SWT.NONE);
+ GridLayout gridExperimentHistogram = new GridLayout();
+ gridExperimentHistogram.numColumns = 2;
+ gridExperimentHistogram.marginHeight = 0;
+ gridExperimentHistogram.marginWidth = 0;
+ gridExperimentHistogram.horizontalSpacing = 0;
+ gridExperimentHistogram.verticalSpacing = 0;
+ layoutExperimentHistogram.setLayout(gridExperimentHistogram);
+ GridData gridDataExperimentHistogram = new GridData(SWT.FILL, SWT.TOP, true, false, 2, 1);
+ layoutExperimentHistogram.setLayoutData(gridDataExperimentHistogram);
+
+
+
+ // *** Everything related to the selection window is below
+ GridData gridDataSelectionWindowCanvas = new GridData(SWT.LEFT, SWT.TOP, true, false, 2, 2);
+ gridDataSelectionWindowCanvas.heightHint = SELECTED_WINDOW_CANVAS_HEIGHT;
+ gridDataSelectionWindowCanvas.minimumHeight = SELECTED_WINDOW_CANVAS_HEIGHT;
+ gridDataSelectionWindowCanvas.widthHint = selectedCanvasWidth;
+ gridDataSelectionWindowCanvas.minimumWidth = selectedCanvasWidth;
+ selectedWindowCanvas = new ChildrenHistogramCanvas(this, layoutSelectionWindow, SWT.BORDER);
+ selectedWindowCanvas.setLayoutData(gridDataSelectionWindowCanvas);
+
+ GridData gridDataWindowMaxEvents = new GridData(SWT.FILL, SWT.TOP, true, false, 1, 1);
+ // Force a width, to avoid the control to enlarge if the number of events change
+ gridDataWindowMaxEvents.minimumWidth = nbEventWidth;
+ txtWindowMaxNbEvents = new Text(layoutSelectionWindow, SWT.READ_ONLY);
+ txtWindowMaxNbEvents.setFont(smallFont);
+ txtWindowMaxNbEvents.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_TITLE_INACTIVE_BACKGROUND));
+ txtWindowMaxNbEvents.setEditable(false);
+ txtWindowMaxNbEvents.setText("");
+ txtWindowMaxNbEvents.setLayoutData(gridDataWindowMaxEvents);
+
+ GridData gridDataWindowMinEvents = new GridData(SWT.LEFT, SWT.BOTTOM, true, false, 1, 1);
+ // Force a width, to avoid the control to enlarge if the number of events change
+ gridDataWindowMinEvents.minimumWidth = nbEventWidth;
+ txtWindowMinNbEvents = new Text(layoutSelectionWindow, SWT.READ_ONLY);
+ txtWindowMinNbEvents.setFont(smallFont);
+ txtWindowMinNbEvents.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_TITLE_INACTIVE_BACKGROUND));
+ txtWindowMinNbEvents.setEditable(false);
+ txtWindowMinNbEvents.setText("");
+ txtWindowMinNbEvents.setLayoutData(gridDataWindowMinEvents);
+
+ GridData gridDataWindowStart = new GridData(SWT.LEFT, SWT.TOP, false, false, 1, 1);
+ txtWindowStartTime = new Text(layoutSelectionWindow, SWT.READ_ONLY);
+ txtWindowStartTime.setFont(smallFont);
+ txtWindowStartTime.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_TITLE_INACTIVE_BACKGROUND));
+ txtWindowStartTime.setEditable(false);
+ txtWindowStartTime.setText("");
+ txtWindowStartTime.setLayoutData(gridDataWindowStart);
+
+ GridData gridDataWindowStop = new GridData(SWT.RIGHT, SWT.TOP, false, false, 1, 1);
+ txtWindowStopTime = new Text(layoutSelectionWindow, SWT.READ_ONLY);
+ txtWindowStopTime.setFont(smallFont);
+ txtWindowStopTime.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_TITLE_INACTIVE_BACKGROUND));
+ txtWindowStopTime.setEditable(false);
+ txtWindowStopTime.setText("");
+ txtWindowStopTime.setLayoutData(gridDataWindowStop);
+
+ GridData gridDataSpacer = new GridData(SWT.FILL, SWT.TOP, true, true, 1, 1);
+ gridDataSpacer.minimumWidth = nbEventWidth;
+ // *** HACK ***
+ // To align properly AND to make sure the canvas size is fixed, we NEED to make sure all "section" of the
+ // gridlayout are taken (and if possible of a fixed size).
+ // However, SWT is VERY VERY DUMB and won't consider griddata that contain no control.
+ // Since there will be missing a section, the SelectedWindowCanvas + NbEventsText will take 3 spaces, but
+ // startTimeText + stopTimeText will take only 2 (as if empty the other griddata of 1 will get ignored).
+ // StopTime will then take over the missing space; I want to align "stopTime" right on the end of canvas, so
+ // the added space to stop time would make it being aligned improperly
+ // So I NEED the empty griddata to be considered!
+ // Visually :
+ // |---------------|---------------|-----------|
+ // |SelectionCanvas SelectionCanvas|NbEventText|
+ // |SelectionCanvas SelectionCanvas|NbEventText|
+ // |---------------|---------------|-----------|
+ // |StartTime | StopTime| ??? |
+ // |---------------|---------------|-----------|
+ //
+ // So since SWT will only consider griddata with control,
+ // I need to create a totally useless control in the ??? section.
+ // That's ugly, useless and it is generally a bad practice.
+ //
+ // *** SUB-HACK ***
+ // Other interesting fact about SWT : the way it draws (Fill/Expand control in grid) will change if
+ // the control is a Text or a Label.
+ // A Label here will be "pushed" by startTime/stopTime Text and won't fill the full space as NbEventText.
+ // A Text here will NOT be "pushed" and would give a nice visual output.
+ // (NB : No, I am NOT kidding, try it for yourself!)
+ //
+ // Soooooo I guess I will use a Text here. Way to go SWT!
+ // Downside is that disabled textbox has a slightly different color (even if you force it yourself) so if I want
+ // to make the text "invisible", I have to keep it enabled (but read only), so it can be clicked on.
+ //
+ // Label uselessControlToByPassSWTStupidBug = new Label(layoutSelectionWindow, SWT.BORDER); // WON'T align correctly!!!
+ Text uselessControlToByPassSWTStupidBug = new Text(layoutSelectionWindow, SWT.READ_ONLY); // WILL align correctly!!!
+ uselessControlToByPassSWTStupidBug.setEditable(false);
+ uselessControlToByPassSWTStupidBug.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_TITLE_INACTIVE_BACKGROUND));
+ uselessControlToByPassSWTStupidBug.setLayoutData(gridDataSpacer);
+
+
+
+ // *** Everything related to the time text group is below
+ GridData gridDataCurrentEvent = new GridData(SWT.CENTER, SWT.CENTER, true, true, 1, 2);
+ ntgCurrentEventTime = new TimeTextGroup(this, layoutTimesSpinner, SWT.BORDER, SWT.BORDER, EVENT_CURRENT_TIME_LABEL_TEXT, HistogramConstant.formatNanoSecondsTime( 0L ), doesTimeTextGroupNeedAdjustment);
+ ntgCurrentEventTime.setLayoutData(gridDataCurrentEvent);
+
+ GridData gridDataTimeRange = new GridData(SWT.CENTER, SWT.CENTER, true, true, 1, 2);
+ ntgTimeRangeWindow = new TimeTextGroup(this, layoutTimesSpinner, SWT.BORDER, SWT.BORDER, WINDOW_TIMERANGE_LABEL_TEXT, HistogramConstant.formatNanoSecondsTime( 0L ), doesTimeTextGroupNeedAdjustment);
+ ntgTimeRangeWindow.setLayoutData(gridDataTimeRange);
+
+ GridData gridDataCurrentWindow = new GridData(SWT.CENTER, SWT.CENTER, true, true, 1, 2);
+ ntgCurrentWindowTime = new TimeTextGroup(this, layoutTimesSpinner, SWT.BORDER, SWT.BORDER, WINDOW_CURRENT_TIME_LABEL_TEXT, HistogramConstant.formatNanoSecondsTime( 0L ), doesTimeTextGroupNeedAdjustment);
+ ntgCurrentWindowTime.setLayoutData(gridDataCurrentWindow);
+
+
+
+ // *** Everything related to the experiment canvas is below
+ GridData gridDataExperimentCanvas = new GridData(SWT.FILL, SWT.TOP, true, false, 2, 1);
+ gridDataExperimentCanvas.heightHint = FULL_TRACE_CANVAS_HEIGHT;
+ gridDataExperimentCanvas.minimumHeight = FULL_TRACE_CANVAS_HEIGHT;
+ fullExperimentCanvas = new ParentHistogramCanvas(this, layoutExperimentHistogram, SWT.BORDER);
+ fullExperimentCanvas.setLayoutData(gridDataExperimentCanvas);
+
+ GridData gridDataExperimentStart = new GridData(SWT.LEFT, SWT.TOP, false, false, 1, 1);
+ txtExperimentStartTime = new Text(layoutExperimentHistogram, SWT.READ_ONLY);
+ txtExperimentStartTime.setFont(smallFont);
+ txtExperimentStartTime.setText("");
+ txtExperimentStartTime.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_TITLE_INACTIVE_BACKGROUND));
+ txtExperimentStartTime.setEditable(false);
+ txtExperimentStartTime.setLayoutData(gridDataExperimentStart);
+
+ GridData gridDataExperimentStop = new GridData(SWT.RIGHT, SWT.TOP, false, false, 1, 1);
+ txtExperimentStopTime = new Text(layoutExperimentHistogram, SWT.READ_ONLY);
+ txtExperimentStopTime.setFont(smallFont);
+ txtExperimentStopTime.setText("");
+ txtExperimentStopTime.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_TITLE_INACTIVE_BACKGROUND));
+ txtExperimentStopTime.setEditable(false);
+ txtExperimentStopTime.setLayoutData(gridDataExperimentStop);
+ }
+
+ // *** FIXME ***
+ // This is mainly used because of a because in the "experimentSelected()" notification, we shouldn't need this
+ /**
+ * Method called when the view receive the focus.<p>
+ * If ExperimentSelected didn't send us a request yet, get the current Experiment and fire requests
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public void setFocus() {
+ // WARNING : This does not seem to be thread safe
+ TmfExperiment<LttngEvent> tmpExperiment = (TmfExperiment<LttngEvent>)TmfExperiment.getCurrentExperiment();
+
+ if ( (dataBackgroundFullRequest == null) && (tmpExperiment != null) ) {
+ createCanvasAndRequests(tmpExperiment);
+ }
+
+ // Call a redraw for everything
+ parent.redraw();
+ }
+
+ /**
+ * Method called when the user select (double-click on) an experiment.<p>
+ * We will create the needed canvas and fire the requests.
+ *
+ * @param signal Signal received from the framework. Contain the experiment.
+ */
+ @SuppressWarnings("unchecked")
+ @TmfSignalHandler
+ public void experimentSelected(TmfExperimentSelectedSignal<LttngEvent> signal) {
+ TmfExperiment<LttngEvent> tmpExperiment = (TmfExperiment<LttngEvent>)signal.getExperiment();
+ createCanvasAndRequests(tmpExperiment);
+ }
+
+ // *** VERIFY ***
+ // Not sure what this should do since I don't know when it will be called
+ // Let's do the same thing as experimentSelected for now
+ //
+ /**
+ * Method called when an experiment is updated (??).<p>
+ * ...for now, do nothing, as udating an experiment running in the background might cause crash
+ *
+ * @param signal Signal received from the framework. Contain the experiment.
+ */
+// @SuppressWarnings("unchecked")
+ @TmfSignalHandler
+ public void experimentUpdated(TmfExperimentUpdatedSignal signal) {
+//
+// TmfExperiment<LttngEvent> tmpExperiment = (TmfExperiment<LttngEvent>)signal.getExperiment();
+//
+// // Make sure the UI object are sane
+// resetControlsContent();
+//
+// // Redraw the canvas right away to have something "clean" as soon as we can
+// fullExperimentCanvas.redraw();
+// selectedWindowCanvas.redraw();
+//
+// // Recreate the request
+// createCanvasAndRequests(tmpExperiment);
+ }
+
+ /**
+ * Method called when synchonization is active and that the user select an event.<p>
+ * We update the current event timeTextGroup and move the selected window if needed.
+ *
+ * @param signal Signal received from the framework. Contain the event.
+ */
+ @TmfSignalHandler
+ public void currentTimeUpdated(TmfTimeSynchSignal signal) {
+ // In case we received our own signal
+ if (signal.getSource() != this) {
+ TmfTimestamp currentTime = signal.getCurrentTime();
+
+ // Update the current event controls
+ currentEventTime = currentTime.getValue();
+ updateSelectedEventTime();
+
+ // If the given event is outside the selection window, recenter the window
+ if ( isGivenTimestampInSelectedWindow( currentEventTime ) == false) {
+ fullExperimentCanvas.setWindowCenterPosition( fullExperimentCanvas.getHistogramContent().getClosestXPositionFromTimestamp(currentEventTime) );
+ // Notify control that the window changed
+ windowChangedNotification();
+ // Send a broadcast to the framework about the window change
+ sendTmfRangeSynchSignalBroadcast();
+ }
+ }
+ }
+
+ @TmfSignalHandler
+ public void synchToTimeRange(TmfRangeSynchSignal signal) {
+ if ( (signal != null) && (signal.getSource() != this) ) {
+ if ( lastUsedExperiment != null ) {
+ long currentTime = signal.getCurrentTime().getValue();
+ long windowStart = signal.getCurrentRange().getStartTime().getValue();
+ long windowEnd = signal.getCurrentRange().getEndTime().getValue();
+ long windowTimeWidth = (windowEnd - windowStart);
+
+ // Recenter the window
+ fullExperimentCanvas.setWindowCenterPosition( fullExperimentCanvas.getHistogramContent().getClosestXPositionFromTimestamp(windowStart + (windowTimeWidth/2)) );
+ fullExperimentCanvas.setSelectedWindowSize(windowTimeWidth);
+
+ // *** HACK ***
+ // Views could send us incorrect current event value (event outside the current window)
+ // Here we make sure the value is sane, otherwise, we force it as the left border of the window
+ if ( isGivenTimestampInSelectedWindow( currentTime ) == false ) {
+ currentTime = windowStart;
+ }
+ currentEventTime = currentTime;
+
+ // Notify control that the window changed
+ windowChangedNotification();
+
+ // Make sure we redraw the change
+ fullExperimentCanvas.redraw();
+ }
+ }
+ }
+
+
+ /*
+ * Create the canvas needed and issue the requests
+ *
+ * @param newExperiment Experiment we will use for the request
+ */
+ private void createCanvasAndRequests(TmfExperiment<LttngEvent> newExperiment) {
+ // Save the experiment we are about to use
+ lastUsedExperiment = newExperiment;
+
+ // Create a copy of the trace that will be use only by the full experiment request
+ TmfExperiment<LttngEvent> experimentCopy = newExperiment.createTraceCopy();
+
+ // Create the content for the full experiment.
+ // This NEED to be created first, as we use it in the selectedWindowCanvas
+ fullExperimentCanvas.createNewHistogramContent(fullExperimentCanvas.getSize().x, FULL_TRACE_BAR_WIDTH, FULL_TRACE_CANVAS_HEIGHT, FULL_TRACE_DIFFERENCE_TO_AVERAGE);
+ fullExperimentCanvas.createNewSelectedWindow(DEFAULT_WINDOW_SIZE);
+ currentEventTime = newExperiment.getStartTime().getValue();
+ // Set the window of the fullTrace canvas visible.
+ fullExperimentCanvas.getCurrentWindow().setSelectedWindowVisible(true);
+ fullExperimentCanvas.getHistogramContent().resetTable(newExperiment.getStartTime().getValue(), newExperiment.getEndTime().getValue());
+
+ // Create the content for the selected window.
+ selectedWindowCanvas.createNewHistogramContent(selectedWindowCanvas.getSize().x ,SELECTED_WINDOW_BAR_WIDTH, SELECTED_WINDOW_CANVAS_HEIGHT, SELECTED_WINDOW_DIFFERENCE_TO_AVERAGE);
+ selectedWindowCanvas.getHistogramContent().resetTable(fullExperimentCanvas.getCurrentWindow().getTimestampOfLeftPosition(), fullExperimentCanvas.getCurrentWindow().getTimestampOfRightPosition());
+
+ // Make sure the UI object are sane
+ resetControlsContent();
+
+ // Redraw the canvas right away to have something "clean" as soon as we can
+ if ( dataBackgroundFullRequest != null ) {
+ fullExperimentCanvas.redraw();
+ selectedWindowCanvas.redraw();
+ }
+ // Nullify the (possible) old request to be sure we start we something clean
+ // Note : this is very important for the order of the request below,
+ // see "TODO" in performSelectedWindowEventsRequest
+ dataBackgroundFullRequest = null;
+ selectedWindowRequest = null;
+
+ // Perform both request.
+ // Order is important here, the small/synchronous request for the selection window should go first
+ performSelectedWindowEventsRequest(newExperiment);
+ performAllTraceEventsRequest(experimentCopy);
+ }
+
+ /**
+ * Perform a new request for the Selection window.<p>
+ * This assume the full experiment canvas has correct information about the selected window;
+ * we need the fullExperimentCanvas' HistogramContent to be created and a selection window to be set.
+ *
+ * @param experiment The experiment we will select from
+ */
+ public void performSelectedWindowEventsRequest(TmfExperiment<LttngEvent> experiment) {
+
+ HistogramSelectedWindow curSelectedWindow = fullExperimentCanvas.getCurrentWindow();
+
+ // If no selection window exists, we will try to cerate one;
+ // however this will most likely fail as the content is probably not created either
+ if ( curSelectedWindow == null ) {
+ fullExperimentCanvas.createNewSelectedWindow( DEFAULT_WINDOW_SIZE );
+ curSelectedWindow = fullExperimentCanvas.getCurrentWindow();
+ }
+
+ // The request will go from the Left timestamp of the window to the Right timestamp
+ // This assume that out-of-bound value are handled by the SelectionWindow itself
+ LttngTimestamp ts1 = new LttngTimestamp( curSelectedWindow.getTimestampOfLeftPosition() );
+ LttngTimestamp ts2 = new LttngTimestamp( curSelectedWindow.getTimestampOfRightPosition() );
+ TmfTimeRange tmpRange = new TmfTimeRange(ts1, ts2);
+
+ // Set a (dynamic) time interval
+ long intervalTime = ( (ts2.getValue() - ts1.getValue()) / selectedWindowCanvas.getHistogramContent().getNbElement() );
+
+ selectedWindowRequest = performRequest(experiment, selectedWindowCanvas, tmpRange, intervalTime);
+ selectedWindowCanvas.redrawAsynchronously();
+ }
+
+ /**
+ * Perform a new request for the full experiment.<p>
+ * NOTE : this is very long, we need to implement a way to run this in parallel (see TODO)
+ *
+ * @param experiment The experiment we will select from
+ */
+ public void performAllTraceEventsRequest(TmfExperiment<LttngEvent> experiment) {
+ // Create a new time range from "start" to "end"
+ // That way, we will get "everything" in the trace
+ LttngTimestamp ts1 = new LttngTimestamp( experiment.getStartTime() );
+ LttngTimestamp ts2 = new LttngTimestamp( experiment.getEndTime() );
+ TmfTimeRange tmpRange = new TmfTimeRange(ts1, ts2);
+
+ // Set a (dynamic) time interval
+ long intervalTime = ( (ts2.getValue() - ts1.getValue()) / fullExperimentCanvas.getHistogramContent().getNbElement() );
+
+ // *** VERIFY ***
+ // This would enable "fixed interval" instead of dynamic one.
+ // ... we don't need it, do we?
+ //
+ // long intervalTime = ((long)(0.001 * (double)1000000000));
+
+ // *** TODO ***
+ // It would be interesting if there was a way to tell the framework to run the request "in parallel" here.
+ // Mean a completetly independant copy of the Expereiment would be done and we would proceed on that.
+ //
+ dataBackgroundFullRequest = performRequest(experiment, fullExperimentCanvas, tmpRange, intervalTime);
+ fullExperimentCanvas.redrawAsynchronously();
+ }
+
+ // *** VERIFY ***
+ // This function is synchronized, is it a good idea?
+ // Tis is done to make sure requests arrive somewhat in order,
+ // this is especially important when request are issued from different thread.
+ /**
+ * Create a new request from the given data and send it to the framework.<p>
+ * The request will be queued and processed later.
+ *
+ * @param experiment The experiment we will process the request on
+ * @param targetCanvas The canvas that will received the result
+ * @param newRange The range of the request
+ * @param newInterval The interval of time we use to store the result into the HistogramContent
+ */
+ public synchronized HistogramRequest performRequest(TmfExperiment<LttngEvent> experiment, HistogramCanvas targetCanvas, TmfTimeRange newRange, long newInterval) {
+ HistogramRequest returnedRequest = null;
+
+ // *** FIXME ***
+ // EVIL BUG!
+ // We use int.MAX_VALUE because we want every events BUT we don't know the number inside the range.
+ // HOWEVER, this would cause the request to run forever (or until it reach the end of trace).
+ // Seeting an EndTime does not seems to stop the request
+ returnedRequest = new HistogramRequest(newRange, Integer.MAX_VALUE, targetCanvas, newInterval );
+
+ // Send the request to the framework : it will be queued and processed later
+ experiment.sendRequest(returnedRequest);
+
+ return returnedRequest;
+ }
+
+ /**
+ * Function used to warn that the selection window changed.<p>
+ * This might be called because the window moved or because its size changed.<p>
+ *
+ * We will update the different control related to the selection window.
+ */
+ public void windowChangedNotification() {
+
+ if ( lastUsedExperiment != null ) {
+ // If a request is ongoing, try to stop it
+ if ( selectedWindowRequest.isCompleted() == false ) {
+ selectedWindowRequest.cancel();
+ }
+
+ // Get the latest window information
+ selectedWindowTime = fullExperimentCanvas.getCurrentWindow().getTimestampOfCenterPosition();
+ selectedWindowTimerange = fullExperimentCanvas.getCurrentWindow().getWindowTimeWidth();
+
+ // If the current event time is outside the new window, change the current event
+ // The new current event will be the one closest to the LEFT side of the new window
+ if ( isGivenTimestampInSelectedWindow(currentEventTime) == false ) {
+ currentEventChangeNotification( fullExperimentCanvas.getCurrentWindow().getTimestampOfLeftPosition() );
+ }
+
+ // Perform a new request to read data about the new window
+ performSelectedWindowEventsRequest(lastUsedExperiment);
+ }
+ }
+
+ /**
+ * Function used to tell that the current event changed.<p>
+ * This might be called because the user changed the current event or
+ * because the last current event is now outside the selection window.<p>
+ *
+ * We update the related control and send a signal to notify other views of the new current event.
+ *
+ * @param newCurrentEventTime
+ */
+ public void currentEventChangeNotification(long newCurrentEventTime) {
+
+ // Notify other views in the framework
+ if (currentEventTime != newCurrentEventTime) {
+ currentEventTime = newCurrentEventTime;
+
+ // Update the UI control
+ updateSelectedEventTime();
+ }
+ }
+
+ public void sendTmfTimeSynchSignalBroadcast() {
+
+// System.out.println("sendTmfTimeSynchSignalBroadcast " + System.currentTimeMillis());
+
+ // Send a signal to the framework
+ LttngTimestamp tmpTimestamp = new LttngTimestamp(currentEventTime);
+ broadcast(new TmfTimeSynchSignal(this, tmpTimestamp));
+ }
+
+ /**
+ * Function used to tell that the timerange (window) changed.<p>
+ * This will most likely be called if the time window is resized.
+ *
+ * We send a signal to notify other views of the new timerange.
+ */
+ public void sendTmfRangeSynchSignalBroadcast() {
+
+// System.out.println("sendTmfRangeSynchSignalBroadcast " + System.currentTimeMillis());
+
+ // *** TODO ***
+ // Not very elegant... we need to chance this below.
+ //
+ long centerTime = fullExperimentCanvas.getCurrentWindow().getTimestampOfCenterPosition();
+ long windowWidth = fullExperimentCanvas.getCurrentWindow().getWindowTimeWidth();
+
+ long startTime = centerTime-windowWidth;
+ if ( startTime < fullExperimentCanvas.getHistogramContent().getStartTime() ) {
+ startTime = fullExperimentCanvas.getHistogramContent().getStartTime();
+ }
+ LttngTimestamp tmpStartTime = new LttngTimestamp(startTime);
+
+ long endTime = centerTime+windowWidth;
+ if ( endTime > fullExperimentCanvas.getHistogramContent().getEndTime() ) {
+ endTime = fullExperimentCanvas.getHistogramContent().getEndTime();
+ }
+ LttngTimestamp tmpEndTime = new LttngTimestamp(endTime);
+
+ TmfTimeRange tmpTimeRange = new TmfTimeRange(tmpStartTime, tmpEndTime);
+ LttngTimestamp tmpEventTime = new LttngTimestamp(currentEventTime);
+
+ // Send a signal to the framework
+ broadcast(new TmfRangeSynchSignal(this, tmpTimeRange, tmpEventTime));
+ }
+
+ /**
+ * Function that will be called when one of the time text group value is changed.<p>
+ * Since we don't (and can't unless we subclass them) know which one, we check them all.
+ */
+ public void timeTextGroupChangeNotification() {
+
+ // Get all the time text group value
+ long newCurrentTime = ntgCurrentEventTime.getValue();
+ long newSelectedWindowTime = ntgCurrentWindowTime.getValue();
+ long newSelectedWindowTimeRange = ntgTimeRangeWindow.getValue();
+
+ // If the user changed the current event time, call the notification
+ if ( newCurrentTime != currentEventTime ) {
+ currentEventChangeNotification( newCurrentTime );
+ // Send a broadcast to the framework about the window change
+ sendTmfTimeSynchSignalBroadcast();
+ }
+
+ // If the user changed the selected window time, recenter the window and call the notification
+ if ( newSelectedWindowTime != selectedWindowTime ) {
+ selectedWindowTime = newSelectedWindowTime;
+ fullExperimentCanvas.setWindowCenterPosition( fullExperimentCanvas.getHistogramContent().getClosestXPositionFromTimestamp(selectedWindowTime) );
+ windowChangedNotification();
+ // Send a broadcast to the framework about the window change
+ sendTmfRangeSynchSignalBroadcast();
+ }
+
+ // If the user changed the selected window size, resize the window and call the notification
+ if ( newSelectedWindowTimeRange != selectedWindowTimerange ) {
+ selectedWindowTimerange = newSelectedWindowTimeRange;
+ fullExperimentCanvas.resizeWindowByAbsoluteTime(selectedWindowTimerange);
+ windowChangedNotification();
+ // Send a broadcast to the framework about the window change
+ sendTmfRangeSynchSignalBroadcast();
+ }
+
+ }
+
+ /**
+ * Getter for the last used experiment.<p>
+ * This might be different than the current experiment or even null.
+ *
+ * @return the last experiment we used in this view
+ */
+ public TmfExperiment<LttngEvent> getLastUsedExperiment() {
+ return lastUsedExperiment;
+ }
+
+ /**
+ * Check if a given timestamp is inside the selection window.<p>
+ * This assume fullExperimentCanvas contain a valid HistogramContent
+ *
+ * @param timestamp the timestamp to check
+ *
+ * @return if the time is inside the selection window or not
+ */
+ public boolean isGivenTimestampInSelectedWindow(long timestamp) {
+ boolean returnedValue = true;
+
+ // If the content is not set correctly, this will return weird (or even null) result
+ if ( (timestamp < fullExperimentCanvas.getCurrentWindow().getTimestampOfLeftPosition() ) ||
+ (timestamp > fullExperimentCanvas.getCurrentWindow().getTimestampOfRightPosition() ) )
+ {
+ returnedValue = false;
+ }
+
+ return returnedValue;
+ }
+
+ /**
+ * Reset the content of all Controls.<p>
+ * WARNING : Calls in there are not thread safe and can't be called from different thread than "main"
+ */
+ public void resetControlsContent() {
+
+ TmfExperiment<LttngEvent> tmpExperiment = getLastUsedExperiment();
+
+ // Use the previous Start and End time, or default if they are not available
+ String startTime = null;
+ String stopTime = null;
+ if ( tmpExperiment != null ) {
+ startTime = HistogramConstant.formatNanoSecondsTime( tmpExperiment.getStartTime().getValue() );
+ stopTime = HistogramConstant.formatNanoSecondsTime( tmpExperiment.getEndTime().getValue() );
+ }
+ else {
+ startTime = HistogramConstant.formatNanoSecondsTime( 0L );
+ stopTime = HistogramConstant.formatNanoSecondsTime( 0L );
+ }
+
+ txtExperimentStartTime.setText( startTime );
+ txtExperimentStopTime.setText( stopTime );
+ txtExperimentStartTime.getParent().layout();
+
+ txtWindowMaxNbEvents.setText("" + 0);
+ txtWindowMinNbEvents.setText("" + 0);
+ txtWindowStartTime.setText( HistogramConstant.formatNanoSecondsTime( 0L ) );
+ txtWindowStopTime.setText( HistogramConstant.formatNanoSecondsTime( 0L ) );
+ txtWindowStartTime.getParent().layout();
+
+ ntgCurrentWindowTime.setValue( HistogramConstant.formatNanoSecondsTime( 0L ) );
+ ntgTimeRangeWindow.setValue( HistogramConstant.formatNanoSecondsTime( 0L ) );
+
+ // Using "startTime" here can avoid an useless TmfTimeSynchSignal here
+ // However it look ugly to have only this time
+ ntgCurrentEventTime.setValue( HistogramConstant.formatNanoSecondsTime( 0L ) );
+ }
+
+ /**
+ * Update the content of the controls related to the full experiment canvas<p>
+ * WARNING : Calls in there are not thread safe and can't be called from different thread than "main"
+ */
+ public void updateFullExperimentInformation() {
+
+ String startTime = HistogramConstant.formatNanoSecondsTime( fullExperimentCanvas.getHistogramContent().getStartTime() );
+ String stopTime = HistogramConstant.formatNanoSecondsTime( fullExperimentCanvas.getHistogramContent().getEndTime() );
+
+ txtExperimentStartTime.setText( startTime );
+ txtExperimentStopTime.setText( stopTime );
+
+ // Take one of the parent and call its layout to update control size
+ // Since both control have the same parent, only one call is needed
+ txtExperimentStartTime.getParent().layout();
+
+ // Update the selected window, just in case
+ // This should give a better user experience and it is low cost
+ updateSelectedWindowInformation();
+ }
+
+ /**
+ * Update the content of the controls related to the selection window canvas<p>
+ * WARNING : Calls in there are not thread safe and can't be called from different thread than "main"
+ */
+ public void updateSelectedWindowInformation() {
+ // Update the timestamp as well
+ updateSelectedWindowTimestamp();
+
+ txtWindowMaxNbEvents.setText( Long.toString(selectedWindowCanvas.getHistogramContent().getHeighestEventCount()) );
+ txtWindowMinNbEvents.setText(Long.toString(0));
+
+ // Refresh the layout
+ txtWindowMaxNbEvents.getParent().layout();
+ }
+
+ /**
+ * Update the content of the controls related to the timestamp of the selection window<p>
+ * WARNING : Calls in there are not thread safe and can't be called from different thread than "main"
+ */
+ public void updateSelectedWindowTimestamp() {
+ String startTime = HistogramConstant.formatNanoSecondsTime( selectedWindowCanvas.getHistogramContent().getStartTime() );
+ String stopTime = HistogramConstant.formatNanoSecondsTime( selectedWindowCanvas.getHistogramContent().getEndTime() );
+ txtWindowStartTime.setText( startTime );
+ txtWindowStopTime.setText( stopTime );
+
+ ntgCurrentWindowTime.setValue( fullExperimentCanvas.getCurrentWindow().getTimestampOfCenterPosition() );
+ ntgTimeRangeWindow.setValue( fullExperimentCanvas.getCurrentWindow().getWindowTimeWidth() );
+
+ // If the current event time is outside the selection window, recenter our window
+ if ( isGivenTimestampInSelectedWindow(ntgCurrentEventTime.getValue()) == false ) {
+ currentEventChangeNotification( fullExperimentCanvas.getCurrentWindow().getTimestampOfCenterPosition() );
+ }
+
+ // Take one control in each group to call to refresh the layout
+ // Since both control have the same parent, only one call is needed
+ txtWindowStartTime.getParent().layout();
+ ntgCurrentWindowTime.getParent().layout();
+ }
+
+ /**
+ * Update the controls related current event.<p>
+ * The call here SHOULD be thread safe and can be call from any threads.
+ */
+ public void updateSelectedEventTime() {
+ ntgCurrentEventTime.setValueAsynchronously(currentEventTime);
+ // Tell the selection canvas which event is currently selected
+ // This give a nice graphic output
+ selectedWindowCanvas.getHistogramContent().setSelectedEventTimeInWindow(currentEventTime);
+ selectedWindowCanvas.redrawAsynchronously();
+ }
+
+ /**
+ * Method called when the view is moved.<p>
+ *
+ * Just redraw everything...
+ *
+ * @param event The controle event generated by the move.
+ */
+ public void controlMoved(ControlEvent event) {
+ parent.redraw();
+ }
+
+ /**
+ * Method called when the view is resized.<p>
+ *
+ * We will make sure that the size didn't change more than the content size.<p>
+ * Otherwise we need to perform a new request for the full experiment because we are missing data).
+ *
+ * @param event The control event generated by the resize.
+ */
+ public void controlResized(ControlEvent event) {
+
+ // Ouch! The screen enlarged (screen resolution changed?) so far that we miss content to fill the space.
+ if ( parent.getDisplay().getBounds().width > fullExperimentCanvas.getHistogramContent().getNbElement() ) {
+ if ( lastUsedExperiment != null ) {
+ createCanvasAndRequests(lastUsedExperiment);
+ }
+ }
+
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * William Bourque - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.histogram;
+
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * <b><u>ParentHistogramCanvas</u></b>
+ * <p>
+ * Extended implementation of the HistogramCanvas.
+ * <p>
+ * This canvas goal is to display the "Full experiment" histogram.
+ */
+public class ParentHistogramCanvas extends HistogramCanvas {
+
+ protected HistogramView parentHistogramWindow = null;
+
+ /**
+ * ParentHistogramCanvas constructor.<p>
+ * Same as HistogramCanvas, but receive a parent HistogramView that we can call from here.
+ *
+ * @param parent Composite control which will be the parent of the new instance (cannot be null)
+ * @param Style the style of control to construct
+ */
+ public ParentHistogramCanvas(HistogramView newParentWindow, Composite parent, int style) {
+ super(parent, style);
+
+ parentHistogramWindow = newParentWindow;
+ }
+
+ /**
+ * Create a new HistogramContent for this HistogramCanvas<p>
+ * A new <I>empty</I> canvas will then be created.
+ *
+ * IMPORTANT NOTE : This implementaton use the next power of 2 to the full screen resolution as the content size.
+ * This allow us to resize the canvas at low cost (i.e. : no need to reissue a full request)
+ * We need a "particular" paint listener that know about this.
+ *
+ * @param canvasSize Size of the parent canvas.
+ * @param widthPerBar Width of the histogram "bars"
+ * @param barsHeight Height of the histogram "bars"
+ * @param maxBarsDifferenceToAverage Factor used to "chop" bars that are too tall. Set to something big (100.0?) if not needed.
+ */
+ @Override
+ public void createNewHistogramContent(int canvasSize, int widthPerBar, int barsHeight, double maxBarsDifferenceToAverage) {
+
+ // *** FIXME ***
+ // Note there MIGHT be some unhandled case, like if the resolution of the screen change
+ // or if a new screen is plugged.
+ // Let's ignore them for now.
+ //
+ // The maximum size the canvas could ever had
+ int canvasMaxSize = getParent().getDisplay().getBounds().width;
+
+ // Calculate the power of two superior to the max size
+ int exp = (int)Math.ceil( Math.log( (double)canvasMaxSize ) / Math.log(2.0) );
+ int contentSize = (int)Math.pow(2, exp);
+
+ // Create the content
+ histogramContent = new HistogramContent( contentSize, canvasSize, widthPerBar, barsHeight, maxBarsDifferenceToAverage);
+
+ // We need to ajust the "maxDifferenceToAverageFactor" as the bars we draw might be slitghly larger than the value asked
+ // Each "interval" are concatenated when draw so the worst case should be :
+ // contentSize / (closest power of 2 to canvasMaxSize)
+ // Ex : if canvasSize is 1500 -> (2048 / 1024) == 2 so maxDiff should be twice larger
+ //
+ // Note : this is not perfect, if the screen is resized after we calculate this, the resulting output can be quite ugly
+ // For this reason, this will be recalculated in the paintListener as well.
+ double maxBarsDiffFactor = ((double)contentSize / Math.pow(2, exp-1));
+ histogramContent.setMaxDifferenceToAverageFactor(maxBarsDiffFactor);
+ }
+
+ /*
+ * Create a histogram paint listener and bind it to this canvas.<p>
+ *
+ * Note : This one is a bit particular, as it is made to draw content that is of a power of 2.
+ * The default one draw content that is relative to the real pixels size.
+ */
+ @Override
+ protected void createAndAddPaintListener() {
+ paintListener = new ParentHistogramCanvasPaintListener(this);;
+ this.addPaintListener( paintListener );
+ }
+
+ /**
+ * Function that is called when the selection window is moved.<p>
+ * Note: Given position should be relative to the previous (centered) absolute position.<p>
+ *
+ * Calculate the new position then re-center the window.<p>
+ * It will also notify the HistogramView that the window changed.
+ *
+ * @param newRelativeXPosition New position relative to the last known absolute position.
+ */
+ @Override
+ public void moveWindow(int newRelativeXPosition) {
+ int absolutePosition = currentWindow.getWindowXPositionCenter() + newRelativeXPosition;
+
+ setWindowCenterPosition(absolutePosition);
+ notifyParentSelectionWindowChangedAsynchronously();
+ }
+
+ /**
+ * Function that is called when the selection window is re-centered.<p>
+ * Note: Given position should be absolute to the window and need to be the selection window center.<p>
+ *
+ * Recenter the window and notify the HistogramView that the window changed.
+ *
+ * @param newRelativeXPosition New absolute position.
+ */
+ @Override
+ public void setWindowCenterPosition(int newAbsoluteXPosition) {
+
+ if ( newAbsoluteXPosition < 0 ) {
+ newAbsoluteXPosition = 0;
+ }
+ else if ( newAbsoluteXPosition > getParent().getSize().x ) {
+ newAbsoluteXPosition = getParent().getSize().x;
+ }
+
+ if ( newAbsoluteXPosition != currentWindow.getWindowXPositionCenter() ) {
+ currentWindow.setWindowXPositionCenter(newAbsoluteXPosition);
+ redrawAsynchronously();
+ }
+ }
+
+ /**
+ * Function that is called when the selection window size (time width) changed by an absolute time.<p>
+ * Note: Given time should be in nanoseconds, positive.
+ *
+ * Set the new window size and notify the HistogramView that the window changed.
+ *
+ * @param newTime New absoulte time (in nanoseconds) to apply to the window.
+ */
+ @Override
+ public void resizeWindowByAbsoluteTime(long newTime) {
+ if ( newTime != getSelectedWindowSize() ) {
+ setSelectedWindowSize(newTime);
+
+ notifyParentSelectionWindowChangedAsynchronously();
+ redrawAsynchronously();
+ }
+ }
+
+ /**
+ * Notify the parent HistogramView that we have updated information.<p>
+ * This is intended to be called at the end of the request when we know we have up-to-date information.
+ */
+ @Override
+ public void notifyParentUpdatedInformation() {
+ parentHistogramWindow.updateFullExperimentInformation();
+ }
+
+ /**
+ * Notify the parent HistogramView that the SelectionWindow changed.<p>
+ * This is intended to be called when the window move or is resized.
+ */
+ @Override
+ public void notifyParentSelectionWindowChanged() {
+ // Notify the parent view that something changed
+ parentHistogramWindow.windowChangedNotification();
+ // Send a broadcast to the framework about the window change
+ parentHistogramWindow.sendTmfRangeSynchSignalBroadcast();
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * William Bourque - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.histogram;
+
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.graphics.Rectangle;
+
+/**
+ * <b><u>HistogramCanvasPaintListener</u></b>
+ * <p>
+ * Implementation of a PaintListener for the specific need of the ParentHistogramCanvas.
+ * <p>
+ * The difference with the default one is that this one take a content that is the power of 2 higher
+ * than the display size.<p>
+ *
+ * When it is time to draw, it takes the closest power of 2 smaller than the canvas size; it is then easy to
+ * concatenate the interval as they are both power of 2.<p>
+ * The difference between the power of 2 and the not-power-of-2 canvas size is then filled by drawing bar that are
+ * slightly larger every (power/canvasSize) interval.<p>
+ */
+public class ParentHistogramCanvasPaintListener extends HistogramCanvasPaintListener
+{
+ public ParentHistogramCanvasPaintListener(HistogramCanvas newParentCanvas) {
+ super(newParentCanvas);
+ }
+
+
+ // *** VERIFY ***
+ // Is it good to put this synchronized?
+ //
+ /**
+ * Draw the histogram bars in the canvas.<p>
+ * This drawing function expect the content to be the power of 2 higher than the canvas size.
+ * The bars size will be slightly dynamic to fill the gap between the power and the canvas size.<p>
+ *
+ * Note : This draw function is somewhat heavier than the default one.
+ *
+ * @param event The generated paint event when redraw is called.
+ */
+ @Override
+ public synchronized void drawHistogram(PaintEvent event) {
+ HistogramContent tmpContent = parentCanvas.getHistogramContent();
+ int tmpBarWidth = tmpContent.getBarsWidth();
+ int canvasSize = event.width;
+
+ event.gc.setBackground(event.display.getSystemColor(HistogramConstant.HISTOGRAM_BARS_COLOR));
+
+ // Calculate the closest power of 2 just smaller than the canvas size
+ int closestPowerToCanvas = (int)Math.pow(2, Math.floor( Math.log( canvasSize ) / Math.log(2.0) ));
+
+ // Make sure the canvas didn't change size, it which case we need to recalculate our heights
+ recalculateHeightIfCanvasSizeChanged();
+
+ // Calculate the factor of difference between canvas and the power
+ double factor = (double)canvasSize / (double)closestPowerToCanvas;
+ // Calculate how many interval will need to be concatenated into one pixel
+ int intervalDifference = (tmpContent.getNbElement() / closestPowerToCanvas)*tmpBarWidth;
+
+ // This keep a link between the position in "power" and the pixel we draw
+ // I.e. correlation between position in the power ("fake" pixels) and the position in the canvas ("real" pixels)
+ // So if pos == 30 and factor == 1.5, we know that the pixel that draw this pos is (30 * 1.5) == 45
+ int posInPower = 0;
+ int widthFilled = 0;
+
+ // Read from 0 up to the currently ready position
+ // We advance by "intervalDifference" as the bars migth not represent 1 interval only
+ for( int contentPos=0; contentPos < tmpContent.getReadyUpToPosition(); contentPos += intervalDifference ) {
+ // Width of the current item.
+ // Vary because of the difference between the power of 2 and the canvas size
+ // Ex: if power == 1024 and canvas == 1500, a bars every (1024/1500) will have a size of 2 instead of 1.
+ int itemWidth = (int)( Math.ceil((double)(posInPower+1)*factor) - Math.ceil((double)posInPower*factor) );
+ itemWidth = itemWidth*tmpBarWidth;
+
+ // Concatenate all the element in the interval
+ // Ex : if power == 1024 and content == 2048, every (2048/1024)*bars_width will be concatenated
+ int thisElementHeight = 0;
+ for ( int concatPos=0; concatPos<intervalDifference; concatPos++) {
+ int updatedPos = contentPos + concatPos;
+ // Make sure we don't cross the last element available.
+ if ( updatedPos < tmpContent.getReadyUpToPosition() ) {
+ thisElementHeight += tmpContent.getElementByIndex(contentPos + concatPos).intervalHeight;
+ }
+ }
+
+ // *** NOTE ***
+ // Y Position in a canvas is REVERSED, so "0" is on top of the screen and "MAX" is on bottom.
+ // Not very instinctive, isn't it?
+
+ // Draw our rectangle
+ Rectangle rect = new Rectangle(widthFilled, event.height - thisElementHeight, itemWidth, thisElementHeight);
+ event.gc.fillRectangle(rect);
+
+ // Keep in a variable how much width we filld so far
+ widthFilled += itemWidth;
+ // Keep a correlation between fake_pixel -> real_pixel,
+ // this is used to calculate the width of each element
+ posInPower++;
+ }
+
+ // Clear the remaining space in the canvas (there should not be any) so it appears clean.
+ event.gc.setBackground(event.display.getSystemColor(HistogramConstant.EMPTY_BACKGROUND_COLOR));
+ Rectangle rect = new Rectangle(widthFilled, 0, event.width, event.height);
+ event.gc.fillRectangle(rect);
+ }
+
+ /*
+ * The function will make sure that the "max difference average" factor is still the same as before;
+ * if not, the heigth of the events will be recalculated.<p>
+ *
+ * The factor might change if the canvas is resized by a big factor.<p>
+ */
+ protected void recalculateHeightIfCanvasSizeChanged() {
+ HistogramContent tmpContent = parentCanvas.getHistogramContent();
+ // We need to ajust the "maxDifferenceToAverageFactor" as the bars we draw might be slitghly larger than the value asked
+ // Each "interval" are concatenated when draw so the worst case should be :
+ // contentSize / (closest power of 2 to canvasMaxSize)
+ // Ex : if canvasSize is 1500 -> (2048 / 1024) == 2 so maxDiff should be twice larger
+ //
+ // His is set in the create content of the canvas, but we need to recalculate it
+ // here because the window might have been resized!
+ int exp = (int)Math.floor( Math.log( (double)tmpContent.getCanvasWindowSize() ) / Math.log(2.0) );
+ int contentSize = (int)Math.pow(2, exp);
+ double maxBarsDiffFactor = ((double)tmpContent.getNbElement() / (double)contentSize );
+
+ // Floating point comparaison :
+ // We consider it is different if the difference is greater than 10^-3
+ if ( Math.abs(maxBarsDiffFactor - tmpContent.getMaxDifferenceToAverageFactor()) > 0.001 ) {
+ // The factor changed! That's unfortunate because it will take a while to recalculate.
+ tmpContent.setMaxDifferenceToAverageFactor(maxBarsDiffFactor);
+ tmpContent.recalculateHeightFactor();
+ tmpContent.recalculateEventHeight();
+ }
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.histogram;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * <b><u>TimeTextGroup</u></b>
+ * <p>
+ * Special control for HistogramView
+ * <p>
+ * This control will give you a group, a text box and a label at once.
+ */
+public class TimeTextGroup implements FocusListener, KeyListener {
+
+ protected static final String NANOSEC_LABEL = "sec";
+ protected static final String LONGEST_STRING_VALUE = "." + Long.MAX_VALUE;
+ protected static final int MAX_CHAR_IN_TEXTBOX = LONGEST_STRING_VALUE.length();
+
+ // The "small font" height used to display time will be "default font" minus this constant
+ protected static final int VERY_SMALL_FONT_MODIFIER = 2;
+ protected static final int SMALL_FONT_MODIFIER = 1;
+
+ // Indentation size
+ protected static final int DEFAULT_INDENT_SIZE = 10;
+
+ protected HistogramView parentView = null;
+ protected AsyncTimeTextGroupRedrawer asyncRedrawer = null;
+
+ protected Group grpName = null;
+ protected Text txtNanosec = null;
+ protected Label lblNanosec = null;
+
+ protected long timeValue = 0L;
+
+ /**
+ * Default Constructor.<p>
+ *
+ * @param newParentView Parent HistogramView
+ * @param parent Parent Composite, used to position the inner controls.
+ * @param textStyle Style of the textbox. Usually SWT.BORDER or SWT.NONE (or anything that suit a Text)
+ * @param groupStyle Style of the group. Anything that suite a Text
+ */
+ public TimeTextGroup(HistogramView newParentView, Composite parent, int textStyle, int groupStyle) {
+ this(newParentView, parent, textStyle, groupStyle, "", HistogramConstant.formatNanoSecondsTime(0L), false);
+ }
+
+ /**
+ * Default Constructor with adjustement for small screen.<p>
+ *
+ * @param newParentView Parent HistogramView
+ * @param parent Parent Composite, used to position the inner controls.
+ * @param textStyle Style of the textbox. Usually SWT.BORDER or SWT.NONE (or anything that suit a Text)
+ * @param groupStyle Style of the group. Anything that suite a Text
+ * @param isSpaceSaverNeeded Value that tell if we try to save some space in the control.
+ */
+ public TimeTextGroup(HistogramView newParentView, Composite parent, int textStyle, int groupStyle, boolean isSpaceSaverNeeded) {
+ this(newParentView, parent, textStyle, groupStyle, "", HistogramConstant.formatNanoSecondsTime(0L), isSpaceSaverNeeded);
+ }
+
+ /**
+ * Default Constructor, allow you to give the groupname and the textbox value.<p>
+ *
+ * @param newParentView Parent HistogramView
+ * @param parent Parent Composite, used to position the inner controls.
+ * @param textStyle Style of the textbox. Usually SWT.BORDER or SWT.NONE (or anything that suit a Text)
+ * @param groupStyle Style of the group. Anything that suite a Text
+ * @param groupValue Value (label) of the group.
+ * @param textValue Value of the textbox.
+ */
+ public TimeTextGroup(HistogramView newParentView, Composite parent, int textStyle, int groupStyle, String groupValue, String textValue) {
+ this(newParentView, parent, textStyle, groupStyle, groupValue, textValue, false);
+ }
+
+ /**
+ * Default Constructor with adjustement for small screen, allow you to give the groupname and the textbox value.<p>
+ *
+ * @param newParentView Parent HistogramView
+ * @param parent Parent Composite, used to position the inner controls.
+ * @param textStyle Style of the textbox. Usually SWT.BORDER or SWT.NONE (or anything that suit a Text)
+ * @param groupStyle Style of the group. Anything that suite a Text
+ * @param groupValue Value (label) of the group.
+ * @param textValue Value of the textbox.
+ * @param isSpaceSaverNeeded Value that tell if we try to save some space in the control.
+ */
+ public TimeTextGroup(HistogramView newParentView, Composite parent, int textStyle, int groupStyle, String groupValue, String textValue, boolean isSpaceSaverNeeded) {
+ Font font = parent.getFont();
+ FontData tmpFontData = font.getFontData()[0];
+
+ Font smallFont = null;
+ int textBoxSize = -1;
+ int indentSize = -1;
+
+ // If we were asked to save size, calculate the correct value here
+ if ( isSpaceSaverNeeded == true ) {
+ smallFont = new Font(font.getDevice(), tmpFontData.getName(), tmpFontData.getHeight()-VERY_SMALL_FONT_MODIFIER, tmpFontData.getStyle());
+
+ // No minimum textBoxSize and no indent size
+ textBoxSize = 0;
+ indentSize = 0;
+ }
+ else {
+ // We use only a slightly smaller font
+ smallFont = new Font(font.getDevice(), tmpFontData.getName(), tmpFontData.getHeight()-SMALL_FONT_MODIFIER, tmpFontData.getStyle());
+
+ // ** Creation of the textbox
+ // Calculate the optimal size of the textbox already
+ // This will avoid the control to move around and resize when bigger value are given
+ textBoxSize = HistogramConstant.getTextSizeInControl(parent, LONGEST_STRING_VALUE);
+
+ // Default indent
+ indentSize = DEFAULT_INDENT_SIZE;
+ }
+
+ parentView = newParentView;
+
+ // ** Creation of the group
+ GridLayout gridLayoutgroup = new GridLayout(2, false);
+ gridLayoutgroup.horizontalSpacing = 0;
+ gridLayoutgroup.verticalSpacing = 0;
+ grpName = new Group(parent, groupStyle);
+ grpName.setText(groupValue);
+ grpName.setFont(smallFont);
+ grpName.setLayout(gridLayoutgroup);
+
+ txtNanosec = new Text(grpName, textStyle);
+ txtNanosec.setTextLimit( MAX_CHAR_IN_TEXTBOX );
+ txtNanosec.setText( textValue );
+ txtNanosec.setFont(smallFont);
+ GridData gridDataTextBox = new GridData(SWT.LEFT, SWT.CENTER, true, false);
+ gridDataTextBox.horizontalIndent = indentSize;
+ gridDataTextBox.verticalIndent = 0;
+ gridDataTextBox.minimumWidth = textBoxSize;
+ txtNanosec.setLayoutData(gridDataTextBox);
+
+ // ** Creation of the label
+ lblNanosec = new Label(grpName, SWT.LEFT);
+ lblNanosec.setText(NANOSEC_LABEL);
+ lblNanosec.setFont(smallFont);
+ GridData gridDataLabel = new GridData(SWT.LEFT, SWT.CENTER, false, false);
+ gridDataLabel.horizontalIndent = indentSize;
+ gridDataLabel.verticalIndent = 0;
+ lblNanosec.setLayoutData(gridDataLabel);
+
+ // Add all listener
+ addNeededListeners();
+ }
+
+ /*
+ * Create and add all listeners needed by our control.<p>
+ */
+ protected void addNeededListeners() {
+
+ // AsyncCanvasRedrawer is an internal class
+ // This is used to redraw the canvas without danger from a different thread
+ asyncRedrawer = new AsyncTimeTextGroupRedrawer(this);
+
+ txtNanosec.addFocusListener(this);
+ txtNanosec.addKeyListener(this);
+ }
+
+ /**
+ * Getter for the layout data currently in use.<p>
+ *
+ * @return the layout
+ */
+ public Object getLayoutData() {
+ return grpName.getLayoutData();
+ }
+
+ /**
+ * Set a new layoutData for our control.<p>
+ *
+ * @param layoutData the new layout data
+ */
+ public void setLayoutData(Object layoutData) {
+ grpName.setLayoutData(layoutData);
+ }
+
+ /**
+ * Get the control's parent.<p>
+ *
+ * @return Currently used parent
+ */
+ public Composite getParent() {
+ return grpName.getParent();
+ }
+
+ /**
+ * Set a new parent for the control.<p>
+ *
+ * @return Currently used parent
+ */
+ public void setParent(Composite newParent) {
+ grpName.setParent(newParent);
+ txtNanosec.setParent(newParent);
+ lblNanosec.setParent(newParent);
+ }
+
+ /**
+ * Getter for the time value of the control.<p>
+ *
+ * @return The nanoseconds time value
+ */
+ public long getValue() {
+ return timeValue;
+ }
+
+ /**
+ * Set a new String value to the control.<p>
+ * Note : The String value will be converted in long before being applied;
+ * if any conversion error occur, 0 will be used. <p>
+ *
+ * @param newTimeAsString The value to convert and set.
+ */
+ public void setValue(String newTimeAsString) {
+ long timeAsLong = HistogramConstant.convertStringToNanoseconds(newTimeAsString);
+ setValue( timeAsLong );
+ }
+
+ /**
+ * Set a new value to the control.<p>
+ * Note : The value will be formatted as nanosecond value,
+ * missing zero will be added if needed.<p>
+ *
+ * @param newTime The value to set.
+ */
+ public void setValue(long newTime) {
+ timeValue = newTime;
+ txtNanosec.setText( HistogramConstant.formatNanoSecondsTime(newTime) );
+ }
+
+ /**
+ * Set a new String value, asynchronously.<p>
+ * This will call setValue(String) in async.Exec to avoid Thread Access problem to UI.<p>
+ *
+ * @param newTimeAsString The value to convert and set.
+ */
+ public void setValueAsynchronously(String newTimeAsString) {
+ long timeAsLong = HistogramConstant.convertStringToNanoseconds(newTimeAsString);
+ setValueAsynchronously( timeAsLong );
+ }
+
+ /**
+ * Set a new String value, asynchronously.<p>
+ * This will call setValue(long) in async.Exec to avoid Thread Access problem to UI.<p>
+ *
+ * @param newTimeAsString The value to set.
+ */
+ public void setValueAsynchronously(long newTime) {
+ // Set the correct value ASAP
+ timeValue = newTime;
+
+ // Create a new redrawer in case it doesn't exist yet (we never know with thread!)
+ if ( asyncRedrawer == null ) {
+ asyncRedrawer = new AsyncTimeTextGroupRedrawer(this);
+ }
+
+ asyncRedrawer.asynchronousSetValue(newTime);
+ }
+
+ /**
+ * Set a new group name (label) for this control.<p>
+ *
+ * @param newName The new name to set.
+ */
+ public void setGroupName(String newName) {
+ grpName.setText(newName);
+ }
+
+ /**
+ * Set a new group name (label) for this control, asynchronously.<p>
+ * This will call setValue(long) in async.Exec to avoid Thread Access problem to UI.<p>
+ *
+ * @param newName The new name to set.
+ */
+ public void setGroupNameAsynchronously(String newGroupName) {
+ // Create a new redrawer in case it doesn't exist yet (we never know with thread!)
+ if ( asyncRedrawer == null ) {
+ asyncRedrawer = new AsyncTimeTextGroupRedrawer(this);
+ }
+
+ asyncRedrawer.asynchronousSetGroupName(newGroupName);
+ }
+
+
+ /**
+ * Method to call the "Asynchronous redrawer" for this time text group<p>
+ * This allow safe redraw from different threads.
+ */
+ public void redrawAsynchronously() {
+ // Create a new redrawer in case it doesn't exist yet (we never know with thread!)
+ if ( asyncRedrawer == null ) {
+ asyncRedrawer = new AsyncTimeTextGroupRedrawer(this);
+ }
+
+ asyncRedrawer.asynchronousRedraw();
+ }
+
+ /**
+ * Redraw the control
+ */
+ public void redraw () {
+ grpName.redraw();
+ txtNanosec.redraw();
+ lblNanosec.redraw();
+ }
+
+ /*
+ * This function is called when an user enter a new string in the control by hand.<p>
+ * It will ensure the format of the String is valid.
+ */
+ protected void handleNewStringValue() {
+ String valueInText = txtNanosec.getText();
+ long valueAsLong = HistogramConstant.convertStringToNanoseconds(valueInText);
+
+ if ( getValue() != valueAsLong ) {
+ setValue(valueAsLong);
+ // Notify our parent that the control was updated
+ notifyParentUpdatedTextGroupValue();
+ }
+ }
+
+ /**
+ * This function notify our parent HistogramView that our value changed.
+ */
+ public void notifyParentUpdatedTextGroupValue() {
+ parentView.timeTextGroupChangeNotification();
+ }
+
+ /**
+ * Function that is called when the canvas get focus.<p>
+ *
+ * Doesn't do anything yet...
+ *
+ * @param event The focus event generated.
+ */
+ public void focusGained(FocusEvent event) {
+ // Nothing to do yet
+ }
+
+ /**
+ * Function that is called when the canvas loose focus.<p>
+ * It will validate that the String entered by the user (if any) is valid.<p>
+ *
+ * @param event The focus event generated.
+ */
+ public void focusLost(FocusEvent event) {
+ handleNewStringValue();
+ }
+
+ /**
+ * Function that is called when a key is pressed.<p>
+ * Possible actions :
+ * - Enter (CR) : Validate the entered String.<p>
+ *
+ * @param event The KeyEvent generated when the key was pressed.
+ */
+ public void keyPressed(KeyEvent event) {
+ switch (event.keyCode) {
+ // SWT.CR is "ENTER" Key
+ case SWT.CR:
+ handleNewStringValue();
+ break;
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Function that is called when a key is released.<p>
+ * Possible actions :
+ * Nothing yet
+ *
+ * @param event The KeyEvent generated when the key was pressed.
+ */
+ public void keyReleased(KeyEvent e) {
+
+ }
+}
+
+/**
+ * <b><u>AsyncTimeTextGroupRedrawer Inner Class</u></b>
+ * <p>
+ * Asynchronous redrawer for the TimeTextGroup
+ * <p>
+ * This class role is to call method that update the UI on asynchronously.
+ * This should prevent any "invalid thread access" exception when trying to update UI from a different thread.
+ */
+class AsyncTimeTextGroupRedrawer {
+
+ private TimeTextGroup parentTimeTextGroup = null;
+
+ /**
+ * AsyncTimeTextGroupRedrawer constructor.
+ *
+ * @param newParent Related time text group.
+ */
+ public AsyncTimeTextGroupRedrawer(TimeTextGroup newParent) {
+ parentTimeTextGroup = newParent;
+ }
+
+ /**
+ * Asynchronous SetValue for time text group.
+ *
+ * Basically, it just run "getParent().setValue(time)" in asyncExec.
+ *
+ * @param newTime The new time to set
+ */
+ public void asynchronousSetValue(long newTime) {
+ final long tmpTime = newTime;
+
+ Display display = parentTimeTextGroup.getParent().getDisplay();
+ display.asyncExec(new Runnable() {
+ public void run() {
+ parentTimeTextGroup.setValue(tmpTime);
+ }
+ });
+ }
+
+ /**
+ * Asynchronous SetGroupName for time text group.
+ *
+ * Basically, it just run "getParent().setGroupName(name)" in asyncExec.
+ *
+ * @param newGroupName The new group name to set
+ */
+ public void asynchronousSetGroupName(String newGroupName) {
+ final String tmpName = newGroupName;
+
+ Display display = parentTimeTextGroup.getParent().getDisplay();
+ display.asyncExec(new Runnable() {
+ public void run() {
+ parentTimeTextGroup.setGroupName(tmpName);
+ }
+ });
+ }
+
+ /**
+ * Function to redraw the related time text group asynchonously.<p>
+ *
+ * Basically, it just run "getParent().redraw()" in asyncExec.
+ *
+ */
+ public void asynchronousRedraw() {
+ Display display = parentTimeTextGroup.getParent().getDisplay();
+ display.asyncExec(new Runnable() {
+ public void run() {
+ parentTimeTextGroup.getParent().redraw();
+ }
+ });
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectNature;
+import org.eclipse.core.runtime.CoreException;
+
+/**
+ * <b><u>LTTngProjectNature</u></b>
+ * <p>
+ * This is really a marker for the LTTng projects.
+ */
+public class LTTngProjectNature implements IProjectNature {
+
+ public static final String ID = "org.eclipse.linuxtools.lttng.ui.views.project.LTTngProjectNature";
+
+ private IProject fProject;
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.resources.IProjectNature#configure()
+ */
+ public void configure() throws CoreException {
+ // TODO Auto-generated method stub
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.resources.IProjectNature#deconfigure()
+ */
+ public void deconfigure() throws CoreException {
+ // TODO Auto-generated method stub
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.resources.IProjectNature#getProject()
+ */
+ public IProject getProject() {
+ return fProject;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.resources.IProjectNature#setProject(org.eclipse.core.resources.IProject)
+ */
+ public void setProject(IProject project) {
+ fProject = project;
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project;
+
+import java.io.FileNotFoundException;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TreeSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.linuxtools.lttng.event.LttngEvent;
+import org.eclipse.linuxtools.lttng.state.experiment.StateManagerFactory;
+import org.eclipse.linuxtools.lttng.trace.LTTngTrace;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.ILTTngProjectTreeNode;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngExperimentNode;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngProjectContentProvider;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngProjectLabelProvider;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngProjectRoot;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngTraceNode;
+import org.eclipse.linuxtools.tmf.experiment.TmfExperiment;
+import org.eclipse.linuxtools.tmf.signal.TmfExperimentSelectedSignal;
+import org.eclipse.linuxtools.tmf.trace.ITmfTrace;
+import org.eclipse.linuxtools.tmf.ui.views.TmfView;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Tree;
+
+/**
+ * <b><u>ProjectView</u></b>
+ * <p>
+ * The ProjectView keeps track of the LTTng projects in the workspace.
+ */
+public class ProjectView extends TmfView {
+
+ public static final String ID = "org.eclipse.linuxtools.lttng.ui.views.project";
+
+ // ------------------------------------------------------------------------
+ // Main data structures
+ // ------------------------------------------------------------------------
+
+ private TreeViewer fViewer;
+ private LTTngProjectRoot fProjectRoot;
+ private TmfExperiment<LttngEvent> fSelectedExperiment = null;
+
+ private IWorkspace fWorkspace;
+ private IResourceChangeListener fResourceChangeListener;
+
+ // ------------------------------------------------------------------------
+ // View refresher
+ // ------------------------------------------------------------------------
+
+ // Perform updates on the UI thread
+ private Runnable fViewRefresher = new Runnable() {
+ public void run() {
+ if (fViewer != null) {
+ Object[] elements = fViewer.getExpandedElements();
+ fViewer.refresh();
+ fViewer.setExpandedElements(elements);
+ }
+ }
+ };
+
+ public LTTngProjectRoot getRoot() {
+ return fProjectRoot;
+ }
+
+ // ------------------------------------------------------------------------
+ // Constructor
+ // ------------------------------------------------------------------------
+
+ public ProjectView() {
+
+ super("ProjectView");
+ fProjectRoot = new LTTngProjectRoot(this);
+
+ fWorkspace = ResourcesPlugin.getWorkspace();
+ fResourceChangeListener = new IResourceChangeListener() {
+ public void resourceChanged(IResourceChangeEvent event) {
+ if (event.getType() == IResourceChangeEvent.POST_CHANGE) {
+ fProjectRoot.refreshChildren();
+ refresh();
+ }
+ }
+ };
+ fWorkspace.addResourceChangeListener(fResourceChangeListener);
+ }
+
+ public void refresh() {
+ Tree tree = fViewer.getTree();
+ if (tree != null && !tree.isDisposed())
+ tree.getDisplay().asyncExec(fViewRefresher);
+ }
+
+ public void setSelection(ILTTngProjectTreeNode node) {
+ fViewer.setSelection(new StructuredSelection(node), true);
+ }
+
+ @Override
+ public void dispose() {
+ fWorkspace.removeResourceChangeListener(fResourceChangeListener);
+ }
+
+ @Override
+ public void createPartControl(Composite parent) {
+
+ fViewer = new TreeViewer(parent, SWT.SINGLE);
+ fViewer.setContentProvider(new LTTngProjectContentProvider());
+ fViewer.setSorter(new ViewerSorter());
+ fViewer.setLabelProvider(new LTTngProjectLabelProvider());
+ fViewer.setInput(fProjectRoot);
+
+ getSite().setSelectionProvider(fViewer);
+ hookMouse();
+
+ createContextMenu();
+ }
+
+ // ------------------------------------------------------------------------
+ // ViewPart
+ // ------------------------------------------------------------------------
+
+ @Override
+ public String toString() {
+ return "[ProjectView]";
+ }
+
+ // ------------------------------------------------------------------------
+ // hookMouse
+ // ------------------------------------------------------------------------
+
+ private void hookMouse() {
+ fViewer.getTree().addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseDoubleClick(MouseEvent event) {
+ TreeSelection selection = (TreeSelection) fViewer.getSelection();
+ Object element = selection.getFirstElement();
+ if (element instanceof LTTngExperimentNode) {
+ LTTngExperimentNode experiment = (LTTngExperimentNode) element;
+ selectExperiment(experiment);
+ }
+ }
+ });
+ }
+
+ private boolean waitForCompletion = true;
+
+ /**
+ * @param experiment
+ */
+ public void selectExperiment(LTTngExperimentNode experiment) {
+ String expId = experiment.getName();
+ if (fSelectedExperiment != null)
+ fSelectedExperiment.dispose();
+ try {
+ LTTngTraceNode[] traceEntries = experiment.getTraces();
+ int nbTraces = traceEntries.length;
+ ITmfTrace[] traces = new ITmfTrace[nbTraces];
+ for (int i = 0; i < nbTraces; i++) {
+ IResource res = traceEntries[i].getFolder();
+ String location = res.getLocation().toOSString();
+ ITmfTrace trace = new LTTngTrace(location, waitForCompletion);
+ traces[i] = trace;
+ }
+ fSelectedExperiment = new TmfExperiment<LttngEvent>(LttngEvent.class, expId, traces);
+ fSelectedExperiment.indexExperiment(waitForCompletion);
+ // Make sure the lttng-core, experiment selection context is ready
+ // for an event request from any view
+ StateManagerFactory.getExperimentManager().experimentSelected_prep(
+ (TmfExperiment<LttngEvent>) fSelectedExperiment);
+
+ broadcast(new TmfExperimentSelectedSignal<LttngEvent>(this, fSelectedExperiment));
+ } catch (FileNotFoundException e) {
+ return;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // createContextMenu
+ // ------------------------------------------------------------------------
+
+ // Populated from the plug-in
+ private void createContextMenu() {
+ MenuManager menuManager = new MenuManager("#PopupMenu");
+ menuManager.setRemoveAllWhenShown(true);
+ Menu menu = menuManager.createContextMenu(fViewer.getControl());
+ fViewer.getControl().setMenu(menu);
+ getSite().registerContextMenu(menuManager, fViewer);
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.dialogs;
+
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngExperimentNode;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngProjectNode;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngTraceNode;
+import org.eclipse.ui.IImportWizard;
+import org.eclipse.ui.IWorkbench;
+
+/**
+ * <b><u>AddTraceWizard</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+public class AddTraceWizard extends Wizard implements IImportWizard {
+
+ private LTTngProjectNode fProject;
+ private LTTngExperimentNode fExperiment;
+ private AddTraceWizardPage fMainPage;
+
+ /**
+ * @param project
+ */
+ public AddTraceWizard(LTTngProjectNode project, LTTngExperimentNode experiment) {
+ fProject = project;
+ fExperiment = experiment;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.IWorkbenchWizard#init(org.eclipse.ui.IWorkbench, org.eclipse.jface.viewers.IStructuredSelection)
+ */
+ public void init(IWorkbench workbench, IStructuredSelection selection) {
+ setWindowTitle("Adding traces to experiment");
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.wizard.Wizard#addPages()
+ */
+ @Override
+ public void addPages() {
+ super.addPages();
+ fMainPage = new AddTraceWizardPage(fProject, "Some string");
+ addPage(fMainPage);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.wizard.Wizard#performFinish()
+ */
+ @Override
+ public boolean performFinish() {
+
+ IWorkspace workspace = ResourcesPlugin.getWorkspace();
+ IFolder experimentFolder = fExperiment.getFolder();
+
+ LTTngTraceNode[] traces = fMainPage.getSelection();
+ for (LTTngTraceNode trace : traces) {
+ try {
+ IFolder folder = experimentFolder.getFolder(trace.getName());
+ IPath location = trace.getFolder().getLocation();
+ if (workspace.validateLinkLocation(folder, location).isOK()) {
+ folder.createLink(location, IResource.REPLACE, null);
+ fExperiment.addTrace(folder);
+ }
+ else {
+ System.out.println("Problem");
+ }
+ } catch (CoreException e) {
+ e.printStackTrace();
+ }
+ }
+
+ return true;
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.dialogs;
+
+import java.util.Vector;
+
+import org.eclipse.jface.viewers.CheckboxTableViewer;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngProjectNode;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngTraceNode;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FormAttachment;
+import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.layout.FormLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+
+/**
+ * <b><u>AddTraceWizardPage</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+public class AddTraceWizardPage extends WizardPage {
+
+ private LTTngProjectNode fProject;
+ private CheckboxTableViewer fCheckboxTableViewer;
+
+ protected AddTraceWizardPage(LTTngProjectNode project, String pageName) {
+ super(pageName);
+ setTitle("Select traces");
+ setDescription("Select the traces to add to the experiment");
+ fProject = project;
+ }
+
+ public void createControl(Composite parent) {
+ Composite container = new Composite(parent, SWT.NULL);
+ container.setLayout(new FormLayout());
+ setControl(container);
+
+ fCheckboxTableViewer = CheckboxTableViewer.newCheckList(container, SWT.BORDER);
+ fCheckboxTableViewer.setContentProvider(new DialogTraceContentProvider());
+ fCheckboxTableViewer.setLabelProvider(new DialogTraceLabelProvider());
+
+ final Table table = fCheckboxTableViewer.getTable();
+ final FormData formData = new FormData();
+ formData.bottom = new FormAttachment(100, 0);
+ formData.right = new FormAttachment(100, 0);
+ formData.top = new FormAttachment(0, 0);
+ formData.left = new FormAttachment(0, 0);
+ table.setLayoutData(formData);
+ table.setHeaderVisible(true);
+
+ final TableColumn tableColumn = new TableColumn(table, SWT.NONE);
+ tableColumn.setWidth(200);
+ tableColumn.setText("Trace");
+
+ fCheckboxTableViewer.setInput(fProject.getTracesFolder());
+ }
+
+ public LTTngTraceNode[] getSelection() {
+ Vector<LTTngTraceNode> traces = new Vector<LTTngTraceNode>();
+ Object[] selection = fCheckboxTableViewer.getCheckedElements();
+ for (Object sel : selection) {
+ if (sel instanceof LTTngTraceNode)
+ traces.add((LTTngTraceNode) sel);
+ }
+ LTTngTraceNode[] result = new LTTngTraceNode[traces.size()];
+ traces.toArray(result);
+ return result;
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.dialogs;
+
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngTraceFolderNode;
+
+/**
+ * <b><u>LTTngTracesContentProvider</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+public class DialogTraceContentProvider implements IStructuredContentProvider {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
+ */
+ public Object[] getElements(Object inputElement) {
+ if (inputElement instanceof LTTngTraceFolderNode) {
+ LTTngTraceFolderNode folder = (LTTngTraceFolderNode) inputElement;
+ return folder.getTraces();
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.IContentProvider#dispose()
+ */
+ public void dispose() {
+ // TODO Auto-generated method stub
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
+ */
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ // TODO Auto-generated method stub
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.dialogs;
+
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngTraceNode;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * <b><u>LTTngTracesLabelProvider</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+public class DialogTraceLabelProvider extends LabelProvider implements ITableLabelProvider {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
+ */
+ public Image getColumnImage(Object element, int columnIndex) {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
+ */
+ public String getColumnText(Object element, int columnIndex) {
+ if (element instanceof LTTngTraceNode) {
+ LTTngTraceNode entry = (LTTngTraceNode) element;
+ switch (columnIndex) {
+ case 0:
+ return entry.getName();
+ default:
+ return null;
+ }
+ }
+ return null;
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.dialogs;
+
+import java.util.List;
+
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.ui.IImportWizard;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.internal.WorkbenchPlugin;
+import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
+import org.eclipse.ui.internal.wizards.datatransfer.DataTransferMessages;
+
+/**
+ * <b><u>ImportTraceWizard</u></b>
+ * <p>
+ *
+ * TODO: Implement me. Please.
+ */
+@SuppressWarnings("restriction")
+public class ImportTraceWizard extends Wizard implements IImportWizard {
+
+ private IWorkbench fWorkbench;
+ private IStructuredSelection fSelection;
+ private ImportTraceWizardPage fMainPage;
+
+ /**
+ *
+ */
+ public ImportTraceWizard() {
+ IDialogSettings workbenchSettings = WorkbenchPlugin.getDefault().getDialogSettings();
+ IDialogSettings section = workbenchSettings.getSection("LTTngTraceImportWizard");
+ if (section == null) {
+ section = workbenchSettings.addNewSection("LTTngTraceImportWizard");
+ }
+
+ setDialogSettings(section);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.wizard.Wizard#addPages()
+ */
+ @Override
+ public void addPages() {
+ super.addPages();
+ fMainPage = new ImportTraceWizardPage(fWorkbench, fSelection);
+ addPage(fMainPage);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.IWorkbenchWizard#init(org.eclipse.ui.IWorkbench, org.eclipse.jface.viewers.IStructuredSelection)
+ */
+ @SuppressWarnings("rawtypes")
+ public void init(IWorkbench workbench, IStructuredSelection selection) {
+ fWorkbench = workbench;
+ fSelection = selection;
+
+ List selectedResources = IDE.computeSelectedResources(selection);
+ if (!selectedResources.isEmpty()) {
+ fSelection = new StructuredSelection(selectedResources);
+ }
+
+ setWindowTitle(DataTransferMessages.DataTransfer_importTitle);
+ setDefaultPageImageDescriptor(IDEWorkbenchPlugin.getIDEImageDescriptor("wizban/importdir_wiz.png"));
+ setNeedsProgressMonitor(true);
+ }
+
+ public ImportTraceWizardPage getMainPage() {
+ return fMainPage;
+ }
+
+ /**
+ * performFinish is called after the "finish" button is pressed in the import wizard
+ * If we return "false", the wizard will not close.
+ *
+ * We perform here version check on the imported LTTng trace
+ *
+ */
+ @Override
+ public boolean performFinish() {
+
+ if ( fMainPage.getDestination().equals( fMainPage.getInitialContainerString() ) ) {
+
+ String errMessage[] = { "Error : import destination is wrong." };
+ errMessage = fMainPage.extendErrorMessage(errMessage, "");
+ errMessage = fMainPage.extendErrorMessage(errMessage, "You cannot import your trace directly into the \"" + fMainPage.getInitialContainerString() + "\"");
+ errMessage = fMainPage.extendErrorMessage(errMessage, "The trace has to be into a subdirectly, like \"" + fMainPage.getInitialContainerString() + "/MyTrace\"" );
+ errMessage = fMainPage.extendErrorMessage(errMessage, "");
+ errMessage = fMainPage.extendErrorMessage(errMessage, "Please change the destination folder.");
+ fMainPage.showVersionErrorPopup(errMessage);
+
+ return false;
+ }
+
+ return fMainPage.finish();
+ }
+
+ @Override
+ public boolean canFinish() {
+ return fMainPage.isSelectedElementsValidLttngTraces();
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.dialogs;
+
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.linuxtools.lttng.LttngException;
+import org.eclipse.linuxtools.lttng.trace.LTTngTraceVersion;
+import org.eclipse.linuxtools.lttng.ui.views.project.handlers.TraceErrorHandler;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngProjectNode;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.internal.wizards.datatransfer.WizardFileSystemResourceImportPage1;
+
+/**
+ * <b><u>ImportTraceWizardPage</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+@SuppressWarnings("restriction")
+public class ImportTraceWizardPage extends WizardFileSystemResourceImportPage1 {
+
+ private boolean isContainerSet = false;
+ private String initialContainerString = "";
+ private String selectedSourceDirectory = "";
+
+ public ImportTraceWizardPage(IWorkbench workbench, IStructuredSelection selection) {
+ super(workbench, selection);
+
+ LTTngProjectNode folder = (LTTngProjectNode) selection.getFirstElement();
+ String path = folder.getTracesFolder().getFolder().getFullPath().toOSString();
+
+ initialContainerString = path;
+ setContainerFieldValue(path);
+ }
+
+
+ public String getTraceDirectory() {
+ String tmpPath = "";
+ if ( (getSourceDirectory() != null) && (getSourceDirectory().getName() != null) ) {
+ tmpPath = this.getSourceDirectory().getName().toString();
+ }
+
+ return tmpPath;
+ }
+
+ public String getInitialContainerString() {
+ return initialContainerString;
+ }
+
+ public String getTracepath() {
+ String tmpPath = "";
+ if ( (getSourceDirectory() != null) && (getSourceDirectory().getPath() != null) ) {
+ tmpPath = this.getSourceDirectory().getPath().toString();
+ }
+
+ return tmpPath;
+ }
+
+ public String getDestination() {
+ String returnPath = null;
+
+ if ( getContainerFullPath() != null ) {
+ returnPath = getContainerFullPath().toString();
+ }
+ return returnPath;
+ }
+
+ public boolean isSelectedElementsValidLttngTraces() {
+ boolean returnedValue = true;
+
+ // We don't want to test until something is selected
+ if ( selectionGroup.getCheckedElementCount() > 0 ) {
+
+ // We don't want to revalidate each time, only want a new directory is selected
+ if ( ! selectedSourceDirectory.equals(getSourceDirectory().getAbsolutePath().toString()) )
+ {
+ try {
+ if ( isPathLttngTrace( getSourceDirectory().getAbsolutePath() ) == false ) {
+ returnedValue = false;
+ selectedSourceDirectory = "";
+
+ String errMessage[] = { "Couldn't get LTTng version number for the path : " };
+ errMessage = extendErrorMessage(errMessage, getSourceDirectory().getAbsolutePath() );
+ errMessage = extendErrorMessage(errMessage, "");
+ errMessage = extendErrorMessage(errMessage, "Verify that the directory is a valid LTTng trace directory.");
+ errMessage = extendErrorMessage(errMessage, "Make sure the top directory is the trace itself and not any of its parent.");
+ showVersionErrorPopup(errMessage);
+ selectionGroup.setAllSelections(false);
+ }
+ else {
+ selectedSourceDirectory = getSourceDirectory().getAbsolutePath();
+
+ if ( isContainerSet == false ) {
+ isContainerSet = true;
+
+ if ( ! getDestination().toString().equals( getInitialContainerString() + "/" + getTraceDirectory() ) ) {
+ // *** HACK ***
+ // Force a sane destination to avoid imported files to end up in the root of the "Traces/" directory
+ setContainerFieldValue(getInitialContainerString() + "/" + getTraceDirectory());
+ }
+ }
+ }
+ }
+ catch (LttngException e) {
+ String[] errorMessages = e.toString().split("\n");
+ String exceptionMessage[] = { "Version check failed for the path : ", this.getTracepath(), "", "Returned error was :" };
+
+ for ( int pos=0; pos<errorMessages.length; pos++) {
+ exceptionMessage = extendErrorMessage(exceptionMessage, errorMessages[pos]);
+ }
+
+ showVersionErrorPopup(exceptionMessage);
+ selectionGroup.setAllSelections(false);
+ returnedValue = false;
+ }
+ }
+ }
+ isContainerSet = false;
+
+ return returnedValue;
+ }
+
+
+ public boolean isPathLttngTrace(String path) throws LttngException {
+
+ boolean returnedValue = true;
+
+ // Ask for a LttngTraceVersion for the given path
+ LTTngTraceVersion traceVersion = new LTTngTraceVersion( path );
+
+ // If this is not a valid LTTng trace
+ if ( traceVersion.isValidLttngTrace() == false ) {
+ returnedValue = false;
+ }
+
+ return returnedValue;
+ }
+
+
+ public String[] extendErrorMessage(String[] oldErrorMessage, String lineToAdd) {
+ String tmSwapMessage[] = new String[oldErrorMessage.length + 1];
+ for ( int pos = 0; pos<oldErrorMessage.length; pos++) {
+ tmSwapMessage[pos] = oldErrorMessage[pos];
+ }
+ tmSwapMessage[oldErrorMessage.length] = lineToAdd;
+
+ return tmSwapMessage;
+ }
+
+
+ /**
+ * This function will show a version error popup that contain the given message.
+ *
+ */
+ public void showVersionErrorPopup(String[] errMessages) {
+ TraceErrorHandler errorDialog = new TraceErrorHandler(errMessages);
+ try {
+ errorDialog.execute(null);
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+
+// // *** HACK HACK AND HACK ***
+// // Everything below is a proof of concept on how we could tweak the import wizard to act according to our plan
+// // Uncomment everything below if you want to test it, but please, does not put any of this into production
+// @SuppressWarnings({ "unchecked", "rawtypes" })
+// @Override
+// public boolean finish() {
+// if (!ensureSourceIsValid()) {
+// return false;
+// }
+// saveWidgetValues();
+//
+// Iterator resourcesEnum = getSelectedResources().iterator();
+// List listRealFiles = new ArrayList();
+//
+// // ****
+// // HACK #1 :
+// // We need to convert everything into java.io.File because ImportOperation does NOT support FileSystemElement
+// while (resourcesEnum.hasNext()) {
+// FileSystemElement tmpFileElement = ((FileSystemElement)resourcesEnum.next());
+// java.io.File tmpRealFile = new java.io.File(tmpFileElement.getFileSystemObject().toString());
+//
+// listRealFiles.add(tmpRealFile);
+// }
+//
+// if (listRealFiles.size() > 0) {
+// // Call import ressources (code is below)
+// return importResources(listRealFiles);
+// }
+//
+// MessageDialog.openInformation(getContainer().getShell(),
+// DataTransferMessages.DataTransfer_information,
+// DataTransferMessages.FileImport_noneSelected);
+// return false;
+// }
+//
+// @Override
+// protected boolean importResources(List fileSystemObjects) {
+// // *** Explanation of the hackssss
+// // We want the import wizard to import everything in the form of :
+// // trace1/ -> tracefiles*
+// //
+// // However, the wizard is too dumb to do the following and will recreate the full architecture the user selected.
+// // So, depending what the user select, we could end up with something like :
+// // home/user/somewhere/trace1/ -> tracefiles*
+// //
+// // Since there is nothing to do with that, we need to change the "source" and the "to-import files" to reflect this.
+// // Basically, from the case above, the "source" should be changed to "trace1/" and "to-import files"
+// // should have the correct parent so the wizard can still find them
+// //
+// // Let's see how fun it is to do with mr. import wizard.
+//
+//
+// List listRealFilesShortPath = new ArrayList();
+// java.io.File newFullSource = getSourceDirectory();
+//
+// // We will loop for every "to-import full path files" we have and recreate "short path" files
+// // Mean, the current path of the file is currently something like :
+// // Path : /home/billybob/mytraces/trace1/metadata_0 Parent : null
+// // And we want something less dumb like :
+// // Path : metadata_0 Parent : /home/billybob/mytraces/trace1/
+// for (int pos=0; pos<fileSystemObjects.size(); pos++) {
+// java.io.File oldFile = (java.io.File)fileSystemObjects.get(pos);
+// java.io.File newShortPathFile = oldFile;
+//
+// // ***
+// // HACK #2 : We need to ajust the source of the files!
+// // Our current source is probably like :
+// // (Source) Path : / (or null?)
+// // (Files) Path : /home/billybob/mytraces/trace1/metadata_0 Parent : null
+// // We want something like :
+// // (Source) Path : /home/billybob/mytraces/trace1/
+// // (Files) Path : metadata_0 Parent : /home/billybob/mytraces/trace1/
+// //
+// // *BUG : However, we might need MULTIPLE sources since we could have MULTIPLE traces selected...
+// // THIS IS NOT HANDLED YET.
+//
+// // Make a new path like -> /home/billybob/mytraces/trace1/
+// String newParent = oldFile.getAbsolutePath().substring(0, oldFile.getAbsolutePath().lastIndexOf("/") );
+//
+// // Create a "short path file" with the good parent from it. This give :
+// // (Files) Path : metadata_0 Parent : /home/billybob/mytraces/trace1/
+// newShortPathFile = new java.io.File(newParent, oldFile.getName() );
+//
+// // Create a new "full source" directory -> /home/billybob/mytraces/trace1/
+// newFullSource = new java.io.File( newParent );
+//
+// // Add our pretty file to the new List
+// listRealFilesShortPath.add(newShortPathFile);
+// }
+//
+// // ***
+// // HACK #3
+// // Now that we have everything, we need to AJUST THE DESTINATION
+// // To do so, we ajust the "ContainerValue" text field.
+// //
+// // Right now we have something like :
+// // Path -> /where/to/import/
+// // (Files) Path : metadata_0 Parent : /home/billybob/mytraces/trace1/
+// // We want something like :
+// // Path -> /where/to/import/trace1/
+// // (Files) Path : metadata_0 Parent : /home/billybob/mytraces/trace1/
+// //
+//
+// // We take the current text field and we add the "full source" name
+// // Note : the "name" is the last directory name so "trace1" is returned for a path like "/home/billybob/mytraces/trace1/"
+// setContainerFieldValue(getContainerFullPath() + "/" + newFullSource.getName());
+//
+// /*
+// System.out.println("\n\n" + getContainerFullPath());
+// System.out.println(newFullSource);
+// System.out.println(FileSystemStructureProvider.INSTANCE);
+// System.out.println(this.getContainer());
+// System.out.println(fileSystemObjects);
+// */
+//
+// // Finally import !!
+// ImportOperation operation = new ImportOperation(getContainerFullPath(), newFullSource, FileSystemStructureProvider.INSTANCE, this, listRealFilesShortPath);
+//
+// operation.setContext(getShell());
+// return executeImportOperation(operation);
+// }
+//
+// // This function test if the selected directory are LTTng traces
+// // This one is made to work with the madness above.
+// public boolean isSelectedElementsValidLttngTraces() {
+// boolean returnedValue = true;
+//
+// String errMessage[] = { "Couldn't get LTTng version number for the path : " };
+//
+// // We don't want to test until something is selected
+// if ( selectionGroup.getCheckedElementCount() > 0 ) {
+// try {
+// List<MinimizedFileSystemElement> selectionList = selectionGroup.getAllWhiteCheckedItems();
+// MinimizedFileSystemElement tmpSelectedElement = null;
+//
+// for ( int x=0; x<selectionList.size(); x++) {
+// tmpSelectedElement = selectionList.get(x);
+//
+// // *** VERIFY ***
+// // Not sure ALL directory are checked.
+// if ( tmpSelectedElement.isDirectory() ) {
+// String tmpPath = tmpSelectedElement.getFileSystemObject().toString();
+// if ( isPathLttngTrace( tmpPath ) == false ) {
+// returnedValue = false;
+// errMessage = extendErrorMessage(errMessage, tmpPath);
+// }
+// }
+// }
+//
+// if ( returnedValue == false ) {
+// errMessage = extendErrorMessage(errMessage, "");
+// errMessage = extendErrorMessage(errMessage, "Verify that the directory is a valid LTTng trace directory.");
+// showVersionErrorPopup(errMessage);
+// selectionGroup.setAllSelections(false);
+// }
+// }
+// catch (LttngException e) {
+// String exceptionMessage[] = { "Version check failed for the path : ", this.getTracepath(), "", "Returned error was :", e.toString() };
+// showVersionErrorPopup(exceptionMessage);
+// selectionGroup.setAllSelections(false);
+// returnedValue = false;
+// }
+// }
+//
+// return returnedValue;
+// }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.dialogs;
+
+import java.lang.reflect.InvocationTargetException;
+import java.net.URI;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngExperimentFolderNode;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.actions.WorkspaceModifyOperation;
+import org.eclipse.ui.dialogs.SelectionStatusDialog;
+import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
+import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
+import org.eclipse.ui.internal.ide.dialogs.CreateLinkedResourceGroup;
+
+/**
+ * NewExperimentDialog
+ *
+ * This is stripped down version of NewFolderDialog.
+ */
+@SuppressWarnings("restriction")
+public class NewExperimentDialog extends SelectionStatusDialog {
+
+ private Text folderNameField;
+ private IContainer container;
+ private boolean firstLinkCheck = true;
+ private CreateLinkedResourceGroup linkedResourceGroup;
+
+ /**
+ * Creates a NewFolderDialog
+ *
+ * @param parentShell parent of the new dialog
+ * @param container parent of the new folder
+ */
+ public NewExperimentDialog(Shell parentShell, LTTngExperimentFolderNode experimentFolder) {
+ super(parentShell);
+ this.container = experimentFolder.getFolder();
+ setTitle("LTTng Experiment");
+ setStatusLineAboveButtons(true);
+ }
+
+ /**
+ * Creates the folder using the name and link target entered by the user.
+ * Sets the dialog result to the created folder.
+ */
+ @Override
+ protected void computeResult() {
+ }
+
+ /**
+ * @see org.eclipse.jface.window.Window#create()
+ */
+ @Override
+ public void create() {
+ super.create();
+ getButton(IDialogConstants.OK_ID).setEnabled(false);
+ }
+
+ /**
+ * Creates the widget for advanced options.
+ *
+ * @param parent the parent composite
+ */
+ protected void createLinkResourceGroup(Composite parent) {
+ linkedResourceGroup = new CreateLinkedResourceGroup(IResource.FOLDER,
+ new Listener() {
+ public void handleEvent(Event e) {
+ validateLinkedResource();
+ firstLinkCheck = false;
+ }
+ }, new CreateLinkedResourceGroup.IStringValue() {
+ public void setValue(String string) {
+ folderNameField.setText(string);
+ }
+
+ public String getValue() {
+ return folderNameField.getText();
+ }
+
+ public IResource getResource() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ });
+ }
+
+ /* (non-Javadoc)
+ * Method declared on Dialog.
+ */
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ Composite composite = (Composite) super.createDialogArea(parent);
+ composite.setLayout(new GridLayout());
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ createFolderNameGroup(composite);
+ createLinkResourceGroup(composite);
+ return composite;
+ }
+
+ /**
+ * Creates the folder name specification controls.
+ *
+ * @param parent the parent composite
+ */
+ private void createFolderNameGroup(Composite parent) {
+ Font font = parent.getFont();
+ Composite folderGroup = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ folderGroup.setLayout(layout);
+ folderGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ // new folder label
+ Label folderLabel = new Label(folderGroup, SWT.NONE);
+ folderLabel.setFont(font);
+ folderLabel.setText("Experiment name: ");
+
+ // new folder name entry field
+ folderNameField = new Text(folderGroup, SWT.BORDER);
+ GridData data = new GridData(GridData.FILL_HORIZONTAL);
+ data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH;
+ folderNameField.setLayoutData(data);
+ folderNameField.setFont(font);
+ folderNameField.addListener(SWT.Modify, new Listener() {
+ public void handleEvent(Event event) {
+ validateLinkedResource();
+ }
+ });
+ }
+
+ /**
+ * Creates a folder resource handle for the folder with the given name.
+ * The folder handle is created relative to the container specified during
+ * object creation.
+ *
+ * @param folderName the name of the folder resource to create a handle for
+ * @return the new folder resource handle
+ */
+ private IFolder createFolderHandle(String folderName) {
+ IWorkspaceRoot workspaceRoot = container.getWorkspace().getRoot();
+ IPath folderPath = container.getFullPath().append(folderName);
+ IFolder folderHandle = workspaceRoot.getFolder(folderPath);
+
+ return folderHandle;
+ }
+
+ /**
+ * Creates a new folder with the given name and optionally linking to
+ * the specified link target.
+ *
+ * @param folderName name of the new folder
+ * @param linkTarget name of the link target folder. may be null.
+ * @return IFolder the new folder
+ */
+ private IFolder createNewFolder(String folderName, final URI linkTarget) {
+ final IFolder folderHandle = createFolderHandle(folderName);
+
+ WorkspaceModifyOperation operation = new WorkspaceModifyOperation() {
+ @Override
+ public void execute(IProgressMonitor monitor) throws CoreException {
+ try {
+ monitor.beginTask(IDEWorkbenchMessages.NewFolderDialog_progress, 2000);
+ if (monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ if (linkTarget == null) {
+ folderHandle.create(false, true, monitor);
+ } else {
+ folderHandle.createLink(linkTarget, IResource.ALLOW_MISSING_LOCAL, monitor);
+ }
+ if (monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ } finally {
+ monitor.done();
+ }
+ }
+ };
+ try {
+ PlatformUI.getWorkbench().getProgressService().busyCursorWhile(operation);
+ } catch (InterruptedException exception) {
+ return null;
+ } catch (InvocationTargetException exception) {
+ if (exception.getTargetException() instanceof CoreException) {
+ ErrorDialog.openError(getShell(),
+ IDEWorkbenchMessages.NewFolderDialog_errorTitle, null, // no special message
+ ((CoreException) exception.getTargetException()).getStatus());
+ } else {
+ // CoreExceptions are handled above, but unexpected runtime exceptions and errors may still occur.
+ IDEWorkbenchPlugin.log(getClass(),
+ "createNewExperiment", exception.getTargetException());
+ MessageDialog.openError(getShell(),
+ IDEWorkbenchMessages.NewFolderDialog_errorTitle,
+ NLS.bind(IDEWorkbenchMessages.NewFolderDialog_internalError,
+ exception.getTargetException().getMessage()));
+ }
+ return null;
+ }
+ return folderHandle;
+ }
+
+ /**
+ * Update the dialog's status line to reflect the given status. It is safe to call
+ * this method before the dialog has been opened.
+ */
+ @Override
+ protected void updateStatus(IStatus status) {
+ if (firstLinkCheck && status != null) {
+ Status newStatus = new Status(IStatus.OK, status.getPlugin(),
+ status.getCode(), status.getMessage(), status.getException());
+ super.updateStatus(newStatus);
+ } else {
+ super.updateStatus(status);
+ }
+ }
+
+ /**
+ * Update the dialog's status line to reflect the given status. It is safe to call
+ * this method before the dialog has been opened.
+ * @param severity
+ * @param message
+ */
+ private void updateStatus(int severity, String message) {
+ updateStatus(new Status(severity, IDEWorkbenchPlugin.IDE_WORKBENCH, severity, message, null));
+ }
+
+ /**
+ * Checks whether the folder name and link location are valid.
+ * Disable the OK button if the folder name and link location are valid.
+ * a message that indicates the problem otherwise.
+ */
+ private void validateLinkedResource() {
+ boolean valid = validateFolderName();
+
+ if (valid) {
+ IFolder linkHandle = createFolderHandle(folderNameField.getText());
+ IStatus status = linkedResourceGroup.validateLinkLocation(linkHandle);
+
+ if (status.getSeverity() != IStatus.ERROR) {
+ getOkButton().setEnabled(true);
+ } else {
+ getOkButton().setEnabled(false);
+ }
+
+ if (status.isOK() == false) {
+ updateStatus(status);
+ }
+ } else {
+ getOkButton().setEnabled(false);
+ }
+ }
+
+ /**
+ * Checks if the folder name is valid.
+ *
+ * @return null if the new folder name is valid.
+ * a message that indicates the problem otherwise.
+ */
+ private boolean validateFolderName() {
+ String name = folderNameField.getText();
+ IWorkspace workspace = container.getWorkspace();
+ IStatus nameStatus = workspace.validateName(name, IResource.FOLDER);
+
+ if ("".equals(name)) {
+ updateStatus(IStatus.ERROR, "Experiment name is empty");
+ return false;
+ }
+ if (nameStatus.isOK() == false) {
+ updateStatus(nameStatus);
+ return false;
+ }
+ IPath path = new Path(name);
+ if (container.getFolder(path).exists()
+ || container.getFile(path).exists()) {
+ updateStatus(IStatus.ERROR, NLS.bind("Experiment already exists", name));
+ return false;
+ }
+ updateStatus(IStatus.OK, "");
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.dialogs.SelectionStatusDialog#okPressed()
+ */
+ @Override
+ protected void okPressed() {
+ URI linkTarget = linkedResourceGroup.getLinkTargetURI();
+ IFolder folder = createNewFolder(folderNameField.getText(), linkTarget);
+ if (folder == null) {
+ return;
+ }
+
+ setSelectionResult(new IFolder[] { folder });
+
+ super.okPressed();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.dialogs;
+
+import org.eclipse.ui.dialogs.WizardNewProjectCreationPage;
+
+/**
+ * <b><u>NewProjectMainWizardPage</u></b>
+ * <p>
+ *
+ * TODO: Implement me. Please.
+ */
+public class NewProjectMainWizardPage extends WizardNewProjectCreationPage {
+
+ /**
+ * @param pageName
+ */
+ public NewProjectMainWizardPage(String pageName) {
+ super(pageName);
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.dialogs;
+
+import java.net.URI;
+
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.linuxtools.lttng.ui.LTTngUiPlugin;
+import org.eclipse.linuxtools.lttng.ui.views.project.LTTngProjectNature;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngProjectNode;
+import org.eclipse.ui.wizards.newresource.BasicNewResourceWizard;
+
+/**
+ * <b><u>NewProjectWizard</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+public class NewProjectWizard extends BasicNewResourceWizard {
+
+ private String fTtitle;
+ private String fDescription;
+
+ protected NewProjectMainWizardPage fMainPage;
+ protected String fProjectName;
+ protected URI fProjectLocation;
+ protected IConfigurationElement fConfigElement;
+
+ protected IProject fProject;
+
+ /**
+ *
+ */
+ public NewProjectWizard() {
+ this("LTTng Project", "Create an LTTng Project");
+ }
+
+ /**
+ * @param title
+ * @param desc
+ */
+ public NewProjectWizard(String title, String desc) {
+ super();
+ setDialogSettings(LTTngUiPlugin.getDefault().getDialogSettings());
+ setNeedsProgressMonitor(true);
+ setForcePreviousAndNextButtons(true);
+ setWindowTitle(title);
+ fTtitle = title;
+ fDescription = desc;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.wizard.Wizard#addPages()
+ */
+ @Override
+ public void addPages() {
+ fMainPage= new NewProjectMainWizardPage("LTTng Project");
+ fMainPage.setTitle(fTtitle);
+ fMainPage.setDescription(fDescription);
+ addPage(fMainPage);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.wizard.Wizard#performCancel()
+ */
+ @Override
+ public boolean performCancel() {
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.wizard.Wizard#performFinish()
+ */
+ @Override
+ public boolean performFinish() {
+ fProjectName = fMainPage.getProjectName();
+ fProjectLocation = fMainPage.useDefaults() ? null : fMainPage.getLocationURI();
+ fProject = createProject(fProjectName, fProjectLocation, new NullProgressMonitor());
+ return true;
+ }
+
+ public IProject getProject() {
+ return fProject;
+ }
+
+ /**
+ * @param projectName
+ * @param projectLocation
+ * @param monitor
+ * @return
+ */
+ private IProject createProject(String projectName, URI projectLocation, IProgressMonitor monitor) {
+
+ IWorkspace workspace = ResourcesPlugin.getWorkspace();
+ IWorkspaceRoot root = workspace.getRoot();
+ IProject project = root.getProject(projectName);
+
+ try {
+ if (!project.exists()) {
+ IProjectDescription description = workspace.newProjectDescription(project.getName());
+ if (projectLocation != null)
+ description.setLocationURI(projectLocation);
+ project.create(description, monitor);
+ }
+
+ if (!project.isOpen())
+ project.open(monitor);
+
+ IProjectDescription description = project.getDescription();
+ description.setNatureIds(new String[] { LTTngProjectNature.ID } );
+ project.setDescription(description, null);
+
+ IFolder folder = project.getFolder(LTTngProjectNode.TRACE_FOLDER_NAME);
+ if (!folder.exists())
+ folder.create(true, true, null);
+
+ folder = project.getFolder(LTTngProjectNode.EXPER_FOLDER_NAME);
+ if (!folder.exists())
+ folder.create(true, true, null);
+
+ return project;
+ }
+ catch (CoreException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+package org.eclipse.linuxtools.lttng.ui.views.project.dialogs;
+
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * William Bourque - Initial API and implementation
+ *******************************************************************************/
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.dialogs.SelectionStatusDialog;
+
+public class TraceErrorDialog extends SelectionStatusDialog {
+
+ private String[] messages = null;
+
+ public TraceErrorDialog(Shell parentShell, String[] newMessages) {
+ super(parentShell);
+
+ messages = newMessages;
+ setTitle("Trace Selection");
+ setStatusLineAboveButtons(true);
+ }
+
+ @Override
+ protected void computeResult() {
+ }
+
+ @Override
+ public void create() {
+ super.create();
+ getButton(IDialogConstants.OK_ID).setEnabled(true);
+ getButton(IDialogConstants.OK_ID).setAlignment(GridData.CENTER);
+ getButton(IDialogConstants.CANCEL_ID).setVisible(false);
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ Composite composite = (Composite) super.createDialogArea(parent);
+ composite.setLayout(new GridLayout());
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ createFolderNameGroup(composite);
+ return composite;
+ }
+
+ private void createFolderNameGroup(Composite parent) {
+ Font font = parent.getFont();
+ Composite folderGroup = new Composite(parent, SWT.NONE);
+
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 1;
+ layout.verticalSpacing = 3;
+ folderGroup.setLayout(layout);
+ folderGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+
+ // Position grid for the messages
+ GridData positionningData = new GridData(GridData.FILL_VERTICAL);
+
+ // New message label
+ Label lblMessage = new Label(folderGroup, SWT.NONE);
+ lblMessage.setFont(font);
+ lblMessage.setText("Error while opening the trace! Error message was : ");
+ lblMessage.setLayoutData(positionningData);
+
+ // The actual messages
+ GC graphicContext = new GC(parent);
+ String longuestLine = "";
+ int msgSize = 0;
+
+ // *** Font and FontData are nowhere near elegant to use.
+ Font errorFont = new Font(graphicContext.getDevice(), font.getFontData()[0].getName(), font.getFontData()[0].getHeight(), SWT.ITALIC);
+
+ Label[] lblErrorMessages = new Label[messages.length];
+ for(int x=0; x<messages.length; x++) {
+ lblErrorMessages[x] = new Label(folderGroup, SWT.NONE);
+ lblErrorMessages[x].setFont(errorFont);
+
+ lblErrorMessages[x].setForeground(new Color(lblErrorMessages[x].getForeground().getDevice(), 255, 0, 0));
+ lblErrorMessages[x].setText(messages[x]);
+ lblErrorMessages[x].setLayoutData(positionningData);
+
+ if ( messages[x].length() > longuestLine.length() ) {
+ longuestLine = messages[x];
+ }
+ }
+
+ for ( int pos=0; pos<longuestLine.length(); pos++ ) {
+ msgSize += graphicContext.getAdvanceWidth( longuestLine.charAt(pos) );
+ }
+ // Seems we need to count the final \n of the line otherwise we miss some space
+ msgSize += graphicContext.getAdvanceWidth( '\n' );
+
+ positionningData.widthHint = msgSize;
+ positionningData.grabExcessHorizontalSpace = true;
+
+ graphicContext.dispose();
+
+ }
+
+
+ @Override
+ protected void updateStatus(IStatus status) {
+ if (status != null) {
+ Status newStatus = new Status(IStatus.OK, status.getPlugin(),
+ status.getCode(), status.getMessage(), status.getException());
+ super.updateStatus(newStatus);
+ } else {
+ super.updateStatus(status);
+ }
+ }
+
+ @Override
+ protected void okPressed() {
+ super.okPressed();
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.handlers;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.core.commands.IHandlerListener;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.linuxtools.lttng.ui.views.project.ProjectView;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngProjectNode;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * <b><u>CloseProjectHandler</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+public class CloseProjectHandler implements IHandler {
+
+ private LTTngProjectNode fProject = null;
+
+ // ------------------------------------------------------------------------
+ // Validation
+ // ------------------------------------------------------------------------
+
+ public boolean isEnabled() {
+
+ // Check if we are closing down
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null)
+ return false;
+
+ // Check if we are in the Project View
+ IWorkbenchPage page = window.getActivePage();
+ if (!(page.getActivePart() instanceof ProjectView))
+ return false;
+
+ // Check if a project is selected
+ ISelection selection = page.getSelection(ProjectView.ID);
+ if (selection instanceof StructuredSelection) {
+ Object element = ((StructuredSelection) selection).getFirstElement();
+ fProject = (element instanceof LTTngProjectNode) ? (LTTngProjectNode) element : null;
+ }
+ return (fProject != null && fProject.isOpen());
+ }
+
+ // Handled if we are in the ProjectView
+ public boolean isHandled() {
+ return true;
+ }
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ if (fProject != null) {
+ fProject.closeProject();
+ fProject.refresh();
+ }
+ return null;
+ }
+
+ public void dispose() {
+ // TODO Auto-generated method stub
+ }
+
+ // ------------------------------------------------------------------------
+ // IHandlerListener
+ // ------------------------------------------------------------------------
+
+ public void addHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+ public void removeHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.handlers;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.core.commands.IHandlerListener;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.linuxtools.lttng.ui.views.project.ProjectView;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.ILTTngProjectTreeNode;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngExperimentNode;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * <b><u>DeleteExperimentHandler</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+public class DeleteExperimentHandler implements IHandler {
+
+ private LTTngExperimentNode fExperiment = null;
+
+ // ------------------------------------------------------------------------
+ // Validation
+ // ------------------------------------------------------------------------
+
+ public boolean isEnabled() {
+
+ // Check if we are closing down
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null)
+ return false;
+
+ // Check if a trace is selected
+ IWorkbenchPage page = window.getActivePage();
+ if (!(page.getActivePart() instanceof ProjectView))
+ return false;
+
+ // Check if a trace is selected
+ ISelection selection = page.getSelection(ProjectView.ID);
+ if (selection instanceof StructuredSelection) {
+ Object element = ((StructuredSelection) selection).getFirstElement();
+ fExperiment = (element instanceof LTTngExperimentNode) ? (LTTngExperimentNode) element : null;
+ }
+
+ return (fExperiment != null);
+ }
+
+ // Handled if we are in the ProjectView
+ public boolean isHandled() {
+ return true;
+ }
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ IFolder folder = fExperiment.getFolder();
+ ILTTngProjectTreeNode parent = fExperiment.getParent();
+ try {
+ parent.removeChild(fExperiment);
+ parent.refresh();
+ folder.delete(true, true, null);
+ } catch (CoreException e) {
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ public void dispose() {
+ // TODO Auto-generated method stub
+ }
+
+ // ------------------------------------------------------------------------
+ // IHandlerListener
+ // ------------------------------------------------------------------------
+
+ public void addHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+ public void removeHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.handlers;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.core.commands.IHandlerListener;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.linuxtools.lttng.ui.views.project.ProjectView;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.ILTTngProjectTreeNode;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngProjectNode;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * <b><u>DeleteProjectHandler</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+public class DeleteProjectHandler implements IHandler {
+
+ private LTTngProjectNode fProject = null;
+
+ // ------------------------------------------------------------------------
+ // Validation
+ // ------------------------------------------------------------------------
+
+ public boolean isEnabled() {
+
+ // Check if we are closing down
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null)
+ return false;
+
+ // Check if we are in the Project View
+ IWorkbenchPage page = window.getActivePage();
+ if (!(page.getActivePart() instanceof ProjectView))
+ return false;
+
+ // Check if a project is selected
+ ISelection selection = page.getSelection(ProjectView.ID);
+ if (selection instanceof StructuredSelection) {
+ Object element = ((StructuredSelection) selection).getFirstElement();
+ fProject = (element instanceof LTTngProjectNode) ? (LTTngProjectNode) element : null;
+ }
+ return (fProject != null);
+ }
+
+ // Handled if we are in the ProjectView
+ public boolean isHandled() {
+ return true;
+ }
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ IProject project = fProject.getProject();
+ ILTTngProjectTreeNode parent = fProject.getParent();
+ try {
+ parent.removeChild(fProject);
+ parent.refresh();
+ project.delete(true, true, null);
+ } catch (CoreException e) {
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ public void dispose() {
+ // TODO Auto-generated method stub
+ }
+
+ // ------------------------------------------------------------------------
+ // IHandlerListener
+ // ------------------------------------------------------------------------
+
+ public void addHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+ public void removeHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.handlers;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.core.commands.IHandlerListener;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.linuxtools.lttng.ui.views.project.ProjectView;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.ILTTngProjectTreeNode;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngTraceNode;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * <b><u>DeleteTraceHandler</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+public class DeleteTraceHandler implements IHandler {
+
+ private LTTngTraceNode fTrace = null;
+
+ // ------------------------------------------------------------------------
+ // Validation
+ // ------------------------------------------------------------------------
+
+ public boolean isEnabled() {
+
+ // Check if we are closing down
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null)
+ return false;
+
+ // Check if a trace is selected
+ IWorkbenchPage page = window.getActivePage();
+ if (!(page.getActivePart() instanceof ProjectView))
+ return false;
+
+ // Check if a trace is selected
+ ISelection selection = page.getSelection(ProjectView.ID);
+ if (selection instanceof StructuredSelection) {
+ Object element = ((StructuredSelection) selection).getFirstElement();
+ fTrace = (element instanceof LTTngTraceNode) ? (LTTngTraceNode) element : null;
+ }
+
+ return (fTrace != null);
+ }
+
+ // Handled if we are in the ProjectView
+ public boolean isHandled() {
+ return true;
+ }
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ IFolder folder = fTrace.getFolder();
+ ILTTngProjectTreeNode parent = fTrace.getParent();
+ try {
+ parent.removeChild(fTrace);
+ parent.refresh();
+ folder.delete(true, true, null);
+ } catch (CoreException e) {
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ public void dispose() {
+ // TODO Auto-generated method stub
+ }
+
+ // ------------------------------------------------------------------------
+ // IHandlerListener
+ // ------------------------------------------------------------------------
+
+ public void addHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+ public void removeHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.handlers;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.core.commands.IHandlerListener;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.linuxtools.lttng.ui.views.project.ProjectView;
+import org.eclipse.linuxtools.lttng.ui.views.project.dialogs.ImportTraceWizard;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.ILTTngProjectTreeNode;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngProjectNode;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * <b><u>ImportTraceHandler</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+public class ImportTraceHandler implements IHandler {
+
+ private LTTngProjectNode fProject = null;
+
+ // ------------------------------------------------------------------------
+ // Validation
+ // ------------------------------------------------------------------------
+
+ public boolean isEnabled() {
+
+ // Check if we are closing down
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null)
+ return false;
+
+ // Check if we are in the Project View
+ IWorkbenchPage page = window.getActivePage();
+ if (!(page.getActivePart() instanceof ProjectView))
+ return false;
+
+ // Check if a project is selected
+ ISelection selection = page.getSelection(ProjectView.ID);
+ if (selection instanceof StructuredSelection) {
+ Object element = ((StructuredSelection) selection).getFirstElement();
+ if (element instanceof ILTTngProjectTreeNode) {
+ ILTTngProjectTreeNode node = (ILTTngProjectTreeNode) element;
+ while (node != null && !(node instanceof LTTngProjectNode)) {
+ node = node.getParent();
+ }
+ fProject = (node instanceof LTTngProjectNode) ? (LTTngProjectNode) node : null;
+ }
+ }
+
+ return (fProject != null && fProject.isOpen() && fProject.isLTTngProject());
+ }
+
+ // Always handled
+ public boolean isHandled() {
+ return true;
+ }
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ // Set the selection to the project
+ IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ ProjectView view = (ProjectView) page.getActivePart();
+ view.setSelection(fProject);
+
+ // Fire the Import Trace Wizard
+ IWorkbench workbench = PlatformUI.getWorkbench();
+ Shell shell = workbench.getActiveWorkbenchWindow().getShell();
+
+ ImportTraceWizard wizard = new ImportTraceWizard();
+ wizard.init(PlatformUI.getWorkbench(), new StructuredSelection(fProject));
+ WizardDialog dialog = new WizardDialog(shell, wizard);
+ dialog.open();
+
+ if (dialog.getReturnCode() == Window.OK && fProject != null) {
+ fProject.refreshChildren();
+ fProject.refresh();
+ }
+
+ return null;
+ }
+
+ public void dispose() {
+ // TODO Auto-generated method stub
+ }
+
+ // ------------------------------------------------------------------------
+ // IHandlerListener
+ // ------------------------------------------------------------------------
+
+ public void addHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+ public void removeHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.handlers;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.core.commands.IHandlerListener;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.window.Window;
+import org.eclipse.linuxtools.lttng.ui.views.project.ProjectView;
+import org.eclipse.linuxtools.lttng.ui.views.project.dialogs.NewExperimentDialog;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.ILTTngProjectTreeNode;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngExperimentFolderNode;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngProjectNode;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * <b><u>NewExperimentHandler</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+public class NewExperimentHandler implements IHandler {
+
+ private LTTngProjectNode fProject = null;
+
+ // ------------------------------------------------------------------------
+ // Validation
+ // ------------------------------------------------------------------------
+
+ public boolean isEnabled() {
+
+ // Check if we are closing down
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null)
+ return false;
+
+ // Check if we are in the Project View
+ IWorkbenchPage page = window.getActivePage();
+ if (!(page.getActivePart() instanceof ProjectView))
+ return false;
+
+ // Check if a project is selected
+ ISelection selection = page.getSelection(ProjectView.ID);
+ if (selection instanceof StructuredSelection) {
+ Object element = ((StructuredSelection) selection).getFirstElement();
+ if (element instanceof ILTTngProjectTreeNode) {
+ ILTTngProjectTreeNode node = (ILTTngProjectTreeNode) element;
+ while (node != null && !(node instanceof LTTngProjectNode)) {
+ node = node.getParent();
+ }
+ fProject = (node instanceof LTTngProjectNode) ? (LTTngProjectNode) node : null;
+ }
+ }
+
+ return (fProject != null && fProject.isOpen() && fProject.isLTTngProject());
+ }
+
+ // Handled if we are in the ProjectView
+ public boolean isHandled() {
+ return true;
+ }
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ // Open the experiment creation dialog
+ LTTngExperimentFolderNode experimentFolder = fProject.getExperimentsFolder();
+ Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
+ NewExperimentDialog dialog = new NewExperimentDialog(shell, experimentFolder);
+ dialog.open();
+
+ if (dialog.getReturnCode() == Window.OK) {
+ Object[] experiments = dialog.getResult();
+ if (experiments[0] instanceof IFolder) {
+ experimentFolder.addExperiment((IFolder) experiments[0]);
+ }
+ }
+
+ return null;
+ }
+
+ public void dispose() {
+ // TODO Auto-generated method stub
+ }
+
+ // ------------------------------------------------------------------------
+ // IHandlerListener
+ // ------------------------------------------------------------------------
+
+ public void addHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+ public void removeHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.handlers;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.core.commands.IHandlerListener;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.linuxtools.lttng.ui.views.project.ProjectView;
+import org.eclipse.linuxtools.lttng.ui.views.project.dialogs.NewProjectWizard;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngProjectRoot;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * <b><u>NewProjectHandler</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+public class NewProjectHandler implements IHandler {
+
+ private LTTngProjectRoot fProjectRoot = null;
+
+ // ------------------------------------------------------------------------
+ // Validation
+ // ------------------------------------------------------------------------
+
+ public boolean isEnabled() {
+
+ // Check if we are closing down
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null)
+ return false;
+
+ // Check if we are in the Project View
+ IWorkbenchPart part = window.getActivePage().getActivePart();
+ if (!(part instanceof ProjectView))
+ return false;
+
+ fProjectRoot = ((ProjectView) part).getRoot();
+
+ return (fProjectRoot != null);
+ }
+
+ // Always handled
+ public boolean isHandled() {
+ return true;
+ }
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ // Fire the New Project Wizard
+ Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
+ NewProjectWizard wizard = new NewProjectWizard();
+ WizardDialog dialog = new WizardDialog(shell, wizard);
+ dialog.open();
+
+ // Update the project model
+ if (dialog.getReturnCode() == Window.OK) {
+ IProject project = wizard.getProject();
+ if (project != null && fProjectRoot != null) {
+ fProjectRoot.refreshChildren();
+ fProjectRoot.refresh();
+ }
+ }
+
+ return null;
+ }
+
+ public void dispose() {
+ // TODO Auto-generated method stub
+ }
+
+ // ------------------------------------------------------------------------
+ // IHandlerListener
+ // ------------------------------------------------------------------------
+
+ public void addHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+ public void removeHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.handlers;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.core.commands.IHandlerListener;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.linuxtools.lttng.ui.views.project.ProjectView;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngExperimentNode;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * <b><u>OpenExperimentHandler</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+public class OpenExperimentHandler implements IHandler {
+
+ private LTTngExperimentNode fExperiment = null;
+
+ // ------------------------------------------------------------------------
+ // Validation
+ // ------------------------------------------------------------------------
+
+ public boolean isEnabled() {
+ // Check if we are closing down
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null)
+ return false;
+
+ // Check if a trace is selected
+ IWorkbenchPage page = window.getActivePage();
+ if (!(page.getActivePart() instanceof ProjectView))
+ return false;
+
+ // Check if a trace is selected
+ ISelection selection = page.getSelection(ProjectView.ID);
+ if (selection instanceof StructuredSelection) {
+ Object element = ((StructuredSelection) selection).getFirstElement();
+ fExperiment = (element instanceof LTTngExperimentNode) ? (LTTngExperimentNode) element : null;
+ }
+
+ return (fExperiment != null);
+ }
+
+ // Handled if we are in the ProjectView
+ public boolean isHandled() {
+ return true;
+ }
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ // Set the selection to the project
+ IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ ProjectView projectView = (ProjectView) page.getActivePart();
+
+ if (projectView != null) {
+ projectView.selectExperiment(fExperiment);
+ }
+
+ return null;
+ }
+
+ // ------------------------------------------------------------------------
+ // IHandlerListener
+ // ------------------------------------------------------------------------
+
+ public void addHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+ public void removeHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+ public void dispose() {
+ // TODO Auto-generated method stub
+
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.handlers;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.core.commands.IHandlerListener;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.linuxtools.lttng.ui.views.project.ProjectView;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngProjectNode;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * <b><u>OpenProjectHandler</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+public class OpenProjectHandler implements IHandler {
+
+ private LTTngProjectNode fProject = null;
+
+ // ------------------------------------------------------------------------
+ // Validation
+ // ------------------------------------------------------------------------
+
+ public boolean isEnabled() {
+
+ // Check if we are closing down
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null)
+ return false;
+
+ // Check if we are in the Project View
+ IWorkbenchPage page = window.getActivePage();
+ if (!(page.getActivePart() instanceof ProjectView))
+ return false;
+
+ // Check if a project is selected
+ ISelection selection = page.getSelection(ProjectView.ID);
+ if (selection instanceof StructuredSelection) {
+ Object element = ((StructuredSelection) selection).getFirstElement();
+ fProject = (element instanceof LTTngProjectNode) ? (LTTngProjectNode) element : null;
+ }
+ return (fProject != null && !fProject.isOpen());
+ }
+
+ // Handled if we are in the ProjectView
+ public boolean isHandled() {
+ return true;
+ }
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ if (fProject != null) {
+ fProject.openProject();
+ fProject.refresh();
+ }
+ return null;
+ }
+
+ public void dispose() {
+ // TODO Auto-generated method stub
+ }
+
+ // ------------------------------------------------------------------------
+ // IHandlerListener
+ // ------------------------------------------------------------------------
+
+ public void addHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+ public void removeHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.handlers;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.core.commands.IHandlerListener;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngTraceNode;
+import org.eclipse.swt.widgets.MessageBox;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * <b><u>OpenTraceHandler</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+public class OpenTraceHandler implements IHandler {
+
+ private LTTngTraceNode fTrace = null;
+
+ // ------------------------------------------------------------------------
+ // Validation
+ // ------------------------------------------------------------------------
+
+ public boolean isEnabled() {
+ return (fTrace != null);
+ }
+
+ // Handled if we are in the ProjectView
+ public boolean isHandled() {
+ return true;
+ }
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ MessageBox mb = new MessageBox(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
+ mb.setText("Open Trace");
+ mb.setMessage("Not implemented yet");
+ mb.open();
+
+ return null;
+ }
+
+ public void dispose() {
+ // TODO Auto-generated method stub
+ }
+
+ // ------------------------------------------------------------------------
+ // IHandlerListener
+ // ------------------------------------------------------------------------
+
+ public void addHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+ public void removeHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.handlers;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.core.commands.IHandlerListener;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.linuxtools.lttng.ui.views.project.ProjectView;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.ILTTngProjectTreeNode;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngProjectRoot;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * <b><u>RefreshHandler</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+public class RefreshHandler implements IHandler {
+
+ private LTTngProjectRoot fProjectRoot = null;
+
+ // ------------------------------------------------------------------------
+ // Validation
+ // ------------------------------------------------------------------------
+
+ public boolean isEnabled() {
+
+ // Check if we are closing down
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null)
+ return false;
+
+ // Check if we can find the project model root node
+ ISelection selection = window.getActivePage().getSelection(ProjectView.ID);
+ if (selection instanceof StructuredSelection) {
+ Object element = ((StructuredSelection) selection).getFirstElement();
+ if (element instanceof ILTTngProjectTreeNode) {
+ ILTTngProjectTreeNode node = (ILTTngProjectTreeNode) element;
+ while (node != null && !(node instanceof LTTngProjectRoot)) {
+ node = node.getParent();
+ }
+ fProjectRoot = (node instanceof LTTngProjectRoot) ? (LTTngProjectRoot) node : null;
+ }
+ }
+
+ return (fProjectRoot != null);
+ }
+
+ // Handled if we are in the ProjectView
+ public boolean isHandled() {
+ return true;
+ }
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ if (fProjectRoot != null) {
+ fProjectRoot.refreshChildren();
+ fProjectRoot.refresh();
+ }
+
+ return null;
+ }
+
+ public void dispose() {
+ // TODO Auto-generated method stub
+ }
+
+ // ------------------------------------------------------------------------
+ // IHandlerListener
+ // ------------------------------------------------------------------------
+
+ public void addHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+ public void removeHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.handlers;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.core.commands.IHandlerListener;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngExperimentNode;
+import org.eclipse.swt.widgets.MessageBox;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * <b><u>RenameExperimentHandler</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+public class RenameExperimentHandler implements IHandler {
+
+ private LTTngExperimentNode fExperiment = null;
+
+ // ------------------------------------------------------------------------
+ // Validation
+ // ------------------------------------------------------------------------
+
+ public boolean isEnabled() {
+ return (fExperiment != null);
+ }
+
+ // Handled if we are in the ProjectView
+ public boolean isHandled() {
+ return true;
+ }
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ MessageBox mb = new MessageBox(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
+ mb.setText("Rename Experiment");
+ mb.setMessage("Not implemented yet");
+ mb.open();
+
+ return null;
+ }
+
+ public void dispose() {
+ // TODO Auto-generated method stub
+ }
+
+ // ------------------------------------------------------------------------
+ // IHandlerListener
+ // ------------------------------------------------------------------------
+
+ public void addHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+ public void removeHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.handlers;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.core.commands.IHandlerListener;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngProjectNode;
+import org.eclipse.swt.widgets.MessageBox;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * <b><u>RenameProjectHandler</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+public class RenameProjectHandler implements IHandler {
+
+ private LTTngProjectNode fProject = null;
+
+ // ------------------------------------------------------------------------
+ // Validation
+ // ------------------------------------------------------------------------
+
+ public boolean isEnabled() {
+
+// // Check if we are closing down
+// IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+// if (window == null)
+// return false;
+//
+// // Check if we are in the Project View
+// IWorkbenchPage page = window.getActivePage();
+// if (!(page.getActivePart() instanceof ProjectView))
+// return false;
+//
+// // Check if a project is selected
+// ISelection selection = page.getSelection(ProjectView.ID);
+// if (selection instanceof StructuredSelection) {
+// Object element = ((StructuredSelection) selection).getFirstElement();
+// fProjectNode = (element instanceof LTTngProjectNode) ? (LTTngProjectNode) element : null;
+// }
+
+ return (fProject != null);
+ }
+
+ // Handled if we are in the ProjectView
+ public boolean isHandled() {
+ return false;
+ }
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ MessageBox mb = new MessageBox(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
+ mb.setText("Rename Project");
+ mb.setMessage("Not implemented yet");
+ mb.open();
+
+ return null;
+ }
+
+ public void dispose() {
+ // TODO Auto-generated method stub
+ }
+
+ // ------------------------------------------------------------------------
+ // IHandlerListener
+ // ------------------------------------------------------------------------
+
+ public void addHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+ public void removeHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.handlers;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.core.commands.IHandlerListener;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngTraceNode;
+import org.eclipse.swt.widgets.MessageBox;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * <b><u>RenameTraceHandler</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+public class RenameTraceHandler implements IHandler {
+
+ private LTTngTraceNode fTrace = null;
+
+ // ------------------------------------------------------------------------
+ // Validation
+ // ------------------------------------------------------------------------
+
+ public boolean isEnabled() {
+ return (fTrace != null);
+ }
+
+ // Handled if we are in the ProjectView
+ public boolean isHandled() {
+ return true;
+ }
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ MessageBox mb = new MessageBox(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
+ mb.setText("Rename Trace");
+ mb.setMessage("Not implemented yet");
+ mb.open();
+
+ return null;
+ }
+
+ public void dispose() {
+ // TODO Auto-generated method stub
+ }
+
+ // ------------------------------------------------------------------------
+ // IHandlerListener
+ // ------------------------------------------------------------------------
+
+ public void addHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+ public void removeHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.handlers;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.core.commands.IHandlerListener;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.linuxtools.lttng.ui.views.project.ProjectView;
+import org.eclipse.linuxtools.lttng.ui.views.project.dialogs.AddTraceWizard;
+import org.eclipse.linuxtools.lttng.ui.views.project.model.LTTngExperimentNode;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * <b><u>SelectTracesHandler</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+public class SelectTracesHandler implements IHandler {
+
+ private LTTngExperimentNode fExperiment = null;
+
+ // ------------------------------------------------------------------------
+ // Validation
+ // ------------------------------------------------------------------------
+
+ public boolean isEnabled() {
+
+ // Check if we are closing down
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window == null)
+ return false;
+
+ // Check if we are in the Project View
+ IWorkbenchPage page = window.getActivePage();
+ if (!(page.getActivePart() instanceof ProjectView))
+ return false;
+
+ // Check that an experiment is selected
+ ISelection selection = page.getSelection(ProjectView.ID);
+ if (selection instanceof StructuredSelection) {
+ Object element = ((StructuredSelection) selection).getFirstElement();
+ fExperiment = (element instanceof LTTngExperimentNode) ? (LTTngExperimentNode) element : null;
+ }
+
+ return (fExperiment != null);
+ }
+
+ // Handled if we are in the ProjectView
+ public boolean isHandled() {
+ return true;
+ }
+
+ // ------------------------------------------------------------------------
+ // Execution
+ // ------------------------------------------------------------------------
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ // Open the trace addition wizard
+ IWorkbench workbench = PlatformUI.getWorkbench();
+ Shell shell = workbench.getActiveWorkbenchWindow().getShell();
+
+ AddTraceWizard wizard = new AddTraceWizard(fExperiment.getProject(), fExperiment);
+ wizard.init(PlatformUI.getWorkbench(), null);
+ WizardDialog dialog = new WizardDialog(shell, wizard);
+ dialog.open();
+
+ return null;
+ }
+
+ public void dispose() {
+ // TODO Auto-generated method stub
+ }
+
+ // ------------------------------------------------------------------------
+ // IHandlerListener
+ // ------------------------------------------------------------------------
+
+ public void addHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+ public void removeHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * William Bourque - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.handlers;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.core.commands.IHandlerListener;
+import org.eclipse.linuxtools.lttng.ui.views.project.dialogs.TraceErrorDialog;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.PlatformUI;
+
+
+public class TraceErrorHandler implements IHandler {
+
+ private String[] messages;
+
+ public TraceErrorHandler(String[] newMessages) {
+ messages = newMessages;
+ }
+
+ public boolean isEnabled() {
+ return true;
+ }
+
+ public boolean isHandled() {
+ return true;
+ }
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ IWorkbench workbench = PlatformUI.getWorkbench();
+ Shell shell = workbench.getActiveWorkbenchWindow().getShell();
+
+ TraceErrorDialog dialog = new TraceErrorDialog(shell, messages);
+ dialog.open();
+
+ return null;
+ }
+
+ public void dispose() {
+ }
+
+ public void addHandlerListener(IHandlerListener handlerListener) {
+ }
+
+ public void removeHandlerListener(IHandlerListener handlerListener) {
+ }
+
+}
+
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.model;
+
+import java.util.List;
+
+/**
+ * <b><u>ILTTngProjectTreeNode</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ * TODO: Make ILTTngProjectTreeNode extends IAdaptable
+ */
+public interface ILTTngProjectTreeNode {
+
+ public String getName();
+
+ public ILTTngProjectTreeNode getParent();
+
+ public boolean hasChildren();
+
+ public List<ILTTngProjectTreeNode> getChildren();
+
+ public void removeChild(ILTTngProjectTreeNode child);
+
+ public void removeChildren();
+
+ public void refreshChildren();
+
+ public void refresh();
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.model;
+
+import java.lang.reflect.Array;
+
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+
+/**
+ * <b><u>LTTngExperimentFolderNode</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+public class LTTngExperimentFolderNode extends LTTngProjectTreeNode {
+
+ private final IFolder fExperimentFolder;
+
+ // ------------------------------------------------------------------------
+ // Constructors
+ // ------------------------------------------------------------------------
+
+ public LTTngExperimentFolderNode(IFolder folder) {
+ this(null, folder);
+ }
+
+ public LTTngExperimentFolderNode(ILTTngProjectTreeNode parent, IFolder folder) {
+ super(parent);
+ fExperimentFolder = folder;
+ }
+
+ // ------------------------------------------------------------------------
+ // LTTngProjectTreeNode
+ // ------------------------------------------------------------------------
+
+ public String getName() {
+ return fExperimentFolder.getName();
+ }
+
+ @Override
+ public void refreshChildren() {
+ try {
+ IResource[] resources = fExperimentFolder.members();
+ for (IResource resource : resources) {
+ if (resource instanceof IFolder) {
+ LTTngExperimentNode node = find(resource.getName());
+ if (node == null) {
+ node = new LTTngExperimentNode(this, (IFolder) resource);
+ fChildren.add(node);
+ }
+ }
+ }
+ for (ILTTngProjectTreeNode node : fChildren) {
+ if (exists(node.getName(), resources)) {
+ node.refreshChildren();
+ }
+ else {
+ fChildren.remove(node);
+ }
+ }
+ } catch (CoreException e) {
+ }
+ }
+
+ private LTTngExperimentNode find(String name) {
+ for (ILTTngProjectTreeNode node : fChildren) {
+ if (node instanceof LTTngExperimentNode && node.getName().equals(name)) {
+ return (LTTngExperimentNode) node;
+ }
+ }
+ return null;
+ }
+
+ private boolean exists(String name, IResource[] resources) {
+ for (IResource resource : resources) {
+ if (resource.getName().equals(name))
+ return true;
+ }
+ return false;
+ }
+
+ // ------------------------------------------------------------------------
+ // Accessors
+ // ------------------------------------------------------------------------
+
+ /**
+ * @return
+ */
+ public LTTngProjectNode getProject() {
+ return (LTTngProjectNode) getParent();
+ }
+
+ /**
+ * @return
+ */
+ public IFolder getFolder() {
+ return fExperimentFolder;
+ }
+
+ /**
+ * @return
+ */
+ public LTTngExperimentNode[] getExperiments() {
+ LTTngExperimentNode[] result = (LTTngExperimentNode[]) Array.newInstance(LTTngExperimentNode.class, fChildren.size());
+ return fChildren.toArray(result);
+ }
+
+ // ------------------------------------------------------------------------
+ // Modifiers
+ // ------------------------------------------------------------------------
+
+// No longer needed: handled by the IResourceChangeListener in the View
+ public void addExperiment(IFolder experiment) {
+// LTTngExperimentNode node = new LTTngExperimentNode(this, experiment);
+// fChildren.add(node);
+// refresh();
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.model;
+
+import java.lang.reflect.Array;
+
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+
+/**
+ * <b><u>LTTngExperimentNode</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+public class LTTngExperimentNode extends LTTngProjectTreeNode {
+
+ private final IFolder fExperiment;
+
+ // ------------------------------------------------------------------------
+ // Constructors
+ // ------------------------------------------------------------------------
+
+ public LTTngExperimentNode(IFolder resource) {
+ this(null, resource);
+ }
+
+ public LTTngExperimentNode(ILTTngProjectTreeNode parent, IFolder folder) {
+ super(parent);
+ fExperiment = folder;
+ }
+
+ // ------------------------------------------------------------------------
+ // LTTngProjectTreeNode
+ // ------------------------------------------------------------------------
+
+ public String getName() {
+ return fExperiment.getName();
+ }
+
+ @Override
+ public void refreshChildren() {
+ try {
+ IResource[] resources = fExperiment.members(0);
+ for (IResource resource : resources) {
+ LTTngTraceNode node = find(resource.getName());
+ if (node == null) {
+ node = new LTTngTraceNode(this, (IFolder) resource);
+ fChildren.add(node);
+ }
+ }
+ for (ILTTngProjectTreeNode node : fChildren) {
+ if (!exists(node.getName(), resources)) {
+ fChildren.remove(node);
+ }
+ }
+ } catch (CoreException e) {
+ }
+ }
+
+ private LTTngTraceNode find(String name) {
+ for (ILTTngProjectTreeNode node : fChildren) {
+ if (node instanceof LTTngTraceNode && node.getName().equals(name)) {
+ return (LTTngTraceNode) node;
+ }
+ }
+ return null;
+ }
+
+ private boolean exists(String name, IResource[] resources) {
+ for (IResource resource : resources) {
+ if (resource.getName().equals(name))
+ return true;
+ }
+ return false;
+ }
+
+ // ------------------------------------------------------------------------
+ // Modifiers
+ // ------------------------------------------------------------------------
+
+// No longer needed: handled by the IResourceChangeListener in the View
+ public void addTrace(IFolder trace) {
+// LTTngTraceNode node = new LTTngTraceNode(this, trace);
+// fChildren.add(node);
+// refresh();
+ }
+
+ // ------------------------------------------------------------------------
+ // Accessors
+ // ------------------------------------------------------------------------
+
+ /**
+ * @return
+ */
+ public IFolder getFolder() {
+ return fExperiment;
+ }
+
+ /**
+ * @return
+ */
+ public LTTngTraceNode[] getTraces() {
+ LTTngTraceNode[] result = (LTTngTraceNode[]) Array.newInstance(LTTngTraceNode.class, fChildren.size());
+ return fChildren.toArray(result);
+ }
+
+ /**
+ * @return
+ */
+ public LTTngProjectNode getProject() {
+ return (LTTngProjectNode) getParent().getParent();
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.model;
+
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+
+/**
+ * <b><u>LTTngProjectContentProvider</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+ public class LTTngProjectContentProvider implements ITreeContentProvider {
+
+ public Object[] getChildren(Object parentElement) {
+ return ((ILTTngProjectTreeNode) parentElement).getChildren().toArray();
+ }
+
+ public Object getParent(Object element) {
+ return ((ILTTngProjectTreeNode) element).getParent();
+ }
+
+ public boolean hasChildren(Object element) {
+ return ((ILTTngProjectTreeNode) element).hasChildren();
+ }
+
+ public Object[] getElements(Object inputElement) {
+ if (inputElement instanceof LTTngProjectRoot) {
+ return ((LTTngProjectRoot) inputElement).getChildren().toArray();
+ }
+ return null;
+ }
+
+ public void dispose() {
+ // TODO Auto-generated method stub
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ // TODO Auto-generated method stub
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.model;
+
+import java.net.URL;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.linuxtools.lttng.ui.LTTngUiPlugin;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * <b><u>LTTngProjectLabelProvider</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ * TODO: Find proper icons for traces and experiments
+ */
+public class LTTngProjectLabelProvider implements ILabelProvider {
+
+ private final String fTraceIconFile = "icons/garland16.png";
+// private final String fExperimentIconFile = "icons/garland16.png";
+
+ private final Image fOpenedProjectIcon;
+ private final Image fClosedProjectIcon;
+ private final Image fFolderIcon;
+ private final Image fTraceIcon;
+ private final Image fExperimentIcon;
+
+ /**
+ *
+ */
+ public LTTngProjectLabelProvider() {
+
+ fOpenedProjectIcon = PlatformUI.getWorkbench().getSharedImages().getImage(org.eclipse.ui.ide.IDE.SharedImages.IMG_OBJ_PROJECT);
+ fClosedProjectIcon = PlatformUI.getWorkbench().getSharedImages().getImage(org.eclipse.ui.ide.IDE.SharedImages.IMG_OBJ_PROJECT_CLOSED);
+ fFolderIcon = PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FOLDER);
+
+ fTraceIcon = loadIcon(fTraceIconFile);
+ fExperimentIcon = fFolderIcon; // loadIcon(fExperimentIconFile);
+ }
+
+ private Image loadIcon(String url) {
+ LTTngUiPlugin plugin = LTTngUiPlugin.getDefault();
+ Image icon = plugin.getImageRegistry().get(url);
+ if (icon == null) {
+ URL imageURL = plugin.getBundle().getEntry(url);
+ ImageDescriptor descriptor = ImageDescriptor.createFromURL(imageURL);
+ icon = descriptor.createImage();
+ plugin.getImageRegistry().put(url, icon);
+ }
+ return icon;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.ILabelProvider#getImage(java.lang.Object)
+ */
+ public Image getImage(Object element) {
+
+ if (element instanceof LTTngProjectNode) {
+ LTTngProjectNode project = (LTTngProjectNode) element;
+ return (project.isOpen()) ? fOpenedProjectIcon : fClosedProjectIcon;
+ }
+
+ if (element instanceof LTTngTraceFolderNode) {
+ return fFolderIcon;
+ }
+
+ if (element instanceof LTTngTraceNode) {
+ return fTraceIcon;
+ }
+
+ if (element instanceof LTTngExperimentFolderNode) {
+ return fFolderIcon;
+ }
+
+ if (element instanceof LTTngExperimentNode) {
+ return fExperimentIcon;
+ }
+
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.ILabelProvider#getText(java.lang.Object)
+ */
+ public String getText(Object element) {
+ ILTTngProjectTreeNode node = (ILTTngProjectTreeNode) element;
+ String label = node.getName();
+ if (node instanceof LTTngTraceFolderNode ||
+ node instanceof LTTngExperimentFolderNode ||
+ node instanceof LTTngExperimentNode)
+ {
+ label += " [" + node.getChildren().size() + "]";
+ }
+ return label;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.IBaseLabelProvider#addListener(org.eclipse.jface.viewers.ILabelProviderListener)
+ */
+ public void addListener(ILabelProviderListener listener) {
+ // TODO Auto-generated method stub
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose()
+ */
+ public void dispose() {
+ // TODO Auto-generated method stub
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.IBaseLabelProvider#isLabelProperty(java.lang.Object, java.lang.String)
+ */
+ public boolean isLabelProperty(Object element, String property) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.IBaseLabelProvider#removeListener(org.eclipse.jface.viewers.ILabelProviderListener)
+ */
+ public void removeListener(ILabelProviderListener listener) {
+ // TODO Auto-generated method stub
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.linuxtools.lttng.ui.views.project.LTTngProjectNature;
+
+/**
+ * <b><u>LTTngProjectNode</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+public class LTTngProjectNode extends LTTngProjectTreeNode {
+
+ public static final String TRACE_FOLDER_NAME = "Traces";
+ public static final String EXPER_FOLDER_NAME = "Experiments";
+
+ private final IProject fProject;
+ private boolean fIsLTTngProject;
+ private boolean fIsOpen;
+ private LTTngTraceFolderNode fTracesFolder;
+ private LTTngExperimentFolderNode fExperimentsFolder;
+
+ // ------------------------------------------------------------------------
+ // Constructors
+ // ------------------------------------------------------------------------
+
+ public LTTngProjectNode(IProject project) {
+ this(null, project);
+ }
+
+ public LTTngProjectNode(ILTTngProjectTreeNode parent, IProject project) {
+ super(parent);
+ fProject = project;
+ updateState();
+ }
+
+ // ------------------------------------------------------------------------
+ // LTTngProjectTreeNode
+ // ------------------------------------------------------------------------
+
+ public String getName() {
+ return fProject.getName();
+ }
+
+ @Override
+ public void refreshChildren() {
+
+ if (!(fIsOpen && fIsLTTngProject))
+ return;
+
+ try {
+ IResource[] resources = fProject.members();
+ for (IResource resource : resources) {
+ if (resource.getType() == IResource.FOLDER) {
+ String name = resource.getName();
+ if (name.equals(TRACE_FOLDER_NAME) && !isIncluded(true, name, fChildren)) {
+ fTracesFolder = new LTTngTraceFolderNode(this, (IFolder) resource);
+ fChildren.add(fTracesFolder);
+ } else
+ if (name.equals(EXPER_FOLDER_NAME) && !isIncluded(false, name, fChildren)) {
+ fExperimentsFolder = new LTTngExperimentFolderNode(this, (IFolder) resource);
+ fChildren.add(fExperimentsFolder);
+ }
+ }
+ }
+ List<ILTTngProjectTreeNode> toRemove = new ArrayList<ILTTngProjectTreeNode>();
+ for (ILTTngProjectTreeNode node : fChildren) {
+ if (exists(node.getName(), resources)) {
+ node.refreshChildren();
+ }
+ else {
+ toRemove.add(node);
+ }
+ }
+ for (ILTTngProjectTreeNode node : toRemove) {
+ fChildren.remove(node);
+ }
+
+ } catch (CoreException e) {
+ }
+ }
+
+ private boolean isIncluded(boolean isTraces, String name, List<ILTTngProjectTreeNode> list) {
+ boolean found = false;
+ for (ILTTngProjectTreeNode node : list) {
+ if (node instanceof LTTngTraceFolderNode && isTraces) {
+ found |= node.getName().equals(name);
+ } else
+ if (node instanceof LTTngExperimentFolderNode && !isTraces) {
+ found |= node.getName().equals(name);
+ }
+ }
+ return found;
+ }
+
+ private boolean exists(String name, IResource[] resources) {
+ for (IResource resource : resources) {
+ if (resource.getName().equals(name))
+ return true;
+ }
+ return false;
+ }
+
+ // ------------------------------------------------------------------------
+ // Modifiers
+ // ------------------------------------------------------------------------
+
+ public void openProject() {
+ try {
+ fProject.open(null);
+ updateState();
+ refreshChildren();
+ } catch (CoreException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void closeProject() {
+ try {
+ fProject.close(null);
+ updateState();
+ removeChildren();
+ } catch (CoreException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private boolean isLTTngProject(IProject project) {
+ boolean result = false;
+ if (project != null && project.isAccessible()) {
+ try {
+ result = project.hasNature(LTTngProjectNature.ID);
+ } catch (CoreException e) {
+ }
+ }
+ return result;
+ }
+
+ public void updateState() {
+ fIsOpen = (fProject != null) ? fProject.isAccessible() : false;
+ fIsLTTngProject = isLTTngProject(fProject);
+ }
+
+ // ------------------------------------------------------------------------
+ // Accessors
+ // ------------------------------------------------------------------------
+
+ /**
+ * @return
+ */
+ public boolean isLTTngProject() {
+ return fIsLTTngProject;
+ }
+
+ /**
+ * @return
+ */
+ public boolean isOpen() {
+ return fIsOpen;
+ }
+
+ /**
+ * @return
+ */
+ public IProject getProject() {
+ return fProject;
+ }
+
+ /**
+ * @return
+ */
+ public LTTngTraceFolderNode getTracesFolder() {
+ return fTracesFolder;
+ }
+
+ /**
+ * @return
+ */
+ public LTTngExperimentFolderNode getExperimentsFolder() {
+ return fExperimentsFolder;
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.linuxtools.lttng.ui.views.project.ProjectView;
+
+/**
+ * <b><u>LTTngProjectRoot</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+public class LTTngProjectRoot extends LTTngProjectTreeNode {
+
+ private final ProjectView fView;
+
+ // ------------------------------------------------------------------------
+ // Constructors
+ // ------------------------------------------------------------------------
+
+ public LTTngProjectRoot(ProjectView view) {
+ super(null);
+ fView = view;
+ refreshChildren();
+ }
+
+ @Override
+ public void refresh() {
+ fView.refresh();
+ }
+
+ // ------------------------------------------------------------------------
+ // LTTngProjectTreeNode
+ // ------------------------------------------------------------------------
+
+ public String getName() {
+ return null;
+ }
+
+ @Override
+ public void refreshChildren() {
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ IProject[] projects = root.getProjects();
+ for (IProject project : projects) {
+ LTTngProjectNode node = find(project.getName());
+ if (node == null) {
+ node = new LTTngProjectNode(this, project);
+ fChildren.add(node);
+ } else {
+ node.updateState();
+ }
+ }
+ List<ILTTngProjectTreeNode> toRemove = new ArrayList<ILTTngProjectTreeNode>();
+ for (ILTTngProjectTreeNode node : fChildren) {
+ if (exists(node.getName(), projects)) {
+ node.refreshChildren();
+ }
+ else {
+ toRemove.add(node);
+ }
+ }
+ for (ILTTngProjectTreeNode node : toRemove) {
+ fChildren.remove(node);
+ }
+ }
+
+ private LTTngProjectNode find(String name) {
+ for (ILTTngProjectTreeNode node : fChildren) {
+ if (node instanceof LTTngProjectNode && node.getName().equals(name)) {
+ return (LTTngProjectNode) node;
+ }
+ }
+ return null;
+ }
+
+ private boolean exists(String name, IProject[] projects) {
+ for (IProject project : projects) {
+ if (project.getName().equals(name))
+ return true;
+ }
+ return false;
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * <b><u>LTTngProjectTreeNode</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+public abstract class LTTngProjectTreeNode implements ILTTngProjectTreeNode {
+
+ protected ILTTngProjectTreeNode fParent = null;
+ protected List<ILTTngProjectTreeNode> fChildren = null;
+
+ // ------------------------------------------------------------------------
+ // Constructor
+ // ------------------------------------------------------------------------
+
+ public LTTngProjectTreeNode(ILTTngProjectTreeNode parent) {
+ fParent = parent;
+ fChildren = new ArrayList<ILTTngProjectTreeNode>();
+ }
+
+ @Override
+ public String toString() {
+ return getName();
+ }
+
+ // ------------------------------------------------------------------------
+ // ILTTngProjectTreeNode
+ // ------------------------------------------------------------------------
+
+ public ILTTngProjectTreeNode getParent() {
+ return fParent;
+ }
+
+ public boolean hasChildren() {
+ return fChildren.size() > 0;
+ }
+
+ public List<ILTTngProjectTreeNode> getChildren() {
+ return fChildren;
+ }
+
+ public abstract void refreshChildren();
+
+ public void refresh() {
+ fParent.refresh();
+ }
+
+ public void removeChild(ILTTngProjectTreeNode child) {
+ for (ILTTngProjectTreeNode node : fChildren) {
+ if (node == child) {
+ node.removeChildren();
+ // We can do it since we are returning right away
+ fChildren.remove(node);
+ return;
+ }
+ }
+ }
+
+ public void removeChildren() {
+ for (ILTTngProjectTreeNode node : fChildren) {
+ node.removeChildren();
+ }
+ fChildren.clear();
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.model;
+
+import java.lang.reflect.Array;
+
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+
+/**
+ * <b><u>LTTngTraceFolderNode</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+public class LTTngTraceFolderNode extends LTTngProjectTreeNode {
+
+ private final IFolder fTraceFolder;
+
+ // ------------------------------------------------------------------------
+ // Constructors
+ // ------------------------------------------------------------------------
+
+ public LTTngTraceFolderNode(IFolder folder) {
+ this(null, folder);
+ }
+
+ public LTTngTraceFolderNode(ILTTngProjectTreeNode parent, IFolder folder) {
+ super(parent);
+ fTraceFolder = folder;
+ }
+
+ // ------------------------------------------------------------------------
+ // LTTngProjectTreeNode
+ // ------------------------------------------------------------------------
+
+ public String getName() {
+ return fTraceFolder.getName();
+ }
+
+ @Override
+ public void refreshChildren() {
+ try {
+ IResource[] resources = fTraceFolder.members();
+ for (IResource resource : resources) {
+ if (resource instanceof IFolder) {
+ LTTngTraceNode node = find(resource.getName());
+ if (node == null) {
+ node = new LTTngTraceNode(this, (IFolder) resource);
+ fChildren.add(node);
+ }
+ }
+ }
+ for (ILTTngProjectTreeNode node : fChildren) {
+ if (!exists(node.getName(), resources)) {
+ fChildren.remove(node);
+ }
+ }
+ } catch (CoreException e) {
+ }
+ }
+
+ private LTTngTraceNode find(String name) {
+ for (ILTTngProjectTreeNode node : fChildren) {
+ if (node instanceof LTTngTraceNode && node.getName().equals(name)) {
+ return (LTTngTraceNode) node;
+ }
+ }
+ return null;
+ }
+
+ private boolean exists(String name, IResource[] resources) {
+ for (IResource resource : resources) {
+ if (resource.getName().equals(name))
+ return true;
+ }
+ return false;
+ }
+
+ // ------------------------------------------------------------------------
+ // Accessors
+ // ------------------------------------------------------------------------
+
+ /**
+ * @return
+ */
+ public LTTngProjectNode getProject() {
+ return (LTTngProjectNode) getParent();
+ }
+
+ /**
+ * @return
+ */
+ public IFolder getFolder() {
+ return fTraceFolder;
+ }
+
+ /**
+ * @return
+ */
+ public LTTngTraceNode[] getTraces() {
+ LTTngTraceNode[] result = (LTTngTraceNode[]) Array.newInstance(LTTngTraceNode.class, fChildren.size());
+ return fChildren.toArray(result);
+ }
+
+ // ------------------------------------------------------------------------
+ // Modifiers
+ // ------------------------------------------------------------------------
+
+// No longer needed: handled by the IResourceChangeListener in the View
+ public void addTrace(IFolder trace) {
+// LTTngTraceNode node = new LTTngTraceNode(this, trace);
+// fChildren.add(node);
+// refresh();
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.project.model;
+
+import org.eclipse.core.resources.IFolder;
+
+/**
+ * <b><u>LTTngTraceNode</u></b>
+ * <p>
+ * TODO: Implement me. Please.
+ */
+public class LTTngTraceNode extends LTTngProjectTreeNode {
+
+ private final IFolder fTrace;
+
+ // ------------------------------------------------------------------------
+ // Constructors
+ // ------------------------------------------------------------------------
+
+ public LTTngTraceNode(IFolder folder) {
+ this(null, folder);
+ }
+
+ public LTTngTraceNode(ILTTngProjectTreeNode parent, IFolder trace) {
+ super(parent);
+ fTrace = trace;
+ }
+
+ // ------------------------------------------------------------------------
+ // LTTngProjectTreeNode
+ // ------------------------------------------------------------------------
+
+ public String getName() {
+ return fTrace.getName();
+ }
+
+ @Override
+ public void refreshChildren() {
+ }
+
+ // ------------------------------------------------------------------------
+ // Accessors
+ // ------------------------------------------------------------------------
+
+ /**
+ * @return
+ */
+ public LTTngProjectNode getProject() {
+ return (LTTngProjectNode) getParent().getParent();
+ }
+
+ /**
+ * @return
+ */
+ public IFolder getFolder() {
+ return fTrace;
+ }
+
+}
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2009 Ericsson\r
+ * \r
+ * All rights reserved. This program and the accompanying materials are\r
+ * made available under the terms of the Eclipse Public License v1.0 which\r
+ * accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ * \r
+ * Contributors:\r
+ * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation\r
+ *******************************************************************************/\r
+package org.eclipse.linuxtools.lttng.ui.views.resources;\r
+\r
+import java.util.MissingResourceException;\r
+import java.util.ResourceBundle;\r
+\r
+public class Messages {\r
+ private static final String BUNDLE_NAME = "org.eclipse.linuxtools.lttng.ui.views.resources.messages"; //$NON-NLS-1$\r
+\r
+ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle\r
+ .getBundle(BUNDLE_NAME);\r
+\r
+ private Messages() {\r
+ }\r
+\r
+ public static String getString(String key) {\r
+ try {\r
+ return RESOURCE_BUNDLE.getString(key);\r
+ } catch (MissingResourceException e) {\r
+ return '!' + key + '!';\r
+ }\r
+ }\r
+}\r
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors: Alvaro Sanchez-Leon - Initial implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.resources;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.linuxtools.lttng.request.ILttngSyntEventRequest;
+import org.eclipse.linuxtools.lttng.state.evProcessor.ITransEventProcessor;
+import org.eclipse.linuxtools.lttng.ui.TraceDebug;
+import org.eclipse.linuxtools.lttng.ui.model.trange.ItemContainer;
+import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeViewerProvider;
+import org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView;
+import org.eclipse.linuxtools.lttng.ui.views.common.ParamsUpdater;
+import org.eclipse.linuxtools.lttng.ui.views.resources.evProcessor.ResourcesEventToHandlerFactory;
+import org.eclipse.linuxtools.lttng.ui.views.resources.model.ResourceModelFactory;
+import org.eclipse.linuxtools.tmf.event.TmfEvent;
+import org.eclipse.linuxtools.tmf.event.TmfTimeRange;
+import org.eclipse.linuxtools.tmf.experiment.TmfExperiment;
+import org.eclipse.linuxtools.tmf.signal.TmfExperimentSelectedSignal;
+import org.eclipse.linuxtools.tmf.signal.TmfRangeSynchSignal;
+import org.eclipse.linuxtools.tmf.signal.TmfSignalHandler;
+import org.eclipse.linuxtools.tmf.signal.TmfTimeSynchSignal;
+import org.eclipse.linuxtools.tmf.ui.viewers.TmfViewerFactory;
+import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.ITmfTimeScaleSelectionListener;
+import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.ITmfTimeSelectionListener;
+import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeScaleSelectionEvent;
+import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeSelectionEvent;
+import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITmfTimeAnalysisEntry;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IWorkbenchActionConstants;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+
+/**
+ * @author alvaro
+ *
+ */
+public class ResourcesView extends AbsTimeUpdateView implements
+ ITmfTimeSelectionListener, ITmfTimeScaleSelectionListener {
+
+ // ========================================================================
+ // Data
+ // ========================================================================
+ public static final String ID = "org.eclipse.linuxtools.lttng.ui.views.resources";
+
+ // private int totalNumItems = 0;
+ // Actions
+ private Action resetScale;
+ private Action nextEvent;
+ private Action prevEvent;
+ private Action nextTrace;
+ private Action prevTrace;
+ private Action showLegend;
+ private Action filterTraces;
+ private Action zoomIn;
+ private Action zoomOut;
+ private Action zoomFilter;
+ private Composite top;
+
+ // private static SimpleDateFormat stimeformat = new SimpleDateFormat(
+ // "yy/MM/dd HH:mm:ss");
+
+ // private TraceModelImplFactory fact;
+
+ // ========================================================================
+ // Constructor
+ // ========================================================================
+
+ /**
+ * The constructor.
+ */
+ public ResourcesView() {
+ super(ID);
+ }
+
+ // ========================================================================
+ // Methods
+ // ========================================================================
+
+ /**
+ * This is a callback that will allow us to create the viewer and initialize
+ * it.
+ */
+ @Override
+ public void createPartControl(Composite parent) {
+ top = new Composite(parent, SWT.BORDER);
+
+ top.setLayout(new FillLayout());
+ tsfviewer = TmfViewerFactory.createViewer(top,
+ new TimeRangeViewerProvider());
+
+ tsfviewer.addWidgetSelectionListner(this);
+ tsfviewer.addWidgetTimeScaleSelectionListner(this);
+
+ // Traces shall not be grouped to allow synchronisation
+ tsfviewer.groupTraces(true);
+ tsfviewer.setAcceptSelectionAPIcalls(true);
+
+ // Viewer to notify selection to this class
+ // This class will synchronise selections with table.
+ tsfviewer.addWidgetSelectionListner(this);
+ tsfviewer.addWidgetTimeScaleSelectionListner(this);
+
+ // Create the help context id for the viewer's control
+ // TODO: Associate with help system
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(
+ tsfviewer.getControl(),
+ "org.eclipse.linuxtools.lttng.ui.views.resource.view"); //$NON-NLS-1$
+
+ makeActions();
+ hookContextMenu();
+ contributeToActionBars();
+
+ // Read relevant values
+ int timeSpaceWidth = tsfviewer.getTimeSpace();
+ if (timeSpaceWidth < 0) {
+ timeSpaceWidth = -timeSpaceWidth;
+ }
+
+ TmfExperiment<?> experiment = TmfExperiment.getCurrentExperiment();
+ if (experiment != null) {
+ TmfTimeRange experimentTRange = experiment.getTimeRange();
+ if (experimentTRange != null) {
+ long time0 = experimentTRange.getStartTime().getValue();
+ long time1 = experimentTRange.getEndTime().getValue();
+ ParamsUpdater paramUpdater = getParamsUpdater();
+ paramUpdater.update(time0, time1, timeSpaceWidth);
+ }
+ // send the initial request and obtained the adjusted time used
+ TmfTimeRange adjustedTimeRange = initialExperimentDataRequest(this, experimentTRange);
+
+ // initialize widget time boundaries and filtering parameters
+ ModelUpdateInit(experimentTRange, adjustedTimeRange, this);
+ } else {
+ TraceDebug.debug("No selected experiment information available");
+ }
+ }
+
+ private void hookContextMenu() {
+ MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$
+ menuMgr.setRemoveAllWhenShown(true);
+ menuMgr.addMenuListener(new IMenuListener() {
+ public void menuAboutToShow(IMenuManager manager) {
+ ResourcesView.this.fillContextMenu(manager);
+ }
+ });
+
+ Menu menu = menuMgr.createContextMenu(tsfviewer.getControl());
+ tsfviewer.getControl().setMenu(menu);
+ getSite()
+ .registerContextMenu(menuMgr, tsfviewer.getSelectionProvider());
+ }
+
+ private void contributeToActionBars() {
+ IActionBars bars = getViewSite().getActionBars();
+ fillLocalPullDown(bars.getMenuManager());
+ fillLocalToolBar(bars.getToolBarManager());
+ }
+
+ private void fillLocalPullDown(IMenuManager manager) {
+ manager.add(new Separator());
+ // manager.add(showLegend);
+ manager.add(new Separator());
+ manager.add(resetScale);
+ manager.add(nextEvent);
+ manager.add(prevEvent);
+ manager.add(nextTrace);
+ manager.add(prevTrace);
+ // manager.add(filterTraces);
+ manager.add(zoomIn);
+ manager.add(zoomOut);
+ manager.add(zoomFilter);
+ manager.add(new Separator());
+ }
+
+ private void fillContextMenu(IMenuManager manager) {
+ // manager.add(showLegend);
+ manager.add(new Separator());
+ manager.add(resetScale);
+ manager.add(nextEvent);
+ manager.add(prevEvent);
+ manager.add(nextTrace);
+ manager.add(prevTrace);
+ // manager.add(showLegend);
+ // manager.add(filterTraces);
+ manager.add(zoomIn);
+ manager.add(zoomOut);
+ manager.add(zoomFilter);
+ manager.add(new Separator());
+ manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
+ }
+
+ private void fillLocalToolBar(IToolBarManager manager) {
+ // manager.add(showLegend);
+ manager.add(new Separator());
+ manager.add(resetScale);
+ manager.add(nextEvent);
+ manager.add(prevEvent);
+ manager.add(nextTrace);
+ manager.add(prevTrace);
+ // manager.add(filterTraces);
+ manager.add(zoomIn);
+ manager.add(zoomOut);
+ manager.add(zoomFilter);
+ manager.add(new Separator());
+ }
+
+ private void makeActions() {
+ // action4
+ resetScale = new Action() {
+ @Override
+ public void run() {
+ if (tsfviewer != null) {
+ tsfviewer.resetStartFinishTime();
+ }
+
+ }
+ };
+ resetScale.setText(Messages.getString("ResourcesView.Action.Reset")); //$NON-NLS-1$
+ resetScale.setToolTipText(Messages
+ .getString("ResourcesView.Action.Reset.ToolTip")); //$NON-NLS-1$
+ resetScale.setImageDescriptor(AbstractUIPlugin
+ .imageDescriptorFromPlugin(Messages
+ .getString("ResourcesView.tmf.UI"),
+ "icons/home_nav.gif"));
+
+ // action5
+ nextEvent = new Action() {
+ @Override
+ public void run() {
+ if (tsfviewer != null) {
+ tsfviewer.selectNextEvent();
+ }
+ }
+ };
+ nextEvent.setText(Messages.getString("ResourcesView.Action.NextEvent")); //$NON-NLS-1$
+ nextEvent.setToolTipText(Messages
+ .getString("ResourcesView.Action.NextEvent.Tooltip")); //$NON-NLS-1$
+ nextEvent.setImageDescriptor(AbstractUIPlugin
+ .imageDescriptorFromPlugin(Messages
+ .getString("ResourcesView.tmf.UI"),
+ "icons/next_event.gif"));
+
+ // action6
+ prevEvent = new Action() {
+ @Override
+ public void run() {
+ if (tsfviewer != null) {
+ tsfviewer.selectPrevEvent();
+ }
+ }
+ };
+ prevEvent.setText(Messages.getString("ResourcesView.Action.PrevEvent")); //$NON-NLS-1$
+ prevEvent.setToolTipText(Messages
+ .getString("ResourcesView.Action.PrevEvent.Tooltip")); //$NON-NLS-1$
+ prevEvent.setImageDescriptor(AbstractUIPlugin
+ .imageDescriptorFromPlugin(Messages
+ .getString("ResourcesView.tmf.UI"),
+ "icons/prev_event.gif"));
+
+ // action7
+ nextTrace = new Action() {
+ @Override
+ public void run() {
+ if (tsfviewer != null) {
+ tsfviewer.selectNextTrace();
+ }
+ }
+ };
+ nextTrace.setText(Messages
+ .getString("ResourcesView.Action.NextResource")); //$NON-NLS-1$
+ nextTrace.setToolTipText(Messages
+ .getString("ResourcesView.Action.NextResource.ToolTip")); //$NON-NLS-1$
+ nextTrace.setImageDescriptor(AbstractUIPlugin
+ .imageDescriptorFromPlugin(Messages
+ .getString("ResourcesView.tmf.UI"),
+ "icons/next_item.gif"));
+
+ // action8
+ prevTrace = new Action() {
+ @Override
+ public void run() {
+ if (tsfviewer != null) {
+ tsfviewer.selectPrevTrace();
+ }
+ }
+ };
+ prevTrace.setText(Messages
+ .getString("ResourcesView.Action.PreviousResource")); //$NON-NLS-1$
+ prevTrace.setToolTipText(Messages
+ .getString("ResourcesView.Action.PreviousResource.Tooltip")); //$NON-NLS-1$
+ prevTrace.setImageDescriptor(AbstractUIPlugin
+ .imageDescriptorFromPlugin(Messages
+ .getString("ResourcesView.tmf.UI"),
+ "icons/prev_item.gif"));
+
+ // action9
+ showLegend = new Action() {
+ @Override
+ public void run() {
+ if (tsfviewer != null) {
+ tsfviewer.showLegend();
+ }
+ }
+ };
+ showLegend.setText(Messages.getString("ResourcesView.Action.Legend")); //$NON-NLS-1$
+ showLegend.setToolTipText(Messages
+ .getString("ResourcesView.Action.Legend.ToolTip")); //$NON-NLS-1$
+
+ // action10
+ filterTraces = new Action() {
+ @Override
+ public void run() {
+ if (tsfviewer != null) {
+ tsfviewer.filterTraces();
+ }
+ }
+ };
+ filterTraces.setText(Messages.getString("ResourcesView.Action.Filter")); //$NON-NLS-1$
+ filterTraces.setToolTipText(Messages
+ .getString("ResourcesView.Action.Filter.ToolTip")); //$NON-NLS-1$
+ filterTraces.setImageDescriptor(AbstractUIPlugin
+ .imageDescriptorFromPlugin(Messages
+ .getString("ResourcesView.tmf.UI"),
+ "icons/filter_items.gif"));
+
+ // action10
+ zoomIn = new Action() {
+ @Override
+ public void run() {
+ if (tsfviewer != null) {
+ tsfviewer.zoomIn();
+ }
+ }
+ };
+ zoomIn.setText(Messages.getString("ResourcesView.Action.ZoomIn")); //$NON-NLS-1$
+ zoomIn.setToolTipText(Messages
+ .getString("ResourcesView.Action.ZoomIn.Tooltip")); //$NON-NLS-1$
+ zoomIn.setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(
+ Messages.getString("ResourcesView.tmf.UI"),
+ "icons/zoomin_nav.gif"));
+
+ // action10
+ zoomOut = new Action() {
+ @Override
+ public void run() {
+ if (tsfviewer != null) {
+ tsfviewer.zoomOut();
+ }
+ }
+ };
+ zoomOut.setText(Messages.getString("ResourcesView.Action.ZoomOut")); //$NON-NLS-1$
+ zoomOut.setToolTipText(Messages
+ .getString("ResourcesView.Action.ZoomOut.tooltip")); //$NON-NLS-1$
+ zoomOut.setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(
+ Messages.getString("ResourcesView.tmf.UI"),
+ "icons/zoomout_nav.gif"));
+
+ // zoomFilter
+ zoomFilter = new Action() {
+ @Override
+ public void run() {
+ // Nothing to do, however the selection status is needed by the
+ // application
+ }
+ };
+
+ zoomFilter.setText(Messages.getString("ResourcesView.Action.ZoomFilter")); //$NON-NLS-1$
+ zoomFilter.setToolTipText(Messages.getString("ResourcesView.Action.ZoomFilter.tooltip")); //$NON-NLS-1$
+ zoomFilter.setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(Messages
+ .getString("ResourcesView.tmf.UI"), "icons/filter_items.gif"));
+ zoomFilter.setChecked(false);
+
+ // PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_ELCL_SYNCED);
+ }
+
+ /**
+ * Passing the focus request to the viewer's control.
+ */
+ @Override
+ public void setFocus() {
+ tsfviewer.getControl().setFocus();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView#
+ * tsfTmProcessSelEvent
+ * (org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.TmfTimeSelectionEvent
+ * )
+ */
+ public void tsfTmProcessSelEvent(TmfTimeSelectionEvent event) {
+ // common implementation
+ super.tsfTmProcessSelEvent(event);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.
+ * ITmfTimeScaleSelectionListener
+ * #tsfTmProcessTimeScaleEvent(org.eclipse.linuxtools
+ * .tmf.ui.viewers.timeAnalysis.TmfTimeScaleSelectionEvent)
+ */
+ public void tsfTmProcessTimeScaleEvent(TmfTimeScaleSelectionEvent event) {
+ super.tsfTmProcessTimeScaleEvent(event);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView#displayModel
+ * (org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.
+ * ITmfTimeAnalysisEntry[], long, long, boolean, long, long,
+ * java.lang.Object)
+ */
+ public void displayModel(final ITmfTimeAnalysisEntry[] items, final long startBoundTime,
+ final long endBoundTime, final boolean updateTimeBounds, final long startVisibleWindow,
+ final long endVisibleWindow, final Object source) {
+
+ Display display = tsfviewer.getControl().getDisplay();
+ display.asyncExec(new Runnable() {
+
+ public void run() {
+ tsfviewer.display(items, startBoundTime, endBoundTime, updateTimeBounds);
+ // validate visible boundaries
+ if (startVisibleWindow > -1 && endVisibleWindow > -1) {
+ tsfviewer.setSelectVisTimeWindow(startVisibleWindow, endVisibleWindow, source);
+ }
+ tsfviewer.resizeControls();
+ }
+ });
+ }
+
+ @Override
+ public void dispose() {
+ // dispose parent resources
+ super.dispose();
+
+ tsfviewer.removeWidgetSelectionListner(this);
+ tsfviewer.removeWidgetTimeScaleSelectionListner(this);
+ tsfviewer = null;
+ }
+
+ /**
+ * Registers as listener of time selection from other tmf views
+ *
+ * @param signal
+ */
+ @TmfSignalHandler
+ public void synchToTime(TmfTimeSynchSignal signal) {
+ super.synchToTime(signal);
+ }
+
+ /**
+ * Annotation Registers as listener of time range selection from other views
+ * The implementation handles the entry of the signal.
+ *
+ * @param signal
+ */
+ @TmfSignalHandler
+ public void synchToTimeRange(TmfRangeSynchSignal signal) {
+ if (zoomFilter != null) {
+ synchToTimeRange(signal, zoomFilter.isChecked());
+ }
+ }
+
+ @Override
+ public void modelIncomplete(ILttngSyntEventRequest request) {
+ // Nothing to do
+ // The data will be refreshed on the next request
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView#
+ * getEventProcessor()
+ */
+ @Override
+ public ITransEventProcessor getEventProcessor() {
+ return ResourcesEventToHandlerFactory.getInstance();
+ }
+
+ /**
+ * @param signal
+ */
+ @TmfSignalHandler
+ public void experimentSelected(TmfExperimentSelectedSignal<? extends TmfEvent> signal) {
+ if (signal != null) {
+ TmfTimeRange experimentTRange = signal.getExperiment().getTimeRange();
+
+ // prepare time intervals in widget
+ ModelUpdateInit(experimentTRange, experimentTRange, signal.getSource());
+
+ // request initial data
+ initialExperimentDataRequest(signal.getSource(), experimentTRange);
+ }
+ }
+
+ /**
+ * @param source
+ * @param experimentTRange
+ * @return Adjusted time window used for the request (smaller window to
+ * initialize view)
+ */
+ private TmfTimeRange initialExperimentDataRequest(Object source, TmfTimeRange experimentTRange) {
+ // Adjust the initial time window to a shorter interval to allow
+ // user to select the interesting area based on the perspective
+ TmfTimeRange initTimeWindow = getInitTRange(experimentTRange);
+
+ dataRequest(initTimeWindow, experimentTRange, true);
+ if (TraceDebug.isDEBUG()) {
+ TraceDebug.debug("Initialization request time range is: " + initTimeWindow.getStartTime().toString() + "-"
+ + initTimeWindow.getEndTime().toString());
+ }
+
+ return initTimeWindow;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView#
+ * getParamsUpdater()
+ */
+ protected ParamsUpdater getParamsUpdater() {
+ return ResourceModelFactory.getParamsUpdater();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView#
+ * getItemContainer()
+ */
+ @Override
+ protected ItemContainer<?> getItemContainer() {
+ return ResourceModelFactory.getResourceContainer();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.resources.evProcessor;
+
+import java.util.Vector;
+
+import org.eclipse.linuxtools.lttng.event.LttngEvent;
+import org.eclipse.linuxtools.lttng.state.evProcessor.ILttngEventProcessor;
+import org.eclipse.linuxtools.lttng.state.model.LttngTraceState;
+import org.eclipse.linuxtools.lttng.ui.TraceDebug;
+import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeComponent;
+import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEvent;
+import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEvent.Type;
+import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEventResource;
+import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEventResource.ResourceTypes;
+import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeResourceFactory;
+import org.eclipse.linuxtools.lttng.ui.views.common.AbsTRangeUpdate;
+import org.eclipse.linuxtools.lttng.ui.views.common.ParamsUpdater;
+import org.eclipse.linuxtools.lttng.ui.views.resources.model.ResourceContainer;
+import org.eclipse.linuxtools.lttng.ui.views.resources.model.ResourceModelFactory;
+import org.eclipse.linuxtools.tmf.event.TmfTimeRange;
+
+public abstract class AbsResourcesTRangeUpdate extends AbsTRangeUpdate
+ implements ILttngEventProcessor {
+
+ // ========================================================================
+ // Data
+ // =======================================================================
+ protected ResourceContainer resContainer = ResourceModelFactory
+ .getResourceContainer();
+ protected ParamsUpdater params = ResourceModelFactory.getParamsUpdater();
+ protected static final Long ANY_CPU = 0L;
+
+ // ========================================================================
+ // Methods
+ // =======================================================================
+ protected TimeRangeEventResource addLocalResource(long traceStartTime,
+ long traceEndTime, String traceId, ResourceTypes type, Long resId,
+ long insertionTime) {
+
+ String resourceName = type.toString() + " " + resId.toString();
+ // Note : the "traceid" here is assigned to the "groupname" as we group
+ // by trace in the UI
+ TimeRangeEventResource localRessource = TimeRangeResourceFactory
+ .getInstance().createResource(resContainer.getUniqueId(),
+ traceStartTime, traceEndTime, resourceName, traceId,
+ "", type, resId, insertionTime);
+ resContainer.addItem(localRessource);
+ return localRessource;
+ }
+
+ /**
+ * Used to check if the event is visible within the current visible time
+ * window
+ *
+ * @return
+ */
+ protected boolean withinViewRange(long stime, long etime) {
+ long windowStartTime = params.getStartTime();
+ long windowEndTime = params.getEndTime();
+
+ if (stime == 13589765052286L) {
+ TraceDebug.debug("Debug event catched");
+ }
+
+ // Start of event is already out of range
+ if (stime > windowEndTime) {
+ return false;
+ }
+
+ // End time within or beyond start of window as long as the start time
+ // is before the end of the window (condition above)
+ if (etime >= windowStartTime) {
+ return true;
+ }
+
+ // // start time is within window
+ // if (stime >= windowStartTime && stime <= windowEndTime) {
+ // // The event or part of it shall be displayed.
+ // return true;
+ // }
+ //
+ // // end time is within window
+ // if (etime >= windowStartTime && etime <= windowEndTime) {
+ // // The event or part of it shall be displayed.
+ // return true;
+ // }
+
+ // crosses the window
+ if (stime <= windowStartTime && etime >= windowEndTime) {
+ // The time range is bigger than the selected time window and
+ // crosses it
+ return true;
+ }
+
+ return false;
+ }
+
+ public TimeRangeEventResource resourcelist_obtain_bdev(
+ LttngTraceState traceState, Long resourceId) {
+ return resourcelist_obtain_generic(resourceId, ResourceTypes.BDEV,
+ traceState.getTraceId());
+ }
+
+ public TimeRangeEventResource resourcelist_obtain_trap(
+ LttngTraceState traceState, Long resourceId) {
+ return resourcelist_obtain_generic(resourceId, ResourceTypes.TRAP,
+ traceState.getTraceId());
+ }
+
+ public TimeRangeEventResource resourcelist_obtain_irq(
+ LttngTraceState traceState, Long resourceId) {
+ return resourcelist_obtain_generic(resourceId, ResourceTypes.IRQ,
+ traceState.getTraceId());
+ }
+
+ public TimeRangeEventResource resourcelist_obtain_soft_irq(
+ LttngTraceState traceState, Long resourceId) {
+ return resourcelist_obtain_generic(resourceId, ResourceTypes.SOFT_IRQ,
+ traceState.getTraceId());
+ }
+
+ public TimeRangeEventResource resourcelist_obtain_cpu(
+ LttngTraceState traceState, Long resourceId) {
+ return resourcelist_obtain_generic(resourceId, ResourceTypes.CPU,
+ traceState.getTraceId());
+ }
+
+ public TimeRangeEventResource resourcelist_obtain_machine(
+ LttngTraceState traceState, Long resourceId) {
+ // *** VERIFY ***
+ // Does "UNKNOWN" make sense for "obtain_machine" ?
+ // It seems to be the only choice, thought...
+ return resourcelist_obtain_generic(resourceId, ResourceTypes.UNKNOWN,
+ traceState.getTraceId());
+ }
+
+ public TimeRangeEventResource resourcelist_obtain_generic(Long resourceId,
+ ResourceTypes resourceType, String traceId) {
+ return resContainer.findItem(resourceId, resourceType, traceId);
+ }
+
+ protected boolean globalProcessBeforeExecmode(LttngEvent trcEvent,
+ LttngTraceState traceSt) {
+
+ // TODO: Implement the tracking of current resource in order ot speed up
+ // searching for the relevant resource similar to current_hash_data in
+ // the C implementation
+ // e.g.
+ // hashed_process_data =
+ // process_list->current_hash_data[trace_num][cpu];
+
+ TimeRangeEventResource localResource = resourcelist_obtain_cpu(traceSt,
+ trcEvent.getCpuId());
+ Long cpu = trcEvent.getCpuId();
+ if (localResource == null) {
+ TmfTimeRange timeRange = traceSt.getContext()
+ .getTraceTimeWindow();
+ localResource = addLocalResource(timeRange.getStartTime()
+ .getValue(), timeRange.getEndTime().getValue(), traceSt
+ .getTraceId(), ResourceTypes.CPU, cpu, trcEvent
+ .getTimestamp().getValue());
+ }
+
+ // get the start time
+ long stime = localResource.getNext_good_time();
+ // Get the resource state mode
+ String cpuStateMode = localResource.getStateMode(traceSt);
+ // Call the makeDraw function
+ makeDraw(traceSt, stime, trcEvent.getTimestamp().getValue(),
+ localResource, params, cpuStateMode);
+
+ return false;
+ }
+
+ /**
+ * @param traceSt
+ * @param startTime
+ * @param endTime
+ * @param localResource
+ * @param params
+ * @param stateMode
+ * @return
+ */
+ protected boolean makeDraw(LttngTraceState traceSt, long stime, long etime,
+ TimeRangeEventResource localResource,
+ ParamsUpdater params, String stateMode) {
+
+ // Check if the event is out of range
+ if (!withinViewRange(stime, etime)) {
+ params.incrementEventsDiscarded();
+ return false;
+ }
+
+ // Check if the time range is consistent.
+ if (etime < stime) {
+ params.incrementEventsDiscardedWrongOrder();
+ return false;
+ }
+
+ // Store the next good time to start drawing the next event
+ // this is done this early to display an accurate start time of the
+ // first event
+ // within the display window
+ // Moved at the end since it produces space gaps among events
+ // localResource.setNext_good_time(etime);
+
+ // Determine if the time range event will fit it the current
+ // pixel map
+ double duration = etime - stime;
+ double k = getPixelsPerNs(traceSt, params);
+ double pixels = duration * k;
+
+ // Visibility check
+ // Display a "more information" indication by allowing non visible event
+ // as long as its previous event is visible.
+ boolean visible = true;
+ if (pixels < 1) {
+ boolean prevEventVisibility = true;
+ // Get the visibility indication on previous event for
+ // this process
+ Vector<TimeRangeComponent> inMemEvents = localResource
+ .getTraceEvents();
+ if (inMemEvents.size() != 0) {
+ TimeRangeComponent prevEvent = inMemEvents.get(inMemEvents
+ .size() - 1);
+ prevEventVisibility = prevEvent.isVisible();
+
+ // if previous event visibility is false and the time span
+ // between events less than two pixels, there is no need to
+ // load it in memory i.e. not visible and a more indicator is
+ // within two pixels.
+ // return i.e. event discarded to free up memory
+ Long eventSpan = stime - prevEvent.getStartTime();
+ if (prevEventVisibility == false
+ && ((double) eventSpan * k) < 2) {
+ params.incrementEventsDiscarded();
+ return false;
+ }
+ }
+
+ // if previous event is visible, set this one to not
+ // visible and continue
+ visible = false;
+ }
+
+ Type eventType = getEventType(localResource);
+ if (eventType != null) {
+ TimeRangeEvent time_window = new TimeRangeEvent(stime, etime,
+ localResource, eventType, stateMode);
+
+ time_window.setVisible(visible);
+ localResource.addChildren(time_window);
+
+ localResource.setNext_good_time(etime);
+ }
+
+ return false;
+ }
+
+ /**
+ * Convert between resource type and timeRange event type
+ *
+ * @param resource
+ * @return
+ */
+ private Type getEventType(TimeRangeEventResource resource) {
+ // TODO: Can we merge into one type
+ ResourceTypes resType = resource.getType();
+ Type eventType = null;
+
+ switch (resType) {
+ case CPU:
+ eventType = Type.CPU_MODE;
+ break;
+ case IRQ:
+ eventType = Type.IRQ_MODE;
+ break;
+ case SOFT_IRQ:
+ eventType = Type.SOFT_IRQ_MODE;
+ break;
+ case TRAP:
+ eventType = Type.TRAP_MODE;
+ break;
+ case BDEV:
+ eventType = Type.BDEV_MODE;
+ break;
+ default:
+ eventType = Type.PROCESS_MODE;
+ break;
+ }
+
+ return eventType;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.resources.evProcessor;
+
+import org.eclipse.linuxtools.lttng.event.LttngEvent;
+import org.eclipse.linuxtools.lttng.state.evProcessor.ILttngEventProcessor;
+import org.eclipse.linuxtools.lttng.state.model.LttngTraceState;
+
+/**
+ * Creates instances of specific after state update handlers, per corresponding
+ * event.
+ *
+ * @author alvaro
+ *
+ */
+public class ResourcesAfterUpdateHandlers {
+
+ /**
+ * <p>
+ * Handles: LTT_EVENT_SCHED_SCHEDULE
+ * </p>
+ * Replace C function named "after_schedchange_hook" in eventhooks.c
+ * <p>
+ * Fields: LTT_FIELD_PREV_PID, LTT_FIELD_NEXT_PID, LTT_FIELD_PREV_STATE
+ * </p>
+ *
+ * @return
+ */
+ final ILttngEventProcessor getAfterSchedChangeHandler() {
+ AbsResourcesTRangeUpdate handler = new AbsResourcesTRangeUpdate() {
+
+ public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) {
+
+ // TODO: After sched scheduler handler should implement an
+ // update to the current resource data, similar to
+ // current_hash_data in C
+ // We don't keep track of current hashed resource, we look in
+ // the hash table every time. keeping track of current hash may
+ // improve performance, although needs to be bench marked to
+ // verify
+ // if there's is a real gain.
+
+ // process_list->current_hash_data[trace_num][process_in->cpu] =
+ // hashed_process_data_in;
+
+ return false;
+ }
+ };
+
+ return handler;
+ }
+
+ /**
+ * Drawing stuff ?
+ */
+ // int after_request(void *hook_data, void *call_data)
+ // int after_chunk(void *hook_data, void *call_data)
+ // int before_statedump_end(void *hook_data, void *call_data)
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.resources.evProcessor;
+
+import org.eclipse.linuxtools.lttng.event.LttngEvent;
+import org.eclipse.linuxtools.lttng.state.StateStrings.Channels;
+import org.eclipse.linuxtools.lttng.state.StateStrings.Events;
+import org.eclipse.linuxtools.lttng.state.StateStrings.Fields;
+import org.eclipse.linuxtools.lttng.state.evProcessor.ILttngEventProcessor;
+import org.eclipse.linuxtools.lttng.state.model.LttngTraceState;
+import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEventResource;
+import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEventResource.ResourceTypes;
+import org.eclipse.linuxtools.tmf.event.TmfTimeRange;
+
+/**
+ * Creates instances of specific before state update handlers, per corresponding
+ * event.
+ *
+ * @author alvaro
+ *
+ */
+public class ResourcesBeforeUpdateHandlers {
+
+ /**
+ * <p>
+ * Handles: LTT_EVENT_SCHED_SCHEDULE
+ * </p>
+ * Replace C function named "before_schedchange_hook" in eventhooks.c
+ * <p>
+ * Fields: LTT_FIELD_PREV_PID, LTT_FIELD_NEXT_PID(?), LTT_FIELD_PREV_STATE
+ * (?)
+ * </p>
+ *
+ * @return
+ */
+ final ILttngEventProcessor getBeforeSchedChangeHandler() {
+ AbsResourcesTRangeUpdate handler = new AbsResourcesTRangeUpdate() {
+
+ // @Override
+ public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) {
+ // Create a time range for the cpu.
+ globalProcessBeforeExecmode(trcEvent, traceSt);
+
+ return false;
+ }
+ };
+
+ return handler;
+ }
+
+ /**
+ * <p>
+ * Handles: LTT_EVENT_IRQ_ENTRY, LTT_EVENT_IRQ_EXIT
+ * </p>
+ * Replace C function named "before_execmode_hook_irq" in eventhooks.c
+ *
+ * @return
+ */
+ final ILttngEventProcessor getBeforeExecutionModeIrq() {
+ AbsResourcesTRangeUpdate handler = new AbsResourcesTRangeUpdate() {
+
+ // @Override
+ public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) {
+
+ Long irqId = null;
+
+ // According to Ltt, we should not draw anything if the channel
+ // is the kernel one
+ if (trcEvent.getChannelName().equals(
+ Channels.LTT_CHANNEL_KERNEL)) {
+ return false;
+ } else {
+
+ if (trcEvent.getMarkerName().equals(
+ Events.LTT_EVENT_IRQ_ENTRY.getInName())) {
+ irqId = getAFieldLong(trcEvent, traceSt,
+ Fields.LTT_FIELD_IRQ_ID);
+ } else if (trcEvent.getMarkerName().equals(
+ Events.LTT_EVENT_IRQ_EXIT.getInName())) {
+ long cpu = trcEvent.getCpuId();
+ irqId = traceSt.getCpu_states().get(cpu)
+ .peekFromIrqStack();
+ if (irqId.equals(-1L)) {
+ // nothing to update
+ return false;
+ }
+ }
+
+
+ // softIrqId is the resource id here
+ TimeRangeEventResource localResource = resourcelist_obtain_irq(
+ traceSt, irqId);
+
+ // If the resource is missing in the list, add it
+ if (localResource == null) {
+ TmfTimeRange timeRange = traceSt.getContext()
+ .getTraceTimeWindow();
+ localResource = addLocalResource(timeRange
+ .getStartTime().getValue(), timeRange
+ .getEndTime().getValue(), traceSt.getTraceId(),
+ ResourceTypes.IRQ, irqId, trcEvent
+ .getTimestamp().getValue());
+ }
+
+ // get the start time
+ long stime = localResource.getNext_good_time();
+
+ // Get the resource state mode
+ String irqStateMode = localResource.getStateMode(traceSt);
+
+ // Call the makeDraw function
+ makeDraw(traceSt, stime,
+ trcEvent.getTimestamp().getValue(), localResource,
+ params, irqStateMode);
+
+ // Call the globalProcessBeforeExecmode() after, as
+ // it is needed by all
+ // getBeforeExecmode*SOMETHING*()
+ globalProcessBeforeExecmode(trcEvent, traceSt);
+ }
+ return false;
+ }
+ };
+
+ return handler;
+ }
+
+ /**
+ * <p>
+ * Handles: LTT_EVENT_SOFT_IRQ_RAISE, LTT_EVENT_SOFT_IRQ_ENTRY,
+ * LTT_EVENT_SOFT_IRQ_EXIT,
+ * </p>
+ * Replace C function named "before_execmode_hook_soft_irq" in eventhooks.c
+ * <p>
+ * Fields: LTT_FIELD_SOFT_IRQ_ID
+ * </p>
+ *
+ * @return
+ */
+ final ILttngEventProcessor getBeforeExecutionModeSoftIrq() {
+ AbsResourcesTRangeUpdate handler = new AbsResourcesTRangeUpdate() {
+
+ // @Override
+ public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) {
+
+ Long softIrqId = null;
+
+ // According to Ltt, we should not draw anything if the channel
+ // is the kernel one
+ if (trcEvent.getChannelName().equals(
+ Channels.LTT_CHANNEL_KERNEL)) {
+ return false;
+ } else {
+
+ if ((trcEvent.getMarkerName()
+ .equals(Events.LTT_EVENT_SOFT_IRQ_RAISE.getInName()))
+ || (trcEvent.getMarkerName()
+ .equals(Events.LTT_EVENT_SOFT_IRQ_ENTRY
+ .getInName()))) {
+ softIrqId = getAFieldLong(trcEvent, traceSt,
+ Fields.LTT_FIELD_SOFT_IRQ_ID);
+ } else if (trcEvent.getMarkerName().equals(
+ Events.LTT_EVENT_SOFT_IRQ_EXIT.getInName())) {
+ long cpu = trcEvent.getCpuId();
+ softIrqId = traceSt.getCpu_states().get(cpu)
+ .peekFromSoftIrqStack();
+ if (softIrqId < 0) {
+ // nothing to update
+ return false;
+ }
+ }
+
+ // Add the resource to the resource list
+ // softIrqId is the resource id here
+ TimeRangeEventResource localResource = resourcelist_obtain_soft_irq(
+ traceSt, softIrqId);
+
+ // If the resource is missing in the list, add it
+ if (localResource == null) {
+ TmfTimeRange timeRange = traceSt.getContext()
+ .getTraceTimeWindow();
+ localResource = addLocalResource(timeRange
+ .getStartTime().getValue(), timeRange
+ .getEndTime().getValue(), traceSt.getTraceId(),
+ ResourceTypes.SOFT_IRQ, softIrqId, trcEvent
+ .getTimestamp().getValue());
+ }
+
+ // get the start time
+ long stime = localResource.getNext_good_time();
+
+ // Get the resource state mode
+ String softIrqStateMode = localResource
+ .getStateMode(traceSt);
+
+ // Call the makeDraw function
+ makeDraw(traceSt, stime,
+ trcEvent.getTimestamp().getValue(), localResource,
+ params, softIrqStateMode);
+
+ // Call the globalProcessBeforeExecmode() after, as
+ // it is needed by all
+ // getBeforeExecmode*SOMETHING*()
+ globalProcessBeforeExecmode(trcEvent, traceSt);
+
+ }
+
+ return false;
+ }
+ };
+
+ return handler;
+ }
+
+ /**
+ * <p>
+ * Handles: LTT_EVENT_TRAP_ENTRY, LTT_EVENT_TRAP_EXIT,
+ * LTT_EVENT_PAGE_FAULT_ENTRY, LTT_EVENT_PAGE_FAULT_EXIT,
+ * LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY, LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
+ * </p>
+ * Replace C function named "before_execmode_hook_trap" in eventhooks.c
+ * <p>
+ * Fields: LTT_FIELD_TRAP_ID
+ * </p>
+ *
+ * @return
+ */
+ final ILttngEventProcessor getBeforeExecutionModeTrap() {
+ AbsResourcesTRangeUpdate handler = new AbsResourcesTRangeUpdate() {
+
+ // @Override
+ public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) {
+
+ Long trapId = null;
+
+ // According to Ltt, we should not draw anything if the channel
+ // is the kernel one
+ if (trcEvent.getChannelName().equals(
+ Channels.LTT_CHANNEL_KERNEL)) {
+ return false;
+ } else {
+
+ if ((trcEvent.getMarkerName()
+ .equals(Events.LTT_EVENT_TRAP_ENTRY.getInName()))
+ || (trcEvent.getMarkerName()
+ .equals(Events.LTT_EVENT_PAGE_FAULT_ENTRY
+ .getInName()))
+ || (trcEvent.getMarkerName()
+ .equals(Events.LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
+ .getInName()))) {
+ trapId = getAFieldLong(trcEvent, traceSt,
+ Fields.LTT_FIELD_TRAP_ID);
+ } else if ((trcEvent.getMarkerName()
+ .equals(Events.LTT_EVENT_TRAP_EXIT.getInName()))
+ || (trcEvent.getMarkerName()
+ .equals(Events.LTT_EVENT_PAGE_FAULT_EXIT
+ .getInName()))
+ || (trcEvent.getMarkerName()
+ .equals(Events.LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
+ .getInName()))) {
+ long cpu = trcEvent.getCpuId();
+ trapId = traceSt.getCpu_states().get(cpu)
+ .peekFromTrapStack();
+
+ if (trapId.equals(-1L)) {
+ // Nothing to update
+ return false;
+ }
+ } else {
+ return false;
+ }
+
+ // Add the resource to the resource list
+ // trapId is the resource id here
+ TimeRangeEventResource localResource = resourcelist_obtain_trap(
+ traceSt, trapId);
+
+ // If the resource is missing in the list, add it
+ if (localResource == null) {
+ TmfTimeRange timeRange = traceSt.getContext()
+ .getTraceTimeWindow();
+ localResource = addLocalResource(timeRange
+ .getStartTime().getValue(), timeRange
+ .getEndTime().getValue(), traceSt.getTraceId(),
+ ResourceTypes.TRAP, trapId, trcEvent
+ .getTimestamp().getValue());
+ }
+
+ // Determine the trap state.
+ String trapStateMode = localResource.getStateMode(traceSt);
+
+ long stime = localResource.getNext_good_time();
+ makeDraw(traceSt, stime,
+ trcEvent.getTimestamp().getValue(), localResource,
+ params, trapStateMode);
+
+ // Call the globalProcessBeforeExecmode() after, as
+ // it is needed by all
+ // getBeforeExecmode*SOMETHING*()
+ globalProcessBeforeExecmode(trcEvent, traceSt);
+
+ }
+
+ return false;
+ }
+ };
+
+ return handler;
+ }
+
+ /**
+ * <p>
+ * Handles: LTT_EVENT_REQUEST_ISSUE, LTT_EVENT_REQUEST_COMPLETE
+ * </p>
+ * Replace C function named "before_bdev_event_hook" in eventhooks.c
+ * <p>
+ * Fields: LTT_FIELD_MAJOR, LTT_FIELD_MINOR, LTT_FIELD_OPERATION (?)
+ * </p>
+ *
+ * @return
+ */
+ final ILttngEventProcessor getBeforeBdevEvent() {
+ AbsResourcesTRangeUpdate handler = new AbsResourcesTRangeUpdate() {
+
+ // @Override
+ public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) {
+ Long major = getAFieldLong(trcEvent, traceSt,
+ Fields.LTT_FIELD_MAJOR);
+ Long minor = getAFieldLong(trcEvent, traceSt,
+ Fields.LTT_FIELD_MINOR);
+ // This is useless even in LTTv!
+ // Long oper = getAFieldLong(trcEvent, traceSt,
+ // Fields.LTT_FIELD_OPERATION);
+
+ Long bdevId = getMkdevId(major, minor);
+
+ // According to Lttv, bdevId (obtain from MKDEV macro) is
+ // the id here
+ TimeRangeEventResource localResource = resourcelist_obtain_bdev(
+ traceSt, bdevId);
+
+ if (localResource == null) {
+ TmfTimeRange timeRange = traceSt.getContext()
+ .getTraceTimeWindow();
+ localResource = addLocalResource(timeRange.getStartTime()
+ .getValue(), timeRange.getEndTime().getValue(),
+ traceSt.getTraceId(), ResourceTypes.BDEV, bdevId,
+ trcEvent.getTimestamp().getValue());
+ }
+
+ // get the start time
+ long stime = localResource.getNext_good_time();
+ // Get the resource state mode
+ String bdevStateMode = localResource.getStateMode(traceSt);
+ // Call the makeDraw function
+ makeDraw(traceSt, stime, trcEvent.getTimestamp().getValue(),
+ localResource, params, bdevStateMode);
+
+ return false;
+ }
+ };
+
+ return handler;
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.resources.evProcessor;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.linuxtools.lttng.event.LttngEvent;
+import org.eclipse.linuxtools.lttng.event.LttngSyntheticEvent;
+import org.eclipse.linuxtools.lttng.event.LttngSyntheticEvent.SequenceInd;
+import org.eclipse.linuxtools.lttng.state.StateStrings;
+import org.eclipse.linuxtools.lttng.state.evProcessor.AbsEventToHandlerResolver;
+import org.eclipse.linuxtools.lttng.state.evProcessor.ILttngEventProcessor;
+import org.eclipse.linuxtools.lttng.state.model.LttngTraceState;
+
+/**
+ * Builds a Map from string event name to a processing handler object, the
+ * processors implement the same interface to facilitate transparent methods
+ * call,
+ *
+ * The map key String is the entry point of the raw events. Using a hash speeds
+ * up the resolution of the appropriate processor
+ *
+ * @author alvaro
+ *
+ */
+public class ResourcesEventToHandlerFactory extends AbsEventToHandlerResolver {
+ // ========================================================================
+ // Data
+ // =======================================================================
+ private final Map<String, ILttngEventProcessor> eventNametoBeforeProcessor = new HashMap<String, ILttngEventProcessor>();
+ private final Map<String, ILttngEventProcessor> eventNametoAfterProcessor = new HashMap<String, ILttngEventProcessor>();
+ private ResourcesFinishUpdateHandler finishProcessor = null;
+ private static ResourcesEventToHandlerFactory instance = null;
+ private ResourcesBeforeUpdateHandlers instantiateBeforeHandler = new ResourcesBeforeUpdateHandlers();
+ private ResourcesAfterUpdateHandlers instantiateAfterHandler = new ResourcesAfterUpdateHandlers();
+
+ private ResourcesEventToHandlerFactory() {
+ super();
+ // Create one instance of each individual event handler and add the
+ // instance to the map
+
+ // *** BEFORE HOOKS ***
+ eventNametoBeforeProcessor.put(
+ StateStrings.Events.LTT_EVENT_SCHED_SCHEDULE.getInName(),
+ instantiateBeforeHandler.getBeforeSchedChangeHandler());
+
+ eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_TRAP_ENTRY
+ .getInName(), instantiateBeforeHandler
+ .getBeforeExecutionModeTrap());
+ eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_TRAP_EXIT
+ .getInName(), instantiateBeforeHandler
+ .getBeforeExecutionModeTrap());
+ eventNametoBeforeProcessor.put(
+ StateStrings.Events.LTT_EVENT_PAGE_FAULT_ENTRY.getInName(),
+ instantiateBeforeHandler.getBeforeExecutionModeTrap());
+ eventNametoBeforeProcessor.put(
+ StateStrings.Events.LTT_EVENT_PAGE_FAULT_EXIT.getInName(),
+ instantiateBeforeHandler.getBeforeExecutionModeTrap());
+ eventNametoBeforeProcessor.put(
+ StateStrings.Events.LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
+ .getInName(), instantiateBeforeHandler
+ .getBeforeExecutionModeTrap());
+ eventNametoBeforeProcessor
+ .put(StateStrings.Events.LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
+ .getInName(), instantiateBeforeHandler
+ .getBeforeExecutionModeTrap());
+
+ eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_IRQ_ENTRY
+ .getInName(), instantiateBeforeHandler
+ .getBeforeExecutionModeIrq());
+ eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_IRQ_EXIT
+ .getInName(), instantiateBeforeHandler
+ .getBeforeExecutionModeIrq());
+
+ eventNametoBeforeProcessor.put(
+ StateStrings.Events.LTT_EVENT_SOFT_IRQ_RAISE.getInName(),
+ instantiateBeforeHandler.getBeforeExecutionModeSoftIrq());
+ eventNametoBeforeProcessor.put(
+ StateStrings.Events.LTT_EVENT_SOFT_IRQ_ENTRY.getInName(),
+ instantiateBeforeHandler.getBeforeExecutionModeSoftIrq());
+ eventNametoBeforeProcessor.put(
+ StateStrings.Events.LTT_EVENT_SOFT_IRQ_EXIT.getInName(),
+ instantiateBeforeHandler.getBeforeExecutionModeSoftIrq());
+
+ eventNametoBeforeProcessor.put(
+ StateStrings.Events.LTT_EVENT_REQUEST_ISSUE.getInName(),
+ instantiateBeforeHandler.getBeforeBdevEvent());
+ eventNametoBeforeProcessor.put(
+ StateStrings.Events.LTT_EVENT_REQUEST_COMPLETE.getInName(),
+ instantiateBeforeHandler.getBeforeBdevEvent());
+
+ // *** AFTER HOOKS ***
+ eventNametoAfterProcessor.put(
+ StateStrings.Events.LTT_EVENT_SCHED_SCHEDULE.getInName(),
+ instantiateAfterHandler.getAfterSchedChangeHandler());
+
+ finishProcessor = new ResourcesFinishUpdateHandler();
+ }
+
+ /**
+ *
+ */
+ public static AbsEventToHandlerResolver getInstance() {
+ if (instance == null) {
+ instance = new ResourcesEventToHandlerFactory();
+ }
+ return instance;
+ }
+
+ @Override
+ public ILttngEventProcessor getAfterProcessor(String eventType) {
+ return eventNametoAfterProcessor.get(eventType);
+ }
+
+ @Override
+ public ILttngEventProcessor getBeforeProcessor(String eventType) {
+ return eventNametoBeforeProcessor.get(eventType);
+ }
+
+ @Override
+ public ILttngEventProcessor getfinishProcessor() {
+ return finishProcessor;
+ }
+
+ public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) {
+ if (trcEvent instanceof LttngSyntheticEvent) {
+
+ LttngSyntheticEvent synEvent = (LttngSyntheticEvent) trcEvent;
+ String eventType = synEvent.getMarkerName();
+ ILttngEventProcessor processor = null;
+ if (synEvent.getSynType() == SequenceInd.BEFORE) {
+ processor = getBeforeProcessor(eventType);
+ }
+
+ if (synEvent.getSynType() == SequenceInd.AFTER) {
+ processor = getAfterProcessor(eventType);
+ }
+
+ if (synEvent.getSynType() == SequenceInd.ENDREQ) {
+ processor = getfinishProcessor();
+ }
+
+ if (processor != null) {
+ processor.process(trcEvent, traceSt);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public ILttngEventProcessor getStateUpdaterProcessor(String eventType) {
+ return null;
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.resources.evProcessor;
+
+import org.eclipse.linuxtools.lttng.event.LttngEvent;
+import org.eclipse.linuxtools.lttng.state.StateStrings.Events;
+import org.eclipse.linuxtools.lttng.state.evProcessor.ILttngEventProcessor;
+import org.eclipse.linuxtools.lttng.state.model.LttngTraceState;
+import org.eclipse.linuxtools.lttng.ui.TraceDebug;
+import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEventResource;
+import org.eclipse.linuxtools.tmf.event.TmfTimestamp;
+
+/**
+ * Creates specific finish state data request
+ *
+ * @author alvaro
+ *
+ */
+public class ResourcesFinishUpdateHandler extends
+ AbsResourcesTRangeUpdate
+ implements ILttngEventProcessor {
+
+ public Events getEventHandleType() {
+ // No specific event
+ return null;
+ }
+
+ public boolean process(LttngEvent trcEvent, LttngTraceState traceSt) {
+ // Draw a last known state to the end of the trace
+ TmfTimestamp endReqTime = traceSt.getContext()
+ .getTraceTimeWindow().getEndTime();
+
+ TraceDebug.debug("Number of localResources: "
+ + resContainer.readItems().length);
+
+ // for each existing resource
+ for (TimeRangeEventResource localResource : resContainer
+ .readItems()) {
+
+ // get the start time
+ long stime = localResource.getNext_good_time();
+
+ // Get the resource state mode
+ String stateMode = localResource.getStateMode(traceSt);
+
+ // Insert an instance from previous time to end request time with
+ // the current state
+ makeDraw(traceSt, stime, endReqTime.getValue(),
+ localResource, params, stateMode);
+ }
+
+ return false;
+ }
+
+}
--- /dev/null
+ResourcesView.Action.Filter=Filter\r
+ResourcesView.Action.Filter.ToolTip=Resource Filter options\r
+ResourcesView.Action.Legend=Legend\r
+ResourcesView.Action.Legend.ToolTip=Show Legend\r
+ResourcesView.Action.LoadData=LoadData\r
+ResourcesView.Action.LoadData.ToolTip=Load data from external plug-in\r
+ResourcesView.Action.NextEvent=NextEv\r
+ResourcesView.Action.NextEvent.Tooltip=Next Event\r
+ResourcesView.Action.NextResource=NextResource\r
+ResourcesView.Action.NextResource.ToolTip=Select Next Resource\r
+ResourcesView.Action.PrevEvent=PrevEv\r
+ResourcesView.Action.PrevEvent.Tooltip=Previous Event\r
+ResourcesView.Action.PreviousResource=PreviousResource\r
+ResourcesView.Action.PreviousResource.Tooltip=Select Previous Resource\r
+ResourcesView.Action.Reset=Reset\r
+ResourcesView.Action.Reset.ToolTip=Reset the Time Scale to Default\r
+ResourcesView.Action.Synchronize=Synchronise\r
+ResourcesView.Action.Synchronize.ToolTip=Synchronise by listening to external API selection calls\r
+ResourcesView.Action.ZoomIn=Zoom In\r
+ResourcesView.Action.ZoomIn.Tooltip=Zoom In\r
+ResourcesView.Action.ZoomOut=Zoom Out\r
+ResourcesView.Action.ZoomOut.tooltip=Zoom Out\r
+ResourcesView.Action.ZoomFilter=Zoom Filter\r
+ResourcesView.Action.ZoomFilter.tooltip=Display elements with events within the zoomed time window\r
+ResourcesView.msgSlogan=Resources View\r
+ResourcesView.tmf.UI=org.eclipse.linuxtools.tmf.ui\r
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Alvaro Sanchez-Leon - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.resources.model;
+
+import java.util.HashMap;
+import java.util.Iterator;
+
+import org.eclipse.linuxtools.lttng.TraceDebug;
+import org.eclipse.linuxtools.lttng.ui.model.trange.ItemContainer;
+import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEventResource;
+import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEventResource.ResourceTypes;
+
+/**
+ * Common location to allocate the resources in use by the resource view
+ *
+ * @author alvaro
+ *
+ */
+public class ResourceContainer implements ItemContainer<TimeRangeEventResource> {
+ // ========================================================================
+ // Data
+ // ========================================================================
+ private final HashMap<ResourceKey, TimeRangeEventResource> resources = new HashMap<ResourceKey, TimeRangeEventResource>();
+ private static Integer uniqueId = 0;
+
+
+ // ========================================================================
+ // Constructor
+ // ========================================================================
+ /**
+ * Package level constructor
+ */
+ public ResourceContainer() { }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.linuxtools.lttng.ui.views.resources.model.ItemContainer#addItem
+ * (org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.
+ * ITmfTimeAnalysisEntry)
+ */
+ public void addItem(TimeRangeEventResource newItem) {
+ if (newItem != null) {
+ resources.put( new ResourceKey(newItem),newItem);
+ }
+ }
+
+ // ========================================================================
+ // Methods
+ // ========================================================================
+ /* (non-Javadoc)
+ * @see org.eclipse.linuxtools.lttng.ui.views.resources.model.ItemContainer#getUniqueId()
+ */
+ public Integer getUniqueId() {
+ return uniqueId++;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.linuxtools.lttng.ui.views.resources.model.ItemContainer#readItems()
+ */
+ public TimeRangeEventResource[] readItems() {
+ return resources.values().toArray(
+ new TimeRangeEventResource[resources.size()]);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.linuxtools.lttng.ui.views.resources.model.ItemContainer#clearChildren()
+ */
+ public void clearChildren() {
+ TimeRangeEventResource newRes = null;
+ Iterator<ResourceKey> iterator = resources.keySet().iterator();
+
+ while (iterator.hasNext()) {
+ newRes = resources.get(iterator.next());
+ newRes.reset();
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.linuxtools.lttng.ui.views.resources.model.ItemContainer#clearItems()
+ */
+ public void clearItems() {
+ resources.clear();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.linuxtools.lttng.ui.views.resources.model.ItemContainer#removeItems(java.lang.String)
+ */
+ public void removeItems(String traceId) {
+ ResourceKey newKey = null;
+
+ Iterator<ResourceKey> iterator = resources.keySet().iterator();
+ while (iterator.hasNext()) {
+ newKey = iterator.next();
+
+ if (resources.get(newKey).getTraceId().equals(traceId)) {
+ resources.remove(newKey);
+ }
+ }
+ }
+
+
+ /**
+ * Search by keys (resourceId, traceId and type)
+ * <p>
+ *
+ * A match is returned if the three arguments received match an entry
+ * Otherwise null is returned
+ *
+ * @param searchedId
+ * The ressourceId we are looking for
+ * @param searchedType
+ * The ressourceType we are looking for
+ * @param searchedTraceId
+ * The traceId (trace name?) we are looking for
+ *
+ * @return TimeRangeEventResource
+ */
+ public TimeRangeEventResource findItem(Long searchedId, ResourceTypes searchedType, String searchedTraceId) {
+ // Get the EventResource associated to a key we create here
+ TimeRangeEventResource foundResource = resources.get( new ResourceKey(searchedId, searchedTraceId, searchedType) );
+
+ return foundResource;
+ }
+}
+
+class ResourceKey {
+
+ private TimeRangeEventResource valueRef = null;
+
+ private Long resourceId = null;
+ private String traceId = null;
+ private ResourceTypes type = null;
+
+ @SuppressWarnings("unused")
+ private ResourceKey() { }
+
+ public ResourceKey(TimeRangeEventResource newRef) {
+ valueRef = newRef;
+ }
+
+ public ResourceKey(Long newId, String newTraceId, ResourceTypes newType) {
+ resourceId = newId;
+ traceId = newTraceId;
+ type = newType;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ boolean isSame = false;
+
+ if ( obj instanceof ResourceKey ) {
+ if ( valueRef != null ) {
+ if ( ( ((ResourceKey)obj).getResourceId().equals(valueRef.getResourceId()) ) &&
+ ( ((ResourceKey)obj).getTraceId().equals(valueRef.getTraceId()) ) &&
+ ( ((ResourceKey)obj).getType().equals(valueRef.getType()) ) )
+ {
+ isSame = true;
+ }
+ }
+ else {
+ if ( ( ((ResourceKey)obj).getResourceId().equals(this.resourceId)) &&
+ ( ((ResourceKey)obj).getTraceId().equals(this.traceId)) &&
+ ( ((ResourceKey)obj).getType().equals(this.type)) )
+ {
+ isSame = true;
+ }
+ }
+ }
+ else {
+ TraceDebug.debug("ERROR : The given key is not of the type ProcessKey!" + obj.getClass().toString());
+ }
+
+ return isSame;
+ }
+
+ // *** WARNING : Everything in there work because the check "valueRef != null" is the same for ALL getter
+ // Do NOT change this check without checking.
+ public Long getResourceId() {
+ if ( valueRef != null ) {
+ return valueRef.getResourceId();
+ }
+ else {
+ return resourceId;
+ }
+ }
+
+ public String getTraceId() {
+ if ( valueRef != null ) {
+ return valueRef.getTraceId();
+ }
+ else {
+ return traceId;
+ }
+ }
+
+ public ResourceTypes getType() {
+ if ( valueRef != null ) {
+ return valueRef.getType();
+ }
+ else {
+ return type;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return this.toString().hashCode();
+ }
+
+
+ @Override
+ public String toString() {
+ if ( valueRef != null ) {
+ return (valueRef.getResourceId().toString() + ":" + valueRef.getTraceId().toString() + ":" + valueRef.getType().toString());
+ }
+ return (resourceId + ":" + traceId + ":" + type);
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.resources.model;
+
+import org.eclipse.linuxtools.lttng.ui.views.common.ParamsUpdater;
+
+/**
+ * Instantiates the entry point classes to build the data model for this view
+ *
+ * @author alvaro
+ *
+ */
+public class ResourceModelFactory {
+ // ========================================================================
+ // Data
+ // ========================================================================
+ private static ResourceContainer resContainer = null;
+ private static ParamsUpdater updater = null;
+
+
+ // ========================================================================
+ // Methods
+ // ========================================================================
+ /**
+ * Get Process data container
+ * @return
+ */
+ public static ResourceContainer getResourceContainer() {
+ if (resContainer == null) {
+ resContainer = new ResourceContainer();
+ }
+ return resContainer;
+ }
+
+
+ public static ParamsUpdater getParamsUpdater() {
+ if (updater == null) {
+ updater = new ParamsUpdater();
+ }
+ return updater;
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Yann N. Dauphin (dhaemon@gmail.com) - Implementation
+ * Francois Chouinard (fchouinard@gmail.com) - Initial API
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.statistics;
+
+import java.text.DecimalFormat;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.TreeViewerColumn;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.linuxtools.lttng.request.ILttngSyntEventRequest;
+import org.eclipse.linuxtools.lttng.state.evProcessor.AbsEventToHandlerResolver;
+import org.eclipse.linuxtools.lttng.ui.TraceDebug;
+import org.eclipse.linuxtools.lttng.ui.model.trange.ItemContainer;
+import org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView;
+import org.eclipse.linuxtools.lttng.ui.views.common.ParamsUpdater;
+import org.eclipse.linuxtools.lttng.ui.views.statistics.evProcessor.StatsTimeCountHandlerFactory;
+import org.eclipse.linuxtools.lttng.ui.views.statistics.model.StatisticsTreeNode;
+import org.eclipse.linuxtools.lttng.ui.views.statistics.model.StatisticsTreeRootFactory;
+import org.eclipse.linuxtools.tmf.event.TmfEvent;
+import org.eclipse.linuxtools.tmf.event.TmfTimeRange;
+import org.eclipse.linuxtools.tmf.experiment.TmfExperiment;
+import org.eclipse.linuxtools.tmf.signal.TmfExperimentSelectedSignal;
+import org.eclipse.linuxtools.tmf.signal.TmfSignalHandler;
+import org.eclipse.linuxtools.tmf.trace.ITmfTrace;
+import org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.ITmfTimeAnalysisEntry;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * <b><u>StatisticsView</u></b>
+ * <p>
+ * The Statistics View displays statistics for traces.
+ *
+ * It is implemented according to the MVC pattern. - The model is a
+ * StatisticsTreeNode built by the State Manager. - The view is built with a
+ * TreeViewer. - The controller that keeps model and view synchronised is an
+ * observer of the model.
+ */
+public class StatisticsView extends AbsTimeUpdateView {
+ public static final String ID = "org.eclipse.linuxtools.lttng.ui.views.statistics";
+ private TreeViewer treeViewer;
+
+ // Table column names
+ private final String LEVEL_COLUMN = "Level";
+ private final String EVENTS_COUNT_COLUMN = "Number of Events";
+ private final String CPU_TIME_COLUMN = "CPU Time";
+ private final String CUMULATIVE_CPU_TIME_COLUMN = "Cumulative CPU Time";
+ private final String ELAPSED_TIME_COLUMN = "Elapsed Time";
+
+ // Table column tooltips
+ private final String LEVEL_COLUMN_TIP = "Level at which statistics apply.";
+ private final String EVENTS_COUNT_COLUMN_TIP = "Total amount of events that are tied to given resource.";
+ private final String CPU_TIME_COLUMN_TIP = "Total amount of time the CPU was used excluding wait times(I/O, etc.) at that level.";
+ private final String CUMULATIVE_CPU_TIME_COLUMN_TIP = "Total amount of time between the first and last event excluding wait times in a level.";
+ private final String ELAPSED_TIME_COLUMN_TIP = "Total amount of time the CPU was used including wait times(I/O, etc.) at that level.";
+
+ // Level for which statistics should not be displayed.
+ private Set<String> folderLevels = new HashSet<String>(Arrays
+ .asList(new String[] { "Event Types", "Modes", "Submodes", "CPUs",
+ "Processes", "Functions" }));
+
+ // Levels for which sub-levels should not contain time-related statistics.
+ private Set<String> levelsWithEmptyTime = new HashSet<String>(Arrays
+ .asList(new String[] { "Event Types" }));
+
+ private DecimalFormat decimalFormat = new DecimalFormat("0.#########");
+ private Cursor fwaitCursor = null;
+
+ // Used to draw bar charts in columns.
+ private interface ColumnPercentageProvider {
+ public double getPercentage(StatisticsTreeNode node);
+ }
+
+ /**
+ * Contains all the information necessary to build a column of the table.
+ */
+ private class ColumnData {
+ // Name of the column.
+ public final String header;
+ // Width of the column.
+ public final int width;
+ // Alignment of the column.
+ public final int alignment;
+ // Tooltip of the column.
+ public final String tooltip;
+ // Adapts a StatisticsTreeNode into the content of it's corresponding
+ // cell for that column.
+ public final ColumnLabelProvider labelProvider;
+ // Used to sort elements of this column. Can be null.
+ public final ViewerComparator comparator;
+ // Used to draw bar charts in this column. Can be null.
+ public final ColumnPercentageProvider percentageProvider;
+
+ public ColumnData(String h, int w, int a, String t,
+ ColumnLabelProvider l, ViewerComparator c,
+ ColumnPercentageProvider p) {
+ header = h;
+ width = w;
+ alignment = a;
+ tooltip = t;
+ labelProvider = l;
+ comparator = c;
+ percentageProvider = p;
+ }
+ };
+
+ // List that will be used to create the table.
+ private ColumnData[] columnDataList = new ColumnData[] {
+ new ColumnData(LEVEL_COLUMN, 200, SWT.LEFT, LEVEL_COLUMN_TIP,
+ new ColumnLabelProvider() {
+ @Override
+ public String getText(Object element) {
+ return ((StatisticsTreeNode) element).getKey();
+ }
+
+ @Override
+ public Image getImage(Object element) {
+ StatisticsTreeNode node = (StatisticsTreeNode) element;
+ if (folderLevels.contains(node.getKey())) {
+ return PlatformUI.getWorkbench()
+ .getSharedImages().getImage(
+ ISharedImages.IMG_OBJ_FOLDER);
+ } else {
+ return PlatformUI.getWorkbench()
+ .getSharedImages().getImage(
+ ISharedImages.IMG_OBJ_ELEMENT);
+ }
+ }
+ }, new ViewerComparator() {
+ @Override
+ public int compare(Viewer viewer, Object e1, Object e2) {
+ StatisticsTreeNode n1 = (StatisticsTreeNode) e1;
+ StatisticsTreeNode n2 = (StatisticsTreeNode) e2;
+
+ return n1.getKey().compareTo(n2.getKey());
+ }
+ }, null),
+ new ColumnData(EVENTS_COUNT_COLUMN, 125, SWT.LEFT,
+ EVENTS_COUNT_COLUMN_TIP, new ColumnLabelProvider() {
+ @Override
+ public String getText(Object element) {
+ StatisticsTreeNode node = (StatisticsTreeNode) element;
+ if (!folderLevels.contains(node.getKey())) {
+ return Long.toString(node.getValue().nbEvents);
+ } else {
+ return "";
+ }
+ }
+ }, new ViewerComparator() {
+ @Override
+ public int compare(Viewer viewer, Object e1, Object e2) {
+ StatisticsTreeNode n1 = (StatisticsTreeNode) e1;
+ StatisticsTreeNode n2 = (StatisticsTreeNode) e2;
+
+ return (int) (n1.getValue().nbEvents - n2
+ .getValue().nbEvents);
+ }
+ }, new ColumnPercentageProvider() {
+ public double getPercentage(StatisticsTreeNode node) {
+ StatisticsTreeNode parent = node;
+ do {
+ parent = parent.getParent();
+ } while (parent != null
+ && parent.getValue().nbEvents == 0);
+
+ if (parent == null) {
+ return 0;
+ } else {
+ return (double) node.getValue().nbEvents
+ / parent.getValue().nbEvents;
+ }
+ }
+ }),
+ new ColumnData(CPU_TIME_COLUMN, 125, SWT.LEFT, CPU_TIME_COLUMN_TIP,
+ new ColumnLabelProvider() {
+ @Override
+ public String getText(Object element) {
+ StatisticsTreeNode node = (StatisticsTreeNode) element;
+
+ if (folderLevels.contains(node.getKey())) {
+ return "";
+ } else if (node.getParent() != null
+ && levelsWithEmptyTime.contains(node
+ .getParent().getKey())) {
+ return "";
+ } else {
+ return decimalFormat
+ .format(node.getValue().cpuTime
+ / Math.pow(10, 9));
+ }
+ }
+ }, null, null),
+ new ColumnData(CUMULATIVE_CPU_TIME_COLUMN, 155, SWT.LEFT,
+ CUMULATIVE_CPU_TIME_COLUMN_TIP, new ColumnLabelProvider() {
+ @Override
+ public String getText(Object element) {
+ StatisticsTreeNode node = (StatisticsTreeNode) element;
+ if (folderLevels.contains(node.getKey())) {
+ return "";
+ } else if (node.getParent() != null
+ && levelsWithEmptyTime.contains(node
+ .getParent().getKey())) {
+ return "";
+ } else {
+ return decimalFormat
+ .format(node.getValue().cumulativeCpuTime
+ / Math.pow(10, 9));
+ }
+ }
+ }, null, null),
+ new ColumnData(ELAPSED_TIME_COLUMN, 100, SWT.LEFT,
+ ELAPSED_TIME_COLUMN_TIP, new ColumnLabelProvider() {
+ @Override
+ public String getText(Object element) {
+ StatisticsTreeNode node = (StatisticsTreeNode) element;
+ if (folderLevels.contains(node.getKey())) {
+ return "";
+ } else if (node.getParent() != null
+ && levelsWithEmptyTime.contains(node
+ .getParent().getKey())) {
+ return "";
+ } else {
+ return decimalFormat
+ .format(node.getValue().elapsedTime
+ / Math.pow(10, 9));
+ }
+ }
+ }, null, null) };
+
+ /**
+ * Adapter TreeViewers can use to interact with StatisticsTreeNode objects.
+ *
+ * @see org.eclipse.jface.viewers.ITreeContentProvider
+ */
+ class TreeContentProvider implements ITreeContentProvider {
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang
+ * .Object)
+ */
+ public Object[] getChildren(Object parentElement) {
+ return ((StatisticsTreeNode) parentElement).getChildren().toArray();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang
+ * .Object)
+ */
+ public Object getParent(Object element) {
+ return ((StatisticsTreeNode) element).getParent();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang
+ * .Object)
+ */
+ public boolean hasChildren(Object element) {
+ return ((StatisticsTreeNode) element).hasChildren();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.jface.viewers.IStructuredContentProvider#getElements(
+ * java.lang.Object)
+ */
+ public Object[] getElements(Object inputElement) {
+ return getChildren(inputElement);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.IContentProvider#dispose()
+ */
+ public void dispose() {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse
+ * .jface.viewers.Viewer, java.lang.Object, java.lang.Object)
+ */
+ // @Override
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+ }
+
+ public StatisticsView(String viewName) {
+ super(viewName);
+ }
+
+ public StatisticsView() {
+ this("StatisticsView");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets
+ * .Composite)
+ */
+ @Override
+ public void createPartControl(Composite parent) {
+ parent.setLayout(new FillLayout());
+
+ treeViewer = new TreeViewer(parent, SWT.BORDER | SWT.H_SCROLL
+ | SWT.V_SCROLL);
+ treeViewer.setContentProvider(new TreeContentProvider());
+ treeViewer.getTree().setHeaderVisible(true);
+ treeViewer.setUseHashlookup(true);
+
+ for (final ColumnData columnData : columnDataList) {
+ final TreeViewerColumn treeColumn = new TreeViewerColumn(
+ treeViewer, columnData.alignment);
+ treeColumn.getColumn().setText(columnData.header);
+ treeColumn.getColumn().setWidth(columnData.width);
+ treeColumn.getColumn().setToolTipText(columnData.tooltip);
+ if (columnData.comparator != null) {
+ treeColumn.getColumn().addSelectionListener(
+ new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ if (treeViewer.getTree().getSortDirection() == SWT.UP
+ || treeViewer.getTree().getSortColumn() != treeColumn
+ .getColumn()) {
+ treeViewer
+ .setComparator(columnData.comparator);
+ treeViewer.getTree().setSortDirection(
+ SWT.DOWN);
+ } else {
+ treeViewer
+ .setComparator(new ViewerComparator() {
+ @Override
+ public int compare(
+ Viewer viewer,
+ Object e1, Object e2) {
+ return -1
+ * columnData.comparator
+ .compare(
+ viewer,
+ e1,
+ e2);
+ }
+ });
+ treeViewer.getTree().setSortDirection(
+ SWT.UP);
+ }
+ treeViewer.getTree().setSortColumn(
+ treeColumn.getColumn());
+ }
+ });
+ }
+ treeColumn.setLabelProvider(columnData.labelProvider);
+ }
+
+ // Handler that will draw the bar charts.
+ treeViewer.getTree().addListener(SWT.EraseItem, new Listener() {
+ // @Override
+ public void handleEvent(Event event) {
+ if (columnDataList[event.index].percentageProvider != null) {
+ StatisticsTreeNode node = (StatisticsTreeNode) event.item
+ .getData();
+
+ double percentage = columnDataList[event.index].percentageProvider
+ .getPercentage(node);
+ if (percentage == 0) {
+ return;
+ }
+
+ if ((event.detail & SWT.SELECTED) > 0) {
+ Color oldForeground = event.gc.getForeground();
+ event.gc.setForeground(event.item.getDisplay()
+ .getSystemColor(SWT.COLOR_LIST_SELECTION));
+ event.gc.fillRectangle(event.x, event.y, event.width,
+ event.height);
+ event.gc.setForeground(oldForeground);
+ event.detail &= ~SWT.SELECTED;
+ }
+
+ int barWidth = (int) ((treeViewer.getTree().getColumn(1)
+ .getWidth() - 8) * percentage);
+ int oldAlpha = event.gc.getAlpha();
+ Color oldForeground = event.gc.getForeground();
+ Color oldBackground = event.gc.getBackground();
+ event.gc.setAlpha(64);
+ event.gc.setForeground(event.item.getDisplay()
+ .getSystemColor(SWT.COLOR_BLUE));
+ event.gc.setBackground(event.item.getDisplay()
+ .getSystemColor(SWT.COLOR_LIST_BACKGROUND));
+ event.gc.fillGradientRectangle(event.x, event.y, barWidth,
+ event.height, true);
+ event.gc.drawRectangle(event.x, event.y, barWidth,
+ event.height);
+ event.gc.setForeground(oldForeground);
+ event.gc.setBackground(oldBackground);
+ event.gc.setAlpha(oldAlpha);
+ event.detail &= ~SWT.BACKGROUND;
+ }
+ }
+ });
+
+ treeViewer.setComparator(columnDataList[0].comparator);
+ treeViewer.getTree().setSortColumn(treeViewer.getTree().getColumn(0));
+ treeViewer.getTree().setSortDirection(SWT.DOWN);
+
+ // Read current data if any available
+ TmfExperiment<?> experiment = TmfExperiment.getCurrentExperiment();
+ if (experiment != null) {
+ requestData(experiment);
+ } else {
+ TraceDebug.debug("No selected experiment information available");
+ }
+ }
+
+ @Override
+ public void dispose() {
+ super.dispose();
+ if (fwaitCursor != null) {
+ fwaitCursor.dispose();
+ }
+
+ // clean the model
+ StatisticsTreeRootFactory.removeAll();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
+ */
+ @Override
+ public void setFocus() {
+ treeViewer.getTree().setFocus();
+ }
+
+
+ /**
+ * @return
+ */
+ public AbsEventToHandlerResolver getEventProcessor() {
+ return StatsTimeCountHandlerFactory.getInstance();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView#waitCursor
+ * (boolean)
+ */
+ protected void waitCursor(final boolean waitInd) {
+ if (treeViewer == null) {
+ return;
+ }
+
+ Display display = treeViewer.getControl().getDisplay();
+ if (fwaitCursor == null) {
+ fwaitCursor = new Cursor(display, SWT.CURSOR_WAIT);
+ }
+
+ // Perform the updates on the UI thread
+ display.asyncExec(new Runnable() {
+ public void run() {
+ Cursor cursor = null; /* indicates default */
+ if (waitInd) {
+ cursor = fwaitCursor;
+ }
+ treeViewer.getControl().setCursor(cursor);
+ }
+ });
+ }
+
+ @Override
+ public void ModelUpdatePrep(TmfTimeRange timeRange, boolean clearAllData) {
+ Object input = treeViewer.getInput();
+ if (input != null && input instanceof StatisticsTreeNode) {
+ ((StatisticsTreeNode) input).reset();
+ treeViewer.getTree().getDisplay().asyncExec(new Runnable() {
+ // @Override
+ public void run() {
+ treeViewer.refresh();
+ }
+ });
+ }
+ }
+
+ @Override
+ public void modelInputChanged(ILttngSyntEventRequest request, boolean complete) {
+ treeViewer.getTree().getDisplay().asyncExec(new Runnable() {
+ // @Override
+ public void run() {
+ treeViewer.refresh();
+ }
+ });
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView#
+ * modelIncomplete
+ * (org.eclipse.linuxtools.lttng.request.ILttngSyntEventRequest)
+ */
+ @Override
+ public void modelIncomplete(ILttngSyntEventRequest request) {
+ Object input = treeViewer.getInput();
+ if (input != null && input instanceof StatisticsTreeNode) {
+ // The data from this experiment is invalid and shall be removed to
+ // refresh upon next selection
+ String name = ((StatisticsTreeNode) input).getKey();
+ StatisticsTreeRootFactory.removeStatTreeRoot(name);
+ }
+ }
+
+ /**
+ * @param signal
+ */
+ @TmfSignalHandler
+ public void experimentSelected(TmfExperimentSelectedSignal<? extends TmfEvent> signal) {
+ if (signal != null) {
+ TmfExperiment<?> experiment = signal.getExperiment();
+ String experimentName = experiment.getName();
+
+ if (StatisticsTreeRootFactory.containsTreeRoot(experimentName)) {
+ // The experiment root is already present
+ StatisticsTreeNode experimentTreeNode = StatisticsTreeRootFactory.getStatTreeRoot(experimentName);
+
+ ITmfTrace[] traces = experiment.getTraces();
+
+ // check if there is partial data loaded in the experiment
+ int numTraces = experiment.getTraces().length;
+ int numNodeTraces = experimentTreeNode.getNbChildren();
+
+ if (numTraces == numNodeTraces) {
+ boolean same = true;
+ // Detect if the experiment contains the same traces as when
+ // previously selected
+ for (int i = 0; i < numTraces; i++) {
+ String traceName = traces[i].getName();
+ if (!experimentTreeNode.containsChild(traceName)) {
+ same = false;
+ break;
+ }
+ }
+
+ if (same) {
+ // no need to reload data, all traces are already loaded
+ treeViewer.setInput(experimentTreeNode);
+ return;
+ }
+ }
+ }
+
+ // if the data is not available or has changed, reload it
+ requestData(experiment);
+ }
+ }
+
+ /**
+ * @param experiment
+ */
+ private void requestData(TmfExperiment<?> experiment) {
+ if (experiment != null) {
+ StatisticsTreeNode treeModelRoot = StatisticsTreeRootFactory.getStatTreeRoot(experiment.getName());
+
+ // if the model has contents, clear to start over
+ if (treeModelRoot.hasChildren()) {
+ treeModelRoot.reset();
+ }
+
+ // set input to a clean data model
+ treeViewer.setInput(treeModelRoot);
+ TmfTimeRange experimentTRange = experiment.getTimeRange();
+
+ // send the initial request, to start filling up model
+ dataRequest(experimentTRange, experimentTRange, true);
+ } else {
+ TraceDebug.debug("No selected experiment information available");
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView#displayModel
+ * (org.eclipse.linuxtools.tmf.ui.viewers.timeAnalysis.model.
+ * ITmfTimeAnalysisEntry[], long, long, boolean, long, long,
+ * java.lang.Object)
+ */
+ @Override
+ protected void displayModel(ITmfTimeAnalysisEntry[] items, long startBoundTime, long endBoundTime,
+ boolean updateTimeBounds, long startVisibleWindow, long endVisibleWindow, Object source) {
+ // No applicable to statistics view
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.linuxtools.lttng.ui.views.common.AbsTimeUpdateView#
+ * getParamsUpdater()
+ */
+ @Override
+ protected ParamsUpdater getParamsUpdater() {
+ // Not applicable to statistics view
+ return null;
+ }
+
+ @Override
+ protected ItemContainer<?> getItemContainer() {
+ // Not applicable to statistics view
+ return null;
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Yann N. Dauphin (dhaemon@gmail.com) - Implementation for stats
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.statistics.evProcessor;
+
+import org.eclipse.linuxtools.lttng.event.LttngEvent;
+import org.eclipse.linuxtools.lttng.state.StateStrings.Events;
+import org.eclipse.linuxtools.lttng.state.StateStrings.ExecutionMode;
+import org.eclipse.linuxtools.lttng.state.StateStrings.ProcessStatus;
+import org.eclipse.linuxtools.lttng.state.evProcessor.ILttngEventProcessor;
+import org.eclipse.linuxtools.lttng.state.model.LttngProcessState;
+import org.eclipse.linuxtools.lttng.state.model.LttngTraceState;
+import org.eclipse.linuxtools.lttng.ui.views.statistics.model.StatisticsTreeRootFactory;
+import org.eclipse.linuxtools.lttng.ui.views.statistics.model.StatisticsTreeNode;
+
+abstract class AbstractStatsEventHandler implements ILttngEventProcessor {
+ private Events eventType;
+
+ public AbstractStatsEventHandler(Events eventType) {
+ super();
+ this.eventType = eventType;
+ }
+
+ /**
+ * @return root of of the tree for this experiment.
+ */
+ protected StatisticsTreeNode getStatisticsTree(LttngTraceState trcState) {
+ String experimentName = trcState.getContext().getExperimentName();
+ StatisticsTreeNode tree = StatisticsTreeRootFactory.getStatTreeRoot(experimentName);
+ return tree;
+ }
+
+ /**
+ * @return list of paths that should be updated for this event.
+ */
+ protected String[][] getRelevantPaths(LttngEvent event,
+ LttngTraceState traceState) {
+ String trace = traceState.getContext().getTraceId();
+
+ Long cpu = event.getCpuId();
+
+ LttngProcessState process = traceState.getRunning_process().get(
+ cpu);
+
+ String processName = getPocessName(process);
+
+ String mode = process.getState().getExec_mode().getInName();
+
+ String submode = process.getState().getExec_submode();
+
+ Long function = process.getCurrent_function();
+
+ // String type = event.getType().getTypeId();
+
+ String[][] paths = {
+ {trace},
+ {trace, "Modes", mode},
+ {trace, "Modes", mode, "Submodes", submode},
+ {trace, "Processes", processName},
+ {trace, "Processes", processName, "CPUs", cpu.toString()},
+ {trace, "Processes", processName, "CPUs", cpu.toString(), "Functions", function.toString()},
+ {trace, "Processes", processName, "CPUs", cpu.toString(), "Modes", mode},
+ {trace, "Processes", processName, "CPUs", cpu.toString(), "Modes", mode, "Submodes", submode},
+ {trace, "Processes", processName, "Modes", mode},
+ {trace, "Processes", processName, "Modes", mode, "Submodes", submode},
+ {trace, "CPUs", cpu.toString()},
+ {trace, "CPUs", cpu.toString(), "Modes", mode},
+ {trace, "CPUs", cpu.toString(), "Modes", mode, "Submodes", submode},
+ };
+ return paths;
+ }
+
+ /**
+ * @return list of event types paths that should be updated for this event.
+ */
+ protected String[][] getRelevantEventTypesPaths(LttngEvent event,
+ LttngTraceState traceState) {
+ String trace = traceState.getContext().getTraceId();
+
+ Long cpu = event.getCpuId();
+
+ LttngProcessState process = traceState.getRunning_process().get(
+ cpu);
+
+ String processName = getPocessName(process);
+
+ String mode = process.getState().getExec_mode().getInName();
+
+ String submode = process.getState().getExec_submode();
+
+ Long function = process.getCurrent_function();
+
+ String type = event.getType().getTypeId();
+
+ String[][] paths = {
+ {trace, "Event Types", type},
+ {trace, "Modes", mode, "Event Types", type},
+ {trace, "Modes", mode, "Submodes", submode, "Event Types", type},
+ {trace, "Processes", processName, "Event Types", type},
+ {trace, "Processes", processName, "CPUs", cpu.toString(), "Event Types", type},
+ {trace, "Processes", processName, "CPUs", cpu.toString(), "Functions", function.toString(), "Event Types", type},
+ {trace, "Processes", processName, "CPUs", cpu.toString(), "Modes", mode, "Event Types", type},
+ {trace, "Processes", processName, "CPUs", cpu.toString(), "Modes", mode, "Submodes", submode, "Event Types", type},
+ {trace, "Processes", processName, "Modes", mode, "Event Types", type},
+ {trace, "Processes", processName, "Modes", mode, "Submodes", submode, "Event Types", type},
+ {trace, "CPUs", cpu.toString(), "Event Types", type},
+ {trace, "CPUs", cpu.toString(), "Modes", mode, "Event Types", type},
+ {trace, "CPUs", cpu.toString(), "Modes", mode, "Submodes", submode, "Event Types", type},
+ };
+ return paths;
+ }
+
+ /**
+ * @return name of the process. Returns special string if the name is "".
+ */
+ private String getPocessName(LttngProcessState process) {
+ if (process.getName() == null) {
+ return "Unknown process";
+ }
+ if (process.getName() == "") {
+ return process.getPid().toString();
+ }
+ else {
+ return process.getName();
+ }
+ }
+
+ /**
+ * Increase the NbEvents counter of this node.
+ */
+ protected void increaseNbEvents(StatisticsTreeNode node) {
+ node.getValue().nbEvents++;
+ }
+
+ /**
+ * Increase the CPU Time according to the trace state.
+ */
+ protected void increaseCPUTime(StatisticsTreeNode node, LttngEvent event,
+ LttngTraceState traceState) {
+ Long cpu = event.getCpuId();
+
+ LttngProcessState process = traceState.getRunning_process().get(
+ cpu);
+
+ if (process.getState().getProc_status().equals(ProcessStatus.LTTV_STATE_RUN) &&
+ !process.getState().getExec_mode().equals(ExecutionMode.LTTV_STATE_MODE_UNKNOWN)) {
+ node.getValue().cpuTime += event.getTimestamp().getValue()
+ - process.getState().getChange_LttTime();
+ }
+ }
+
+ /**
+ * Increase the Elapsed Time according to the trace state.
+ */
+ protected void increaseElapsedTime(StatisticsTreeNode node, LttngEvent event,
+ LttngTraceState traceState) {
+ Long cpu = event.getCpuId();
+
+ LttngProcessState process = traceState.getRunning_process().get(
+ cpu);
+
+ if (!process.getState().getExec_mode().equals(ExecutionMode.LTTV_STATE_MODE_UNKNOWN)) {
+ node.getValue().elapsedTime += event.getTimestamp().getValue()
+ - process.getState().getEntry_LttTime();
+ }
+ }
+
+ /**
+ * Increase the Cumulative CPU Time according to the trace state.
+ */
+ protected void increaseCumulativeCPUTime(StatisticsTreeNode node, LttngEvent event,
+ LttngTraceState traceState) {
+ Long cpu = event.getCpuId();
+
+ LttngProcessState process = traceState.getRunning_process().get(
+ cpu);
+
+ if (!process.getState().getExec_mode().equals(ExecutionMode.LTTV_STATE_MODE_UNKNOWN)) {
+ long cumulativeCpuTime = process.getState().getCum_cpu_time();
+ long delta = event.getTimestamp().getValue() - process.getState().getEntry_LttTime();
+ process.getState().setCum_cpu_time(cumulativeCpuTime + delta);
+ node.getValue().cumulativeCpuTime += process.getState().getCum_cpu_time();
+ }
+ else if (process.getState().getProc_status().equals(ProcessStatus.LTTV_STATE_RUN) &&
+ !process.getState().getExec_mode().equals(ExecutionMode.LTTV_STATE_MODE_UNKNOWN)) {
+ long cumulativeCpuTime = process.getState().getCum_cpu_time();
+ long delta = event.getTimestamp().getValue() - process.getState().getChange_LttTime();
+ process.getState().setCum_cpu_time(cumulativeCpuTime + delta);
+ node.getValue().cumulativeCpuTime += process.getState().getCum_cpu_time();
+ }
+ }
+
+ /**
+ * Increase the State-bound Cumulative CPU Time according to the trace state.
+ */
+ protected void increaseStateCumulativeCPUTime(LttngEvent event,
+ LttngTraceState traceState) {
+ Long cpu = event.getCpuId();
+
+ LttngProcessState process = traceState.getRunning_process().get(cpu);
+
+ if (process.getState().getProc_status().equals(ProcessStatus.LTTV_STATE_RUN) &&
+ !process.getState().getExec_mode().equals(ExecutionMode.LTTV_STATE_MODE_UNKNOWN)) {
+ long cumulativeCpuTime = process.getState().getCum_cpu_time();
+ long delta = event.getTimestamp().getValue() - process.getState().getChange_LttTime();
+ process.getState().setCum_cpu_time(cumulativeCpuTime + delta);
+ }
+ }
+
+// @Override
+ public Events getEventHandleType() {
+ return eventType;
+ }
+
+ protected void stepCount(LttngEvent event, LttngTraceState traceState) {
+ StatisticsTreeNode root = getStatisticsTree(traceState);
+
+ String[][] paths = getRelevantPaths(event, traceState);
+
+ for (String[] path : paths) {
+ StatisticsTreeNode node = root.getOrCreateChildFromPath(path);
+
+ increaseNbEvents(node);
+ }
+
+ String[][] eventTypesPaths = getRelevantEventTypesPaths(event, traceState);
+
+ for (String[] path : eventTypesPaths) {
+ StatisticsTreeNode node = root.getOrCreateChildFromPath(path);
+
+ increaseNbEvents(node);
+ }
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Yann N. Dauphin (dhaemon@gmail.com) - Implementation for stats
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.statistics.evProcessor;
+
+import org.eclipse.linuxtools.lttng.event.LttngEvent;
+import org.eclipse.linuxtools.lttng.state.StateStrings.Events;
+import org.eclipse.linuxtools.lttng.state.model.LttngTraceState;
+import org.eclipse.linuxtools.lttng.ui.views.statistics.model.StatisticsTreeNode;
+
+class StatsModeChangeHandler extends AbstractStatsEventHandler {
+
+ public StatsModeChangeHandler(Events eventType) {
+ super(eventType);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.linuxtools.lttng.state.evProcessor.IEventProcessing#process(org.eclipse.linuxtools.lttng.event.LttngEvent, org.eclipse.linuxtools.lttng.state.model.LttngTraceState)
+ */
+ public boolean process(LttngEvent event, LttngTraceState traceState) {
+ StatisticsTreeNode root = getStatisticsTree(traceState);
+
+ String[][] paths = getRelevantPaths(event, traceState);
+
+ for (String[] path : paths) {
+ StatisticsTreeNode node = root.getOrCreateChildFromPath(path);
+
+ increaseCPUTime(node, event, traceState);
+
+ increaseStateCumulativeCPUTime(event, traceState);
+ }
+
+ return false;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Yann N. Dauphin (dhaemon@gmail.com) - Implementation for stats
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.statistics.evProcessor;
+
+import org.eclipse.linuxtools.lttng.event.LttngEvent;
+import org.eclipse.linuxtools.lttng.state.StateStrings.Events;
+import org.eclipse.linuxtools.lttng.state.model.LttngTraceState;
+import org.eclipse.linuxtools.lttng.ui.views.statistics.model.StatisticsTreeNode;
+
+class StatsModeEndHandler extends AbstractStatsEventHandler {
+
+ public StatsModeEndHandler(Events eventType) {
+ super(eventType);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.linuxtools.lttng.state.evProcessor.IEventProcessing#process(org.eclipse.linuxtools.lttng.event.LttngEvent, org.eclipse.linuxtools.lttng.state.model.LttngTraceState)
+ */
+ public boolean process(LttngEvent event, LttngTraceState traceState) {
+ StatisticsTreeNode root = getStatisticsTree(traceState);
+
+ String[][] paths = getRelevantPaths(event, traceState);
+
+ for (String[] path : paths) {
+ StatisticsTreeNode node = root.getOrCreateChildFromPath(path);
+
+ increaseCPUTime(node, event, traceState);
+
+ increaseElapsedTime(node, event, traceState);
+
+ increaseCumulativeCPUTime(node, event, traceState);
+ }
+
+ return false;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Yann N. Dauphin (dhaemon@gmail.com) - Implementation for stats
+ * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.statistics.evProcessor;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.linuxtools.lttng.state.StateStrings;
+import org.eclipse.linuxtools.lttng.state.evProcessor.AbsEventToHandlerResolver;
+import org.eclipse.linuxtools.lttng.state.evProcessor.ILttngEventProcessor;
+
+/**
+ * Provide the handlers that will count the CPU Time, Cumulative CPU Time and
+ * Elapsed Time and update the appropriate tree.
+ *
+ * Builds a Map from string event name to a processing handler object, the
+ * processors implement the same interface to facilitate transparent methods
+ * call,
+ *
+ * The map key STring is the entry point of the raw events, using a hash speeds
+ * up the resolution of the appropriate processor
+ *
+ * @author alvaro
+ *
+ */
+public class StatsTimeCountHandlerFactory extends AbsEventToHandlerResolver {
+ // ========================================================================
+ // Data
+ // =======================================================================
+ private final Map<String, ILttngEventProcessor> eventNametoBeforeProcessor = new HashMap<String, ILttngEventProcessor>();
+ ILttngEventProcessor afterhandler;
+ private static StatsTimeCountHandlerFactory instance = null;
+ private StatsTimeCountHandlers instantiateHandler = new StatsTimeCountHandlers();
+
+ // ========================================================================
+ // Constructors
+ // =======================================================================
+ private StatsTimeCountHandlerFactory() {
+ super();
+ //create one instance of each individual event handler and add the instance to the map
+ eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_SYSCALL_ENTRY
+ .getInName(), instantiateHandler.getSyscallEntryBeforeHandler());
+
+ eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_SYSCALL_EXIT
+ .getInName(), instantiateHandler.getsySyscallExitBeforeHandler());
+
+ eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_TRAP_ENTRY
+ .getInName(), instantiateHandler.getTrapEntryBeforeHandler());
+
+ eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_TRAP_EXIT
+ .getInName(), instantiateHandler.getTrapExitBeforeHandler());
+
+ eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_PAGE_FAULT_ENTRY
+ .getInName(), instantiateHandler.getTrapEntryBeforeHandler());
+
+ eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_PAGE_FAULT_EXIT
+ .getInName(), instantiateHandler.getTrapExitBeforeHandler());
+
+ eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
+ .getInName(), instantiateHandler.getTrapEntryBeforeHandler());
+
+ eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
+ .getInName(), instantiateHandler.getTrapExitBeforeHandler());
+
+ eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_IRQ_ENTRY
+ .getInName(), instantiateHandler.getIrqEntryBeforeHandler());
+
+ eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_IRQ_EXIT
+ .getInName(), instantiateHandler.getIrqExitBeforeHandler());
+
+ eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_SOFT_IRQ_ENTRY
+ .getInName(), instantiateHandler.getSoftIrqEntryBeforeHandler());
+
+ eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_SOFT_IRQ_EXIT
+ .getInName(), instantiateHandler.getSoftIrqExitBeforeHandler());
+
+ eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_FUNCTION_ENTRY
+ .getInName(), instantiateHandler.getFunctionEntryBeforeHandler());
+
+ eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_FUNCTION_EXIT
+ .getInName(), instantiateHandler.getFunctionExitBeforeHandler());
+
+ eventNametoBeforeProcessor.put(StateStrings.Events.LTT_EVENT_SCHED_SCHEDULE
+ .getInName(), instantiateHandler.getSchedChangeBeforeHandler());
+
+ afterhandler = instantiateHandler.getAfterHandler();
+
+ }
+
+ // ========================================================================
+ // Public methods
+ // =======================================================================
+ /**
+ * The event processors are common to all traces an multiple instances will
+ * use more memory unnecessarily
+ *
+ * @return
+ */
+ public static AbsEventToHandlerResolver getInstance() {
+ if (instance == null) {
+ instance = new StatsTimeCountHandlerFactory();
+ }
+ return instance;
+ }
+
+
+ @Override
+ public ILttngEventProcessor getAfterProcessor(String eventType) {
+ return afterhandler;
+ }
+
+ @Override
+ public ILttngEventProcessor getBeforeProcessor(String eventType) {
+ return eventNametoBeforeProcessor.get(eventType);
+ }
+
+ @Override
+ public ILttngEventProcessor getfinishProcessor() {
+ // No finishing processor used
+ return null;
+ }
+
+ @Override
+ public ILttngEventProcessor getStateUpdaterProcessor(String eventType) {
+ return null;
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Yann N. Dauphin (dhaemon@gmail.com) - Implementation for stats
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.statistics.evProcessor;
+
+import org.eclipse.linuxtools.lttng.event.LttngEvent;
+import org.eclipse.linuxtools.lttng.state.StateStrings;
+import org.eclipse.linuxtools.lttng.state.StateStrings.Events;
+import org.eclipse.linuxtools.lttng.state.evProcessor.ILttngEventProcessor;
+import org.eclipse.linuxtools.lttng.state.model.LttngTraceState;
+
+/**
+ * Process the system call entry event
+ *
+ * @author alvaro
+ *
+ */
+class StatsTimeCountHandlers {
+
+ /**
+ * Method to handle the event: LTT_EVENT_SYSCALL_ENTRY
+ *
+ * @return
+ */
+ final ILttngEventProcessor getSyscallEntryBeforeHandler() {
+ AbstractStatsEventHandler handler = new StatsModeChangeHandler(Events.LTT_EVENT_SYSCALL_ENTRY);
+ return handler;
+ }
+
+ /**
+ * Method to handle the event: LTT_EVENT_SYSCALL_EXIT
+ *
+ * @return
+ */
+ final ILttngEventProcessor getsySyscallExitBeforeHandler() {
+ AbstractStatsEventHandler handler = new StatsModeEndHandler(Events.LTT_EVENT_SYSCALL_EXIT);
+ return handler;
+ }
+
+ /**
+ * Method to handle the event: LTT_EVENT_TRAP_ENTRY
+ *
+ * @return
+ */
+ final ILttngEventProcessor getTrapEntryBeforeHandler() {
+ AbstractStatsEventHandler handler = new StatsModeChangeHandler(Events.LTT_EVENT_TRAP_ENTRY);
+ return handler;
+ }
+
+ /**
+ * Method to handle the event: LTT_EVENT_TRAP_EXIT
+ *
+ * @return
+ */
+ final ILttngEventProcessor getTrapExitBeforeHandler() {
+ AbstractStatsEventHandler handler = new StatsModeEndHandler(Events.LTT_EVENT_TRAP_EXIT);
+ return handler;
+ }
+
+ /**
+ * Method to handle the event: LTT_EVENT_IRQ_ENTRY
+ *
+ * @return
+ */
+ final ILttngEventProcessor getIrqEntryBeforeHandler() {
+ AbstractStatsEventHandler handler = new StatsModeChangeHandler(Events.LTT_EVENT_IRQ_ENTRY);
+ return handler;
+ }
+
+ /**
+ * Method to handle the event: LTT_EVENT_IRQ_EXIT
+ *
+ * @return
+ */
+ final ILttngEventProcessor getIrqExitBeforeHandler() {
+ AbstractStatsEventHandler handler = new StatsModeEndHandler(Events.LTT_EVENT_IRQ_EXIT);
+ return handler;
+ }
+
+ /**
+ * Method to handle the event: LTT_EVENT_SOFT_IRQ_ENTRY
+ *
+ * @return
+ */
+ final ILttngEventProcessor getSoftIrqEntryBeforeHandler() {
+ AbstractStatsEventHandler handler = new StatsModeChangeHandler(Events.LTT_EVENT_SOFT_IRQ_ENTRY);
+ return handler;
+ }
+
+ /**
+ * Method to handle the event: LTT_EVENT_SOFT_IRQ_EXIT
+ *
+ * @return
+ */
+ final ILttngEventProcessor getSoftIrqExitBeforeHandler() {
+ AbstractStatsEventHandler handler = new StatsModeEndHandler(Events.LTT_EVENT_SOFT_IRQ_EXIT);
+ return handler;
+ }
+
+ /**
+ * <p>
+ * Handles event: LTT_EVENT_FUNCTION_ENTRY
+ * </p>
+ * <p>
+ * FIELDS: LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE
+ * </p>
+ *
+ * @return
+ */
+ final ILttngEventProcessor getFunctionEntryBeforeHandler() {
+ AbstractStatsEventHandler handler = new StatsModeChangeHandler(Events.LTT_EVENT_FUNCTION_ENTRY);
+ return handler;
+ }
+
+ /**
+ *
+ * @return
+ */
+ final ILttngEventProcessor getFunctionExitBeforeHandler() {
+ AbstractStatsEventHandler handler = new StatsModeEndHandler(Events.LTT_EVENT_FUNCTION_EXIT);
+ return handler;
+ }
+
+ /**
+ * <p>
+ * Handles: LTT_EVENT_SCHED_SCHEDULE
+ * </p>
+ * <p>
+ * Fields: LTT_FIELD_PREV_PID, LTT_FIELD_NEXT_PID, LTT_FIELD_PREV_STATE
+ * </p>
+ *
+ * @return
+ */
+ final ILttngEventProcessor getSchedChangeBeforeHandler() {
+ AbstractStatsEventHandler handler = new StatsModeChangeHandler(Events.LTT_EVENT_SCHED_SCHEDULE);
+ return handler;
+ }
+
+ /**
+ * <p>
+ * Handles: LTT_EVENT_SCHED_SCHEDULE
+ * </p>
+ * <p>
+ * Fields: LTT_FIELD_PREV_PID, LTT_FIELD_NEXT_PID, LTT_FIELD_PREV_STATE
+ * </p>
+ *
+ * @return
+ */
+ final ILttngEventProcessor getAfterHandler() {
+ AbstractStatsEventHandler handler = new StatsModeChangeHandler(null) {
+ int sched_hash = StateStrings.Events.LTT_EVENT_SCHED_SCHEDULE.getInName().hashCode();
+ public boolean process(LttngEvent event, LttngTraceState traceState) {
+ // Step the event counter for any after event
+ stepCount(event, traceState);
+
+ int eventNameHash = event.getMarkerName().hashCode();
+ // specific processing for after sched schedule
+ if (sched_hash == eventNameHash
+ && event.getMarkerName().equals(StateStrings.Events.LTT_EVENT_SCHED_SCHEDULE.getInName())) {
+ return super.process(event, traceState);
+ }
+
+ return false;
+ }
+ };
+
+ return handler;
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Yann N. Dauphin (dhaemon@gmail.com) - Implementation for stats
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.statistics.model;
+
+public class Statistics {
+ public long nbEvents = 0;
+
+ public long cpuTime = 0;
+
+ public long cumulativeCpuTime = 0;
+
+ public long elapsedTime = 0;
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Yann N. Dauphin (dhaemon@gmail.com) - Implementation for stats
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.statistics.model;
+
+import java.util.AbstractMap;
+import java.util.Collection;
+import java.util.HashMap;
+
+/*
+ * A tree where nodes can be accessed efficiently using paths.
+ *
+ * It works like file systems. Each node is identified by a key. A path is a list of keys separated by the character '/'.
+ * For example, the path 'persons/yann' will browse to the child 'persons' and return it's 'yann' child.
+ *
+ * If a key might contains the character '/', use the #escapeKey method to get an escaped key. Use the #unescapeKey
+ * method to unescaped the key.
+ */
+public class StatisticsTreeNode {
+
+ private StatisticsTreeNode parent;
+
+ private String key;
+
+ private Statistics value;
+
+ private AbstractMap<String, StatisticsTreeNode> children;
+
+ /*
+ * Construct a node with the given key
+ */
+ public StatisticsTreeNode(String key) {
+ this(null, key);
+ }
+
+ /*
+ * Construct a node with the given parent, key and value.
+ */
+ public StatisticsTreeNode(StatisticsTreeNode parent, String key) {
+ super();
+ this.parent = parent;
+ this.key = key;
+ this.value = new Statistics();
+ this.children = new HashMap<String, StatisticsTreeNode>();
+ }
+
+ /*
+ * @return key associated with this node.
+ */
+ public StatisticsTreeNode getParent() {
+ return this.parent;
+ }
+
+ /*
+ * @return key associated with this node.
+ */
+ public String getKey() {
+ return this.key;
+ }
+
+ /*
+ * @return value associated with this node.
+ */
+ public Statistics getValue() {
+ return this.value;
+ }
+
+ /*
+ * Add a direct child with the given value at the given path.
+ *
+ * @return children node that was created.
+ */
+ public StatisticsTreeNode addChild(String key) {
+ StatisticsTreeNode created = new StatisticsTreeNode(this, key);
+
+ this.children.put(key, created);
+
+ return created;
+ }
+
+ /*
+ * @return direct children node with the given key. null if not found.
+ */
+ public StatisticsTreeNode getChild(String key) {
+ if (!this.children.containsKey(key)) {
+ return null;
+ }
+
+ return this.children.get(key);
+ }
+
+ /*
+ * @return number of direct children of this node.
+ */
+ public boolean hasChildren() {
+ return getNbChildren() > 0;
+ }
+
+ /*
+ * @return direct children of this node.
+ */
+ public Collection<StatisticsTreeNode> getChildren() {
+ return children.values();
+ }
+
+ /*
+ * @return number of direct children of this node.
+ */
+ public int getNbChildren() {
+ return children.size();
+ }
+
+ /*
+ * Get the node at the given path. If it doesn't exist each node in the path
+ * will be created with the given class.
+ *
+ * @return children node with the given path. null if not found.
+ */
+ public StatisticsTreeNode getOrCreateChildFromPath(String[] path) {
+ // StatisticsTreeNode previous = this.parent;
+ StatisticsTreeNode current = this;
+ for (String key : path) {
+ if (!current.children.containsKey(key)) {
+ current.children.put(key, new StatisticsTreeNode(current, key));
+ }
+
+ // previous = current;
+ current = current.children.get(key);
+ }
+
+ return current;
+ }
+
+ /*
+ * Get the node at the given path. If it doesn't exist each node in the path
+ * will be created with the given class.
+ *
+ * @return children node with the given path. null if not found.
+ */
+ public StatisticsTreeNode getOrCreateChildFromPath(String path) {
+ StatisticsTreeNode previous = this.parent;
+ StatisticsTreeNode current = this;
+ for (String key : path.split("/")) {
+ if (!current.children.containsKey(key)) {
+ current.children.put(key, new StatisticsTreeNode(previous, key));
+ }
+
+ previous = current;
+ current = current.children.get(key);
+ }
+
+ return current;
+ }
+
+ /*
+ * @return children node with the given path. null if not found.
+ */
+ public StatisticsTreeNode getChildFromPath(String path) {
+ StatisticsTreeNode current = this;
+ for (String key : path.split("/")) {
+ if (!current.children.containsKey(key)) {
+ return null;
+ }
+
+ current = current.children.get(key);
+ }
+
+ return current;
+ }
+
+ /*
+ * Use this to escape a key that might contain the '/' character.
+ *
+ * @return escaped key
+ */
+ public static String escapeKey(String key) {
+ return key.replace("%", "%25").replace("/", "%2F");
+ }
+
+ /*
+ * Use this to unescape a key.
+ *
+ * @return unescaped key
+ */
+ public static String unescapeKey(String key) {
+ return key.replace("%2F", "/").replace("%25", "%");
+ }
+
+ /**
+ * Start from creation time i.e. keep key and parent but new statistics and
+ * no children
+ */
+ public void reset() {
+ this.value = new Statistics();
+ this.children = new HashMap<String, StatisticsTreeNode>();
+ }
+
+ /**
+ *
+ * @param key
+ * @return true: if child with given key is present, false: if no child
+ * exists with given key name
+ */
+ public boolean containsChild(String key) {
+ return children.containsKey(key);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Yann N. Dauphin (dhaemon@gmail.com) - Implementation for stats
+ *******************************************************************************/
+package org.eclipse.linuxtools.lttng.ui.views.statistics.model;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class StatisticsTreeRootFactory {
+ // ========================================================================
+ // Data
+ // =======================================================================
+
+ private static final Map<String, StatisticsTreeNode> rootInstances = new HashMap<String, StatisticsTreeNode>();
+
+ // ========================================================================
+ // Methods
+ // =======================================================================
+
+ /**
+ * Provide a statisticsTree instance per trace
+ *
+ * @return
+ */
+ public static StatisticsTreeNode getStatTreeRoot(String traceUniqueId) {
+ if (traceUniqueId == null) {
+ return null;
+ }
+
+ if (rootInstances.containsKey(traceUniqueId)) {
+ return rootInstances.get(traceUniqueId);
+ }
+
+ StatisticsTreeNode tree = new StatisticsTreeNode(traceUniqueId);
+
+ rootInstances.put(traceUniqueId, tree);
+
+ return tree;
+ }
+
+ /**
+ * @param traceUniqueId
+ * @return
+ */
+ public static boolean containsTreeRoot(String traceUniqueId) {
+ return rootInstances.containsKey(traceUniqueId);
+ }
+
+ /**
+ * Remove previously registered statistics tree.
+ * @param traceUniqueId
+ */
+ public static void removeStatTreeRoot(String traceUniqueId) {
+ if (traceUniqueId != null && rootInstances.containsKey(traceUniqueId)) {
+ rootInstances.remove(traceUniqueId);
+ }
+ }
+
+ /**
+ * Remove all tree root instances
+ */
+ public static void removeAll() {
+ rootInstances.clear();
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.timeframe;
+
+import org.eclipse.linuxtools.tmf.event.TmfTimeRange;
+import org.eclipse.linuxtools.tmf.event.TmfTimestamp;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Spinner;
+
+// ========================================================================
+// SpinnerGroup
+// ========================================================================
+
+/**
+ * <b><u>SpinnerGroup</u></b>
+ * <p>
+ * A SpinnerGroup holds two coordinated spinners (for seconds and
+ * nanoseconds) representing the current time within the trace.
+ * <p>
+ * The current time can take any value anything within the time range (start
+ * and end time).
+ */
+public class SpinnerGroup {
+
+ // The nanosecond scale (10^9)
+ private static final int NS_PER_SECOND = 1000 * 1000 * 1000;
+ private static final byte NS_SCALING_FACTOR = -9;
+
+ // Labels
+ private static final String SECONDS_LABEL = "sec";
+ private static final String NANOSEC_LABEL = "ns";
+
+ // Widgets
+ private Group group;
+ private Spinner seconds;
+ private Spinner nanosec;
+
+ // The valid time range - start time
+ private TmfTimestamp startTime;
+ private int startSeconds;
+ private int startNanosec;
+
+ // The valid time range - end time
+ private TmfTimestamp endTime;
+ private int endSeconds;
+ private int endNanosec;
+
+ // The current time value
+ private TmfTimestamp currentTime;
+ private int currentSeconds;
+ private int currentNanosec;
+
+ @SuppressWarnings("unused")
+ private TimeFrameView fOwner;
+
+ /**
+ * <b><u>Constructor</u></b>
+ * <p>
+ * <li>Creates the display group and formats it for the grid cell
+ * <li>Sets the initial values for Start/End/Current time
+ * </li>
+ * <p>
+ * @param parent - the parent Composite
+ * @param groupName - the group name
+ * @param range - the valid time range (start/end time)
+ * @param current - the current time
+ */
+ public SpinnerGroup(TimeFrameView owner, Composite parent, String groupName, TmfTimeRange range, TmfTimestamp current) {
+
+ fOwner = owner;
+
+ // Create the group
+ group = new Group(parent, SWT.BORDER);
+ group.setText(groupName);
+
+ // Make it use the whole grid cell
+ GridData gridData = new GridData(SWT.LEFT, SWT.TOP, true, false);
+ gridData.horizontalAlignment = SWT.FILL;
+ group.setLayoutData(gridData);
+
+ // Create and position the widgets
+ seconds = new Spinner(group, SWT.BORDER);
+ seconds.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ currentSeconds = seconds.getSelection();
+ refreshCurrentTime();
+ }
+ });
+ seconds.setBounds(5, 25, 110, 25);
+
+ Label label = new Label(group, SWT.LEFT);
+ label.setText(SECONDS_LABEL);
+ label.setBounds(120, 28, 25, 22);
+
+ nanosec = new Spinner(group, SWT.BORDER);
+ nanosec.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ currentNanosec = nanosec.getSelection();
+ // Correct for nanosec underflow
+ if (currentNanosec < 0) {
+ currentSeconds--;
+ currentNanosec = NS_PER_SECOND - 1;
+ }
+ // Correct for nanosec overflow
+ if (currentNanosec >= NS_PER_SECOND) {
+ currentSeconds++;
+ currentNanosec = 0;
+ }
+ refreshCurrentTime();
+ }
+ });
+ nanosec.setBounds(150, 25, 110, 25);
+
+ label = new Label(group, SWT.LEFT);
+ label.setText(NANOSEC_LABEL);
+ label.setBounds(265, 28, 25, 22);
+
+ setContent(range, current);
+ }
+
+ private void refreshCurrentTime() {
+ long newCurrentTime = ((long) currentSeconds) * NS_PER_SECOND + currentNanosec;
+ TmfTimestamp ts = new TmfTimestamp(newCurrentTime, NS_SCALING_FACTOR, 0);
+ currentTime = ts;
+// fOwner.synchTimeFrameWidgets(this);
+ }
+
+ // ====================================================================
+ // Get/Set
+ // ====================================================================
+
+ public TmfTimestamp getStartTime() {
+ return startTime;
+ }
+
+ public TmfTimestamp getEndTime() {
+ return endTime;
+ }
+
+ public TmfTimestamp getCurrentTime() {
+ return currentTime;
+ }
+
+ public TmfTimestamp getSpan() {
+ TmfTimestamp span = new TmfTimestamp(startTime.getAdjustment(endTime, NS_SCALING_FACTOR), NS_SCALING_FACTOR, 0);
+ return span;
+ }
+
+ public TmfTimeRange getTimeRange() {
+ TmfTimeRange range = new TmfTimeRange(startTime, endTime);
+ return range;
+ }
+
+ public void setStartTime(TmfTimestamp ts) {
+ try {
+ startTime = ts.synchronize(0, NS_SCALING_FACTOR);
+ startSeconds = (int) (startTime.getValue() / NS_PER_SECOND);
+ startNanosec = (int) (startTime.getValue() % NS_PER_SECOND);
+ }
+ catch (ArithmeticException e) {
+ }
+ }
+
+ public void setEndTime(TmfTimestamp ts) {
+ try {
+ endTime = ts.synchronize(0, NS_SCALING_FACTOR);
+ endSeconds = (int) (endTime.getValue() / NS_PER_SECOND);
+ endNanosec = (int) (endTime.getValue() % NS_PER_SECOND);
+ }
+ catch (ArithmeticException e) {
+ }
+ }
+
+ public void setCurrentTime(TmfTimestamp ts) {
+ try {
+ currentTime = ts.synchronize(0, NS_SCALING_FACTOR);
+ currentSeconds = (int) (currentTime.getValue() / NS_PER_SECOND);
+ currentNanosec = (int) (currentTime.getValue() % NS_PER_SECOND);
+ }
+ catch (ArithmeticException e) {
+ }
+ }
+
+ // ====================================================================
+ // Operators
+ // ====================================================================
+
+ /**
+ * <b><u>setContent</u></b>
+ * <p>
+ * <li>validates that [startTime <= currentTime <= endTime] is respected
+ * <li>sets the start/current/end time and update the spinners
+ * </li>
+ * <p>
+ *
+ * @param range
+ * @param current
+ */
+ public void setContent(TmfTimeRange range, TmfTimestamp current) {
+
+ if (range != null) {
+ // Extract the time range
+ TmfTimestamp start = range.getStartTime();
+ TmfTimestamp end = range.getEndTime();
+
+ // Assume start time is OK
+ setStartTime(start);
+
+ // Make sure end time >= start time
+ if (end.compareTo(start, false) < 0) {
+ end = start;
+ }
+ setEndTime(end);
+
+ // Make sure [start time <= current time <= end time]
+ // If not: current = min(max(start, current), end);
+ if (current.compareTo(start, false) < 0) {
+ current = start;
+ }
+ if (current.compareTo(end, false) > 0) {
+ current = end;
+ }
+ }
+ setCurrentTime(current);
+
+ // And configure the spinners
+ updateSpinners();
+ }
+
+ /**
+ * <b><u>setValue</u></b>
+ * <p>
+ * <li>validates that [startTime <= currentTime <= endTime] is respected
+ * <li>sets the current time and the spinners
+ * </li>
+ * <p>
+ *
+ * @param range
+ * @param current
+ */
+ public void setValue(TmfTimestamp current) {
+
+ // Make sure [start time <= current time <= end time]
+ // If not: current = min(max(start, current), end);
+ if (current.compareTo(startTime, false) < 0) {
+ current = startTime;
+ }
+ if (current.compareTo(endTime, false) > 0) {
+ current = endTime;
+ }
+ setCurrentTime(current);
+
+ // And configure the spinners
+ updateSpinners();
+ }
+
+ /**
+ * Update the spinners with the new current time value
+ * Perform the update on the UI thread
+ */
+ public void updateSpinners() {
+
+ seconds.getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ if (!seconds.isDisposed() && !nanosec.isDisposed()) {
+ // If we are on the start second, ensure that [currentNS >= startNS]
+ // If the currentSeconds > startSeconds, set startns to -1 so we can
+ // "underflow"
+ int startns = -1;
+ if (currentSeconds <= startSeconds) {
+ currentSeconds = startSeconds;
+ startns = startNanosec;
+ if (currentNanosec < startns) {
+ currentNanosec = startns;
+ }
+ }
+
+ // If we are on the end second, ensure that [currentNS <= endNS]
+ // If the currentSeconds < endSeconds, set endns to MAX so we can
+ // "overflow"
+ int endns = NS_PER_SECOND;
+ if (currentSeconds >= endSeconds) {
+ currentSeconds = endSeconds;
+ endns = endNanosec;
+ if (currentNanosec > endns) {
+ currentNanosec = endns;
+ }
+ }
+
+ // Refresh the spinners (value, range, increments, ...)
+ // To ensure that the spinners are properly set, the range has to be > 0
+// seconds.setValues(currentSeconds, startSeconds - 1, endSeconds + 1, 0, 1, 10);
+// nanosec.setValues(currentNanosec, startns - 1, endns + 1, 0, 1, 1000000);
+ seconds.setValues(currentSeconds, startSeconds, endSeconds, 0, 1, 10);
+ nanosec.setValues(currentNanosec, startns, endns, 0, 100000, 10000000);
+
+ // If start == end (i.e. no range), disable the spinner
+ // (if start == end, the spinner widget range is set to [0..100] by default)
+ seconds.setEnabled(startSeconds != endSeconds);
+ nanosec.setEnabled(startns != endns);
+ }
+ }
+ });
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2009 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Francois Chouinard - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.lttng.ui.views.timeframe;
+
+import org.eclipse.linuxtools.lttng.event.LttngEvent;
+import org.eclipse.linuxtools.tmf.event.TmfTimeRange;
+import org.eclipse.linuxtools.tmf.event.TmfTimestamp;
+import org.eclipse.linuxtools.tmf.experiment.TmfExperiment;
+import org.eclipse.linuxtools.tmf.signal.TmfExperimentSelectedSignal;
+import org.eclipse.linuxtools.tmf.signal.TmfExperimentUpdatedSignal;
+import org.eclipse.linuxtools.tmf.signal.TmfRangeSynchSignal;
+import org.eclipse.linuxtools.tmf.signal.TmfSignalHandler;
+import org.eclipse.linuxtools.tmf.signal.TmfTimeSynchSignal;
+import org.eclipse.linuxtools.tmf.ui.views.TmfView;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Slider;
+
+/**
+ * <b><u>TimeFrameView</u></b>
+ * <p>
+ * The TimeFrameView provides a set of spinners to monitor and set the start
+ * time, end time, the current time interval and current time of the trace
+ * set at the nanosecond level.
+ * <p>
+ * It ensures that the following relations are always true:
+ * <p>
+ * <li>[ startTime >= start time of the trace ]
+ * <li>[ endTime <= end time of the trace ]
+ * <li>[ startTime <= currentTime <= endTime ]
+ * <li>[ interval == (endTime - startTime) ]
+ * </li>
+ * <p>
+ * It provides a slider to rapidly set the current time within the time range
+ * (i.e. between startTime and endTime).
+ * <p>
+ * Finally, it allows modification of the time range and the current time. This
+ * triggers notifications to the other LTTng views.
+ * <p>
+ * FIXME: The slider is very jumpy due to the large number of async updates
+ * FIXME: Revisit the control flow between View, Spinners and Slider
+ */
+public class TimeFrameView extends TmfView {
+
+ public static final String ID = "org.eclipse.linuxtools.lttng.ui.views.timeframe";
+
+ // ========================================================================
+ // TimeFrameView
+ // ========================================================================
+
+ // The event log timestamp characteristics
+ private TmfTimestamp fTraceStartTime = new TmfTimestamp();
+ private TmfTimestamp fTraceEndTime = new TmfTimestamp();
+
+ private TmfTimestamp fCurrentTime = new TmfTimestamp();
+
+ private TmfTimeRange fTraceTimeRange = new TmfTimeRange(fTraceStartTime, fTraceEndTime);
+ private TmfTimeRange fTraceSpan = new TmfTimeRange(fTraceStartTime, fTraceEndTime);
+ private byte fScale = 0;
+
+ // Labels
+ private static final String START_TIME_LABEL = "Window Start Time";
+ private static final String END_TIME_LABEL = "Window End Time";
+ private static final String TIME_RANGE_LABEL = "Window Range";
+ private static final String CURRENT_TIME_LABEL = "Current Time";
+
+ private static final int SLIDER_RANGE = 10000;
+
+ private SpinnerGroup fStartGroup;
+ private SpinnerGroup fEndGroup;
+ private SpinnerGroup fRangeGroup;
+ private SpinnerGroup fCurrentGroup;
+
+ // The slider
+ private Slider fSlider;
+
+ // The current experiment
+ TmfExperiment<LttngEvent> fExperiment = null;
+ // notify external listeners may not be needed if the update originated
+ // externally
+ private boolean fupdateExternalListeners = true;
+
+
+ /**
+ * Constructor
+ */
+ public TimeFrameView() {
+ super("TimeFrameView");
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
+ */
+ @Override
+ public void createPartControl(Composite parent) {
+
+ // Set the view layout
+ GridLayout layout = new GridLayout(4, true);
+ parent.setLayout(layout);
+
+ fStartGroup = new SpinnerGroup(this, parent, START_TIME_LABEL, fTraceTimeRange, fTraceStartTime);
+ fEndGroup = new SpinnerGroup(this, parent, END_TIME_LABEL, fTraceTimeRange, fTraceEndTime);
+ fRangeGroup = new SpinnerGroup(this, parent, TIME_RANGE_LABEL, fTraceTimeRange, fTraceEndTime);
+ fCurrentGroup = new SpinnerGroup(this, parent, CURRENT_TIME_LABEL, fTraceTimeRange, fTraceStartTime);
+
+ // Create the slider
+ createSlider(parent);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
+ */
+ @Override
+ public void setFocus() {
+ // TODO Auto-generated method stub
+ }
+
+ // ========================================================================
+ // Operators
+ // ========================================================================
+
+ /**
+ * One of the spinners has been updated. Synchronize the other widgets.
+ */
+ public void synchTimeFrameWidgets(SpinnerGroup trigger) {
+ boolean trangeUpdated = false;
+
+ // Collect the data
+ TmfTimestamp startTime = fStartGroup.getCurrentTime();
+ TmfTimestamp endTime = fEndGroup.getCurrentTime();
+ TmfTimestamp timeRange = fRangeGroup.getCurrentTime();
+ TmfTimestamp currentTime = fCurrentGroup.getCurrentTime();
+
+ // If startTime was set beyond endTime, adjust endTime and interval
+ if (trigger == fStartGroup) {
+ if (startTime.compareTo(endTime, false) > 0) {
+ endTime = startTime;
+ trangeUpdated = true;
+ }
+ }
+
+ // If endTime was set beyond startTime, adjust startTime and interval
+ if (trigger == fEndGroup) {
+ if (endTime.compareTo(startTime, false) < 0) {
+ startTime = endTime;
+ trangeUpdated = true;
+ }
+ }
+
+ // If timeRange was set, adjust endTime
+ if (trigger == fRangeGroup) {
+ long start = startTime.getValue();
+ long span = timeRange.getValue();
+ TmfTimestamp ts = new TmfTimestamp(start + span, startTime.getScale(), 0);
+ if (ts.compareTo(fTraceEndTime, false) > 0) {
+ ts = fTraceEndTime.synchronize(fTraceEndTime.getValue(), startTime.getScale());
+ }
+ endTime = ts;
+ trangeUpdated = true;
+ }
+
+ // Compute the new time range
+ TmfTimeRange subrange = new TmfTimeRange(startTime, endTime);
+ byte scale = startTime.getScale();
+ TmfTimestamp interval = new TmfTimestamp(startTime.getAdjustment(endTime, scale), scale, 0);
+
+ // Update the spinner groups
+ fStartGroup.setContent(fTraceTimeRange, startTime);
+ fEndGroup.setContent(fTraceTimeRange, endTime);
+ fRangeGroup.setContent(fTraceSpan, interval);
+ fCurrentGroup.setContent(subrange, currentTime);
+
+ updateSlider(subrange, currentTime);
+ // Notify other views, only if the update originated from this view
+ if (fupdateExternalListeners) {
+ if (!fCurrentTime.equals(currentTime)) {
+ fCurrentTime = currentTime;
+ broadcast(new TmfTimeSynchSignal(this, currentTime));
+ }
+
+ // Notify the views if the time range has been impacted
+ if (trangeUpdated) {
+ TmfTimeRange trange = new TmfTimeRange(startTime, endTime);
+ broadcast(new TmfRangeSynchSignal(this, trange, currentTime));
+ }
+ }
+ }
+
+ // ========================================================================
+ // Slider Handling
+ // ========================================================================
+
+ /**
+ * @param parent
+ */
+ private void createSlider(Composite parent) {
+ fSlider = new Slider(parent, SWT.SMOOTH | SWT.FILL);
+ fSlider.setMinimum(0);
+ fSlider.setMaximum(SLIDER_RANGE + fSlider.getThumb());
+ fSlider.setIncrement(SLIDER_RANGE / 100);
+ fSlider.setPageIncrement(SLIDER_RANGE / 10);
+ fSlider.setSelection(0);
+
+ GridData gridData = new GridData(SWT.LEFT, SWT.TOP, true, false);
+ gridData.horizontalAlignment = SWT.FILL;
+ gridData.horizontalSpan = 4;
+ fSlider.setLayoutData(gridData);
+
+ fSlider.addListener(SWT.Selection, new Listener() {
+ public void handleEvent(Event event) {
+ int ratio = fSlider.getSelection();
+ TmfTimestamp span = fCurrentGroup.getSpan();
+ long value = span.getValue() * ratio / SLIDER_RANGE;
+ TmfTimestamp start = fCurrentGroup.getStartTime();
+ TmfTimestamp current = new TmfTimestamp(start.getValue() + value, start.getScale(), 0);
+ fCurrentGroup.setValue(current);
+ }
+ });
+
+ }
+
+ /**
+ * @param range
+ * @param timestamp
+ */
+ private void updateSlider(TmfTimeRange range, TmfTimestamp timestamp) {
+
+ // Determine the new relative position
+ byte scale = range.getEndTime().getScale();
+ long total = range.getStartTime().getAdjustment(range.getEndTime(), scale);
+ long relative = range.getStartTime().getAdjustment(timestamp, scale);
+
+ // Set the slider value
+ final long position = (total > 0) ? (relative * SLIDER_RANGE / total) : 0;
+
+ // Update the slider on the UI thread
+ long current = fSlider.getSelection();
+ if (position != current) {
+ fSlider.getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ fSlider.setSelection((int) position);
+ }
+ });
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return "[TimeFrameView]";
+ }
+
+ // ========================================================================
+ // TMF Signal Handling
+ // ========================================================================
+
+ /**
+ * @param signal
+ */
+ @SuppressWarnings("unchecked")
+ @TmfSignalHandler
+ public void experimentSelected(TmfExperimentSelectedSignal<LttngEvent> signal) {
+
+ // Update the trace reference
+ fExperiment = (TmfExperiment<LttngEvent>) signal.getExperiment();
+
+ // Update the time frame
+ fTraceTimeRange = fExperiment.getTimeRange();
+ fTraceStartTime = fTraceTimeRange.getStartTime();
+ fTraceEndTime = fTraceTimeRange.getEndTime();
+ fScale = fTraceStartTime.getScale();
+
+ // Update the widgets
+ fStartGroup.setContent(fTraceTimeRange, fTraceStartTime);
+ fEndGroup.setContent(fTraceTimeRange, fTraceEndTime);
+ fCurrentGroup.setContent(fTraceTimeRange, fTraceStartTime);
+
+ fCurrentTime = fTraceStartTime;
+
+ TmfTimestamp delta = new TmfTimestamp(fTraceStartTime.getAdjustment(fTraceEndTime, fScale), fScale, 0);
+ fTraceSpan = new TmfTimeRange(new TmfTimestamp(0, fScale, 0), delta);
+// fRangeGroup.setContent(fTraceSpan, delta);
+ TmfTimestamp start = new TmfTimestamp(1, (byte) -1, 0);
+ fRangeGroup.setContent(fTraceSpan, start);
+ }
+
+ /**
+ * @param signal
+ */
+ @TmfSignalHandler
+ public void experimentUpdated(TmfExperimentUpdatedSignal signal) {
+
+ // Update the time frame
+ fTraceTimeRange = signal.getTrace().getTimeRange();
+ fTraceStartTime = fTraceTimeRange.getStartTime();
+ fTraceEndTime = fTraceTimeRange.getEndTime();
+ fScale = fTraceStartTime.getScale();
+
+ // Update the widgets
+ fStartGroup.setContent(fTraceTimeRange, fStartGroup.getCurrentTime());
+ fEndGroup.setContent(fTraceTimeRange, fTraceEndTime);
+ fCurrentGroup.setContent(fTraceTimeRange, fCurrentGroup.getCurrentTime());
+
+ TmfTimestamp delta = new TmfTimestamp(fTraceStartTime.getAdjustment(fTraceEndTime, fScale), fScale, 0);
+ fTraceSpan = new TmfTimeRange(new TmfTimestamp(0, fScale, 0), delta);
+ fRangeGroup.setContent(fTraceSpan, delta);
+ }
+
+ /**
+ * @param signal
+ */
+ @TmfSignalHandler
+ public void currentTimeRangeUpdated(TmfRangeSynchSignal signal) {
+ if (signal.getSource() != this) {
+ // Update the time frame
+ TmfTimeRange selTimeRange = signal.getCurrentRange();
+ TmfTimestamp selStart = selTimeRange.getStartTime().synchronize(0,
+ fScale);
+ TmfTimestamp selEnd = selTimeRange.getEndTime().synchronize(0,
+ fScale);
+
+ fupdateExternalListeners = false;
+ // Update the widgets and prevent broadcast notifications to
+ // the views which have been notified already.
+ {
+ fStartGroup.setContent(fTraceTimeRange, selStart);
+ fEndGroup.setContent(fTraceTimeRange, selEnd);
+
+ TmfTimestamp delta = new TmfTimestamp(selStart.getAdjustment(
+ selEnd, fScale), fScale, 0);
+
+ fRangeGroup.setContent(fTraceSpan, delta);
+ }
+
+ // restore the external notification flag
+ fupdateExternalListeners = true;
+
+ }
+ }
+
+ /**
+ * @param signal
+ */
+ @TmfSignalHandler
+ public void currentTimeUpdated(TmfTimeSynchSignal signal) {
+ if (signal.getSource() != this) {
+ // prevent loop to external notifications
+ fupdateExternalListeners = false;
+ fCurrentTime = signal.getCurrentTime().synchronize(0, fStartGroup.getCurrentTime().getScale());
+ if (fStartGroup.getCurrentTime().compareTo(fCurrentTime, false) > 0) {
+ fStartGroup.setContent(new TmfTimeRange(fCurrentTime, fEndGroup.getCurrentTime()), fCurrentTime);
+ }
+ if (fEndGroup.getCurrentTime().compareTo(fCurrentTime, false) < 0) {
+ fEndGroup.setContent(new TmfTimeRange(fStartGroup.getCurrentTime(), fCurrentTime), fCurrentTime);
+ }
+ fCurrentGroup.setContent(null, fCurrentTime);
+ updateSlider(fCurrentGroup.getTimeRange(), fCurrentTime);
+
+ // Enable external notifications
+ fupdateExternalListeners = true;
+ }
+ }
+
+}
\ No newline at end of file