tmf: Offset traces ui
authorMatthew Khouzam <matthew.khouzam@ericsson.com>
Wed, 6 Aug 2014 19:07:03 +0000 (15:07 -0400)
committerPatrick Tasse <patrick.tasse@gmail.com>
Tue, 14 Oct 2014 16:35:35 +0000 (12:35 -0400)
Change-Id: Ifbcfa32cddfaa21e6c526169e9b2b3a8f06fcf72
Signed-off-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Signed-off-by: Patrick Tasse <patrick.tasse@gmail.com>
Reviewed-on: https://git.eclipse.org/r/30689
Tested-by: Hudson CI
Reviewed-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Tested-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Reviewed-by: Bernd Hufmann <bernd.hufmann@ericsson.com>
Tested-by: Bernd Hufmann <bernd.hufmann@ericsson.com>
25 files changed:
org.eclipse.linuxtools.btf.core/src/org/eclipse/linuxtools/btf/core/trace/BtfTrace.java
org.eclipse.linuxtools.tmf.core.tests/stubs/org/eclipse/linuxtools/tmf/tests/stubs/trace/text/SyslogTrace.java
org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/parsers/custom/CustomEvent.java
org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/signal/TmfEventSelectedSignal.java [new file with mode: 0644]
org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/synchronization/TimestampTransformFactory.java
org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/trace/TmfTrace.java
org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/trace/text/TextTrace.java
org.eclipse.linuxtools.tmf.pcap.core/src/org/eclipse/linuxtools/internal/tmf/pcap/core/util/PcapEventFactory.java
org.eclipse.linuxtools.tmf.ui/META-INF/MANIFEST.MF
org.eclipse.linuxtools.tmf.ui/plugin.properties
org.eclipse.linuxtools.tmf.ui/plugin.xml
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/dialogs/offset/Messages.java [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/dialogs/offset/OffsetDialog.java [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/dialogs/offset/messages.properties [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/handlers/ClearTraceOffsetHandler.java [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/handlers/DeleteTraceSupplementaryFilesHandler.java
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/handlers/Messages.java
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/handlers/OffsetTraceHandler.java [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/handlers/messages.properties
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/Messages.java
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/TmfCommonProjectElement.java
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/TmfTraceElement.java
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/messages.properties
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/ArrayTreeContentProvider.java [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/events/TmfEventsTable.java

index f3af6758ee18a36f9335c68cc030503ebf345fc1..ec6a17d2b2154e669fd9d6bb40bb5ece5fb7ddac 100644 (file)
@@ -387,7 +387,7 @@ public class BtfTrace extends TmfTrace implements ITmfEventParser, ITmfPersisten
         ITmfEventField content = type.generateContent(event, sourceInstance, targetInstance);
 
         return new BtfEvent(this, rank,
-                fTsFormat.createTimestamp(getTimestampTransform().transform(timestamp + fTsOffset)),
+                getTimestampTransform().transform(fTsFormat.createTimestamp(timestamp + fTsOffset)),
                 source,
                 type,
                 type.getDescription(),
index 0dd7c45326a0a70ce5141fe3b04f268fbdc6e70b..f0b90656fddb32db8375947e8e8c4231c7f6d3c9 100644 (file)
@@ -40,8 +40,6 @@ public class SyslogTrace extends TextTrace<SyslogEvent> {
     /** The corresponding date format of the time stamp. */
     public static final SimpleDateFormat TIMESTAMP_SIMPLEDATEFORMAT = new SimpleDateFormat(
             TIMESTAMP_FORMAT, TmfTimePreferences.getInstance().getLocale());
-    /** The scale of the time stamps. */
-    public static final byte TIMESTAMP_SCALE = ITmfTimestamp.MILLISECOND_SCALE;
     /** The regular expression pattern of the first line of an event. */
     public static final Pattern LINE1_PATTERN = Pattern.compile(
             "\\s*(\\S\\S\\S \\d\\d? \\d\\d:\\d\\d:\\d\\d)\\s*(\\S*)\\s*(\\S*):+\\s*(.*\\S)?"); //$NON-NLS-1$
@@ -76,8 +74,8 @@ public class SyslogTrace extends TextTrace<SyslogEvent> {
                 if (calendar.after(CURRENT)) {
                     calendar.set(Calendar.YEAR, CURRENT.get(Calendar.YEAR) - 1);
                 }
-                long ms = calendar.getTimeInMillis();
-                timestamp = new TmfTimestamp(ms, TIMESTAMP_SCALE);
+                long ns = calendar.getTimeInMillis() * 1000000;
+                timestamp = createTimestamp(ns);
             }
         } catch (ParseException e) {
             timestamp = new TmfTimestamp();
index 3fde3dfd063a502a96d17a38588f19e080ee5b9b..e8508c42953e8c09e5536a1dfc862ae4359b913a 100644 (file)
@@ -23,6 +23,7 @@ import org.eclipse.linuxtools.tmf.core.event.TmfEventField;
 import org.eclipse.linuxtools.tmf.core.event.TmfEventType;
 import org.eclipse.linuxtools.tmf.core.parsers.custom.CustomTraceDefinition.OutputColumn;
 import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp;
+import org.eclipse.linuxtools.tmf.core.timestamp.TmfNanoTimestamp;
 import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestamp;
 import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestampFormat;
 import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
@@ -227,7 +228,7 @@ public class CustomEvent extends TmfEvent {
             TmfTimestampFormat timestampFormat = new TmfTimestampFormat(timestampInputFormat);
             try {
                 long time = timestampFormat.parseValue(timestampString);
-                timestamp = new TmfTimestamp(time, ITmfTimestamp.NANOSECOND_SCALE);
+                timestamp = new TmfNanoTimestamp(getTrace().getTimestampTransform().transform(time));
                 setTimestamp(timestamp);
             } catch (ParseException e) {
                 setTimestamp(TmfTimestamp.ZERO);
diff --git a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/signal/TmfEventSelectedSignal.java b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/signal/TmfEventSelectedSignal.java
new file mode 100644 (file)
index 0000000..53b5e0d
--- /dev/null
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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:
+ *   Patrick Tasse - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.tmf.core.signal;
+
+import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
+
+/**
+ * Signal indicating a trace event has been selected.
+ *
+ * The specified event has been selected.
+ *
+ * @author Patrick Tasse
+ * @since 3.2
+ */
+public class TmfEventSelectedSignal extends TmfSignal {
+
+    private final ITmfEvent fEvent;
+
+    /**
+     * Constructor
+     *
+     * @param source
+     *            Object sending this signal
+     * @param event
+     *            The event that was selected
+     */
+    public TmfEventSelectedSignal(Object source, ITmfEvent event) {
+        super(source);
+        fEvent = event;
+    }
+
+    /**
+     * @return The event referred to by this signal
+     */
+    public ITmfEvent getEvent() {
+        return fEvent;
+    }
+
+    @Override
+    public String toString() {
+        return "[TmfEventSelectedSignal (" + fEvent.toString() + ")]"; //$NON-NLS-1$ //$NON-NLS-2$
+    }
+}
index 88119e8f2e9a6390f2f6214b1c3762a104d7bd48..f74deb02dec15322f0d4012544470b8c1cd819b8 100644 (file)
  *******************************************************************************/
 package org.eclipse.linuxtools.tmf.core.synchronization;
 
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
 import java.math.BigDecimal;
 
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.linuxtools.internal.tmf.core.Activator;
 import org.eclipse.linuxtools.internal.tmf.core.synchronization.TmfConstantTransform;
 import org.eclipse.linuxtools.internal.tmf.core.synchronization.TmfTimestampTransform;
 import org.eclipse.linuxtools.internal.tmf.core.synchronization.TmfTimestampTransformLinear;
+import org.eclipse.linuxtools.tmf.core.TmfCommonConstants;
 import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp;
 
 /**
@@ -26,6 +36,8 @@ import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp;
  */
 public final class TimestampTransformFactory {
 
+    private static final String SYNCHRONIZATION_FORMULA_FILE = "sync_formula"; //$NON-NLS-1$
+
     private TimestampTransformFactory() {
     }
 
@@ -121,4 +133,76 @@ public final class TimestampTransformFactory {
         return new TmfTimestampTransformLinear(factor, offset);
     }
 
+    /**
+     * Returns the file resource used to store synchronization formula. The file
+     * may not exist.
+     *
+     * @param resource
+     *            the trace resource
+     * @return the synchronization file
+     */
+    private static File getSyncFormulaFile(IResource resource) {
+        if (resource == null) {
+            return null;
+        }
+        try {
+            String supplDirectory = resource.getPersistentProperty(TmfCommonConstants.TRACE_SUPPLEMENTARY_FOLDER);
+            return new File(supplDirectory + File.separator + SYNCHRONIZATION_FORMULA_FILE);
+        } catch (CoreException e) {
+            /* Ignored */
+        }
+        return null;
+    }
+
+    /**
+     * Returns the timestamp transform for a trace resource
+     *
+     * @param resource
+     *            the trace resource
+     * @return the timestamp transform
+     * @since 3.2
+     */
+    public static ITmfTimestampTransform getTimestampTransform(IResource resource) {
+        File syncFile = getSyncFormulaFile(resource);
+        if (syncFile != null && syncFile.exists()) {
+            /* Read the serialized object from file */
+            try (FileInputStream fis = new FileInputStream(syncFile);
+                    ObjectInputStream ois = new ObjectInputStream(fis);) {
+                return (ITmfTimestampTransform) ois.readObject();
+            } catch (ClassNotFoundException | IOException e) {
+            }
+        }
+        return TimestampTransformFactory.getDefaultTransform();
+    }
+
+    /**
+     * Sets the trace resource's timestamp transform
+     *
+     * @param resource
+     *            the trace resource
+     * @param tt
+     *            The timestamp transform for all timestamps of this trace, or
+     *            null to clear it
+     * @since 3.2
+     */
+    public static void setTimestampTransform(IResource resource, ITmfTimestampTransform tt) {
+        /* Save the timestamp transform to a file */
+        File syncFile = getSyncFormulaFile(resource);
+        if (syncFile != null) {
+            if (syncFile.exists()) {
+                syncFile.delete();
+            }
+            if (tt == null) {
+                return;
+            }
+            /* Write the serialized object to file */
+            try (FileOutputStream fos = new FileOutputStream(syncFile, false);
+                    ObjectOutputStream oos = new ObjectOutputStream(fos);) {
+                oos.writeObject(tt);
+            } catch (IOException e1) {
+                Activator.logError("Error writing timestamp transform for trace", e1); //$NON-NLS-1$
+            }
+        }
+    }
+
 }
index 54228e13340926dcd3a1728e68832d716aeec622..167800c755d0aa66c145944cdfd56d101ce11a2d 100644 (file)
 package org.eclipse.linuxtools.tmf.core.trace;
 
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
@@ -29,15 +24,12 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 
-import org.eclipse.core.resources.IFolder;
 import org.eclipse.core.resources.IResource;
-import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.MultiStatus;
 import org.eclipse.core.runtime.Path;
 import org.eclipse.core.runtime.Status;
 import org.eclipse.linuxtools.internal.tmf.core.Activator;
-import org.eclipse.linuxtools.tmf.core.TmfCommonConstants;
 import org.eclipse.linuxtools.tmf.core.analysis.IAnalysisModule;
 import org.eclipse.linuxtools.tmf.core.analysis.IAnalysisModuleHelper;
 import org.eclipse.linuxtools.tmf.core.analysis.TmfAnalysisManager;
@@ -77,6 +69,10 @@ import org.eclipse.linuxtools.tmf.core.trace.location.ITmfLocation;
  * accomplish this is by making the concrete class extend TmfTrace and
  * implement ITmfEventParser.
  * <p>
+ * When constructing an event, the concrete trace should use the trace's
+ * timestamp transform to create the timestamp, by either transforming the
+ * parsed time value directly or by using the method createTimestamp().
+ * <p>
  * The concrete class can either specify its own indexer or use the provided
  * TmfCheckpointIndexer (default). In this case, the trace cache size will be
  * used as checkpoint interval.
@@ -124,8 +120,6 @@ public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace, IT
     private final Map<String, IAnalysisModule> fAnalysisModules =
             Collections.synchronizedMap(new LinkedHashMap<String, IAnalysisModule>());
 
-    private static final String SYNCHRONIZATION_FORMULA_FILE = "sync_formula"; //$NON-NLS-1$
-
     // ------------------------------------------------------------------------
     // Construction
     // ------------------------------------------------------------------------
@@ -763,29 +757,6 @@ public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace, IT
         }
     }
 
-    /**
-     * Returns the file resource used to store synchronization formula. The file
-     * may not exist.
-     *
-     * @return the synchronization file
-     */
-    private File getSyncFormulaFile() {
-        File file = null;
-        if (fResource instanceof IFolder) {
-            try {
-                String supplDirectory;
-
-                supplDirectory = fResource.getPersistentProperty(TmfCommonConstants.TRACE_SUPPLEMENTARY_FOLDER);
-
-                file = new File(supplDirectory + File.separator + SYNCHRONIZATION_FORMULA_FILE);
-
-            } catch (CoreException e) {
-
-            }
-        }
-        return file;
-    }
-
     // ------------------------------------------------------------------------
     // Timestamp transformation functions
     // ------------------------------------------------------------------------
@@ -796,21 +767,7 @@ public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace, IT
     @Override
     public ITmfTimestampTransform getTimestampTransform() {
         if (fTsTransform == null) {
-            /* Check if a formula is stored somewhere in the resources */
-            File sync_file = getSyncFormulaFile();
-            if (sync_file != null && sync_file.exists()) {
-
-                try (FileInputStream fis = new FileInputStream(sync_file);
-                        ObjectInputStream ois = new ObjectInputStream(fis);) {
-
-                    fTsTransform = (ITmfTimestampTransform) ois.readObject();
-
-                } catch (ClassNotFoundException | IOException e) {
-                    fTsTransform = TimestampTransformFactory.getDefaultTransform();
-                }
-            } else {
-                fTsTransform = TimestampTransformFactory.getDefaultTransform();
-            }
+            fTsTransform = TimestampTransformFactory.getTimestampTransform(getResource());
         }
         return fTsTransform;
     }
@@ -821,23 +778,7 @@ public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace, IT
     @Override
     public void setTimestampTransform(final ITmfTimestampTransform tt) {
         fTsTransform = tt;
-
-        /* Save the timestamp transform to a file */
-        File sync_file = getSyncFormulaFile();
-        if (sync_file != null) {
-            if (sync_file.exists()) {
-                sync_file.delete();
-            }
-
-            /* Save the header of the file */
-            try (FileOutputStream fos = new FileOutputStream(sync_file, false);
-                    ObjectOutputStream oos = new ObjectOutputStream(fos);) {
-
-                oos.writeObject(fTsTransform);
-            } catch (IOException e1) {
-                Activator.logError("Error writing timestamp transform for trace", e1); //$NON-NLS-1$
-            }
-        }
+        TimestampTransformFactory.setTimestampTransform(getResource(), tt);
     }
 
     /**
index 757506a5408d4438e1263da0d161f3d28d7a3e82..cd48427d6c5b60d36c115f9798565a7540927dbf 100644 (file)
@@ -292,7 +292,10 @@ public abstract class TextTrace<T extends TextTraceEvent> extends TmfTrace imple
     protected abstract Pattern getFirstLinePattern();
 
     /**
-     * Parses the first line data and returns a new event.
+     * Parses the first line data and returns a new event. When constructing the
+     * event, the concrete trace should use the trace's timestamp transform to
+     * create the timestamp, by either transforming the parsed time value
+     * directly or by using the method {@link #createTimestamp(long)}.
      *
      * @param matcher
      *            The matcher
index 6231035f08d0147460f297187ef6acb07df92934..ececebc641c462b2df1ba2b09c6ecca247187e65 100644 (file)
@@ -70,10 +70,12 @@ public class PcapEventFactory {
         ITmfTimestamp tmfTimestamp;
         switch (scale) {
         case MICROSECOND:
-            tmfTimestamp = new TmfTimestamp(timestamp, ITmfTimestamp.MICROSECOND_SCALE, (int) pcap.getTimeAccuracy());
+            long us = trace.getTimestampTransform().transform(timestamp * 1000) / 1000;
+            tmfTimestamp = new TmfTimestamp(us, ITmfTimestamp.MICROSECOND_SCALE, (int) pcap.getTimeAccuracy());
             break;
         case NANOSECOND:
-            tmfTimestamp = new TmfTimestamp(timestamp, ITmfTimestamp.NANOSECOND_SCALE, (int) pcap.getTimeAccuracy());
+            long ns = trace.getTimestampTransform().transform(timestamp);
+            tmfTimestamp = new TmfTimestamp(ns, ITmfTimestamp.NANOSECOND_SCALE, (int) pcap.getTimeAccuracy());
             break;
         default:
             throw new IllegalArgumentException("The timestamp precision is not valid!"); //$NON-NLS-1$
index 1644e4d954e0424388a8ec213af4e0ecada7e037..00f19a3575a7aa1e32196f63f8d050aef9fa7476 100644 (file)
@@ -26,6 +26,7 @@ Export-Package: org.eclipse.linuxtools.internal.tmf.ui;x-friends:="org.eclipse.l
  org.eclipse.linuxtools.internal.tmf.ui.parsers.wizards;x-friends:="org.eclipse.linuxtools.tmf.ui.tests",
  org.eclipse.linuxtools.internal.tmf.ui.preferences;x-internal:=true,
  org.eclipse.linuxtools.internal.tmf.ui.project.dialogs;x-internal:=true,
+ org.eclipse.linuxtools.internal.tmf.ui.project.dialogs.offset;x-internal:=true,
  org.eclipse.linuxtools.internal.tmf.ui.project.handlers;x-friends:="org.eclipse.linuxtools.tmf.ui.tests",
  org.eclipse.linuxtools.internal.tmf.ui.project.model;x-friends:="org.eclipse.linuxtools.lttng2.ui,org.eclipse.linuxtools.tmf.ui.tests,org.eclipse.linuxtools.tmf.ctf.ui.tests",
  org.eclipse.linuxtools.internal.tmf.ui.project.operations;x-internal:=true,
index fb9ec6d1a50bff1d50ef3d3c742ccb25bc4259ee..4c2b539133f66977403eb19d617f88c4339ec00c 100644 (file)
@@ -109,6 +109,12 @@ command.synchronize_traces = Synchronize Traces
 command.synchronize_traces.mnemonic = y
 command.synchronize_traces.description = Synchronize 2 or more traces
 
+command.offset_traces = Apply Time Offset...
+command.offset_traces.description = Shift traces by a constant time offset
+
+command.clear_offset = Clear Time Offset
+command.clear_offset.description = Clear time offset
+
 ## Trace menu
 #  Open, Copy, Rename, Delete, Delete Supplementary Files, Select Trace Type
 
index f336ed28a2dcc53ce1b8c8ed849c2cfbe8a69c3e..e3ccaf012932d129db52b6a779139ab20f0e7d50 100644 (file)
                </with>
             </visibleWhen>
          </command>
+         <command
+               commandId="org.eclipse.linuxtools.tmf.ui.command.offset_traces"
+               label="%command.offset_traces"
+               style="push"
+               tooltip="%command.offset_traces.description">
+            <visibleWhen
+                  checkEnabled="true">
+            </visibleWhen>
+         </command>
+         <command
+               commandId="org.eclipse.linuxtools.tmf.ui.command.clear_offset"
+               label="%command.clear_offset"
+               style="push"
+               tooltip="%command.clear_offset.description">
+            <visibleWhen
+                  checkEnabled="true">
+            </visibleWhen>
+         </command>
          <separator
                name="org.eclipse.linuxtools.tmf.ui.separator5"
                visible="true">
             id="org.eclipse.linuxtools.tmf.ui.openFile"
             name="%command.OpenFile.name">
       </command>
+      <command
+            categoryId="org.eclipse.linuxtools.tmf.ui.commands.category"
+            description="%command.offset_traces.description"
+            id="org.eclipse.linuxtools.tmf.ui.command.offset_traces"
+            name="%command.offset_traces">
+      </command>
+      <command
+            categoryId="org.eclipse.linuxtools.tmf.ui.commands.category"
+            description="%command.clear_offset.description"
+            id="org.eclipse.linuxtools.tmf.ui.command.clear_offset"
+            name="%command.clear_offset">
+      </command>
    </extension>
    <extension
          point="org.eclipse.ui.handlers">
             </with>
          </activeWhen>
       </handler>
+      <handler
+            class="org.eclipse.linuxtools.internal.tmf.ui.project.handlers.OffsetTraceHandler"
+            commandId="org.eclipse.linuxtools.tmf.ui.command.offset_traces">
+         <activeWhen>
+            <with
+                  variable="selection">
+               <iterate
+                     ifEmpty="false"
+                     operator="and">
+                  <or>
+                     <instanceof
+                           value="org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceElement">
+                     </instanceof>
+                     <instanceof
+                           value="org.eclipse.linuxtools.tmf.ui.project.model.TmfExperimentElement">
+                     </instanceof>
+                     <instanceof
+                           value="org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceFolder">
+                     </instanceof>
+                  </or>
+               </iterate>
+            </with>
+         </activeWhen>
+      </handler>
+      <handler
+            class="org.eclipse.linuxtools.internal.tmf.ui.project.handlers.ClearTraceOffsetHandler"
+            commandId="org.eclipse.linuxtools.tmf.ui.command.clear_offset">
+         <activeWhen>
+            <with
+                  variable="selection">
+               <iterate
+                     ifEmpty="false"
+                     operator="and">
+                  <or>
+                     <instanceof
+                           value="org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceElement">
+                     </instanceof>
+                     <instanceof
+                           value="org.eclipse.linuxtools.tmf.ui.project.model.TmfExperimentElement">
+                     </instanceof>
+                     <instanceof
+                           value="org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceFolder">
+                     </instanceof>
+                  </or>
+               </iterate>
+            </with>
+         </activeWhen>
+      </handler>
    </extension>
    <extension point="org.eclipse.ui.bindings">
       <key
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/dialogs/offset/Messages.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/dialogs/offset/Messages.java
new file mode 100644 (file)
index 0000000..f545096
--- /dev/null
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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:
+ *   Matthew Khouzam - Initial API and implementation
+ *   Patrick Tasse - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.internal.tmf.ui.project.dialogs.offset;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Messages for the offset dialog
+ */
+public class Messages extends NLS {
+    private static final String BUNDLE_NAME = "org.eclipse.linuxtools.internal.tmf.ui.project.dialogs.offset.messages"; //$NON-NLS-1$
+
+    /**
+     * Advanced mode button
+     */
+    public static String OffsetDialog_AdvancedButton;
+    /**
+     * Advanced mode dialog message
+     */
+    public static String OffsetDialog_AdvancedMessage;
+    /**
+     * Basic mode button
+     */
+    public static String OffsetDialog_BasicButton;
+    /**
+     * Basic mode dialog message
+     */
+    public static String OffsetDialog_BasicMessage;
+    /**
+     * Offset time
+     */
+    public static String OffsetDialog_OffsetTime;
+    /**
+     * Reference time
+     */
+    public static String OffsetDialog_ReferenceTime;
+    /**
+     * Target time
+     */
+    public static String OffsetDialog_TargetTime;
+    /**
+     * Dialog title
+     */
+    public static String OffsetDialog_Title;
+    /**
+     * Trace name
+     */
+    public static String OffsetDialog_TraceName;
+    static {
+        // initialize resource bundle
+        NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+    }
+
+    private Messages() {
+    }
+}
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/dialogs/offset/OffsetDialog.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/dialogs/offset/OffsetDialog.java
new file mode 100644 (file)
index 0000000..3789d61
--- /dev/null
@@ -0,0 +1,578 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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:
+ *   Matthew Khouzam - Initial API and implementation
+ *   Patrick Tasse - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.internal.tmf.ui.project.dialogs.offset;
+
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.ColumnViewer;
+import org.eclipse.jface.viewers.ColumnViewerEditor;
+import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy;
+import org.eclipse.jface.viewers.EditingSupport;
+import org.eclipse.jface.viewers.FocusCellOwnerDrawHighlighter;
+import org.eclipse.jface.viewers.TextCellEditor;
+import org.eclipse.jface.viewers.TreeViewerColumn;
+import org.eclipse.jface.viewers.TreeViewerEditor;
+import org.eclipse.jface.viewers.TreeViewerFocusCellManager;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.linuxtools.tmf.core.signal.TmfEventSelectedSignal;
+import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
+import org.eclipse.linuxtools.tmf.core.signal.TmfSignalManager;
+import org.eclipse.linuxtools.tmf.core.signal.TmfTimeSynchSignal;
+import org.eclipse.linuxtools.tmf.core.signal.TmfTraceOpenedSignal;
+import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp;
+import org.eclipse.linuxtools.tmf.core.timestamp.TmfNanoTimestamp;
+import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestampFormat;
+import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
+import org.eclipse.linuxtools.tmf.core.trace.TmfTraceManager;
+import org.eclipse.linuxtools.tmf.ui.project.model.TmfOpenTraceHelper;
+import org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceElement;
+import org.eclipse.linuxtools.tmf.ui.viewers.ArrayTreeContentProvider;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.TreeEditor;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeColumn;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.ui.dialogs.FilteredTree;
+import org.eclipse.ui.dialogs.PatternFilter;
+
+/**
+ * Offset wizard dialog
+ *
+ * @author Matthew Khouzam
+ *
+ */
+public class OffsetDialog extends Dialog {
+
+    private static final int TREE_EDITOR_MIN_WIDTH = 50;
+    private static final String EDITOR_KEY = "$editor$";  //$NON-NLS-1$
+    private static final String WIDTH_KEY = "$width$";  //$NON-NLS-1$
+
+    private static final TmfTimestampFormat TIME_FORMAT = new TmfTimestampFormat("yyyy-MM-dd HH:mm:ss.SSS SSS SSS"); //$NON-NLS-1$
+    private static final TmfTimestampFormat OFFSET_FORMAT = new TmfTimestampFormat("T.SSS SSS SSS"); //$NON-NLS-1$
+
+    private final Map<TmfTraceElement, Long> fOffsetMap;
+    private final Map<TmfTraceElement, ITmfTimestamp> fRefTimeMap;
+    private final Map<TmfTraceElement, ITmfTimestamp> fTargetTimeMap;
+
+    private Label fBasicMessageLabel;
+    private Group fButtonGroup;
+    private Label fAdvancedMessageLabel;
+    private FilteredTree fViewer;
+
+    private boolean fAdvancedMode = true;
+    private TreeColumn fRefTimeColumn;
+    private TreeViewerColumn fButtonViewerColumn;
+    private TreeColumn fTargetTimeColumn;
+
+    private abstract class ColumnEditingSupport extends EditingSupport {
+        private final TextCellEditor textCellEditor;
+
+        private ColumnEditingSupport(ColumnViewer viewer, TextCellEditor textCellEditor) {
+            super(viewer);
+            this.textCellEditor = textCellEditor;
+        }
+
+        @Override
+        protected CellEditor getCellEditor(Object element) {
+            return textCellEditor;
+        }
+
+        @Override
+        protected boolean canEdit(Object element) {
+            return true;
+        }
+    }
+
+    private class TimeEditingSupport extends ColumnEditingSupport {
+        private Map<TmfTraceElement, ITmfTimestamp> map;
+
+        private TimeEditingSupport(ColumnViewer viewer, TextCellEditor textCellEditor, Map<TmfTraceElement, ITmfTimestamp> map) {
+            super(viewer, textCellEditor);
+            this.map = map;
+        }
+
+        @Override
+        protected void setValue(Object element, Object value) {
+            if (value instanceof String) {
+                String string = (String) value;
+                if (string.trim().isEmpty()) {
+                    map.remove(element);
+                } else {
+                    try {
+                        ITmfTimestamp refTime = map.get(element);
+                        long ref = refTime == null ? 0 : refTime.normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
+                        Long newVal = TIME_FORMAT.parseValue(string, ref);
+                        map.put((TmfTraceElement) element, new TmfNanoTimestamp(newVal));
+                    } catch (ParseException e) {
+                        /* Ignore and reload previous value */
+                    }
+                }
+                fViewer.getViewer().update(element, null);
+            }
+        }
+
+        @Override
+        protected Object getValue(Object element) {
+            if (map.get(element) == null) {
+                return ""; //$NON-NLS-1$
+            }
+            return TIME_FORMAT.format(map.get(element).normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue());
+        }
+    }
+
+    private class RefTimeEditingSupport extends TimeEditingSupport {
+        private RefTimeEditingSupport(ColumnViewer viewer, TextCellEditor textCellEditor) {
+            super(viewer, textCellEditor, fRefTimeMap);
+        }
+    }
+
+    private class TargetTimeEditingSupport extends TimeEditingSupport {
+        private TargetTimeEditingSupport(ColumnViewer viewer, TextCellEditor textCellEditor) {
+            super(viewer, textCellEditor, fTargetTimeMap);
+        }
+    }
+
+    private class OffsetEditingSupport extends ColumnEditingSupport {
+        private OffsetEditingSupport(ColumnViewer viewer, TextCellEditor textCellEditor) {
+            super(viewer, textCellEditor);
+        }
+
+        @Override
+        protected void setValue(Object element, Object value) {
+            if (value instanceof String) {
+                String string = (String) value;
+                if (string.trim().isEmpty()) {
+                    fOffsetMap.put((TmfTraceElement) element, 0L);
+                } else {
+                    try {
+                        Long newVal = OFFSET_FORMAT.parseValue(string);
+                        fOffsetMap.put((TmfTraceElement) element, newVal);
+                    } catch (ParseException e) {
+                        /* Ignore and reload previous value */
+                    }
+                }
+                fViewer.getViewer().update(element, null);
+            }
+        }
+
+        @Override
+        protected Object getValue(Object element) {
+            if (fOffsetMap.get(element) == 0) {
+                return ""; //$NON-NLS-1$
+            }
+            return OFFSET_FORMAT.format((long) fOffsetMap.get(element));
+        }
+    }
+
+    /**
+     * Constructor
+     *
+     * @param parent
+     *            parent shell
+     * @param results
+     *            results to put the data into
+     */
+    public OffsetDialog(Shell parent, Map<TmfTraceElement, Long> results) {
+        super(parent);
+        setShellStyle(getShellStyle() & ~SWT.APPLICATION_MODAL);
+        fOffsetMap = results;
+        fRefTimeMap = new HashMap<>();
+        fTargetTimeMap = new HashMap<>();
+    }
+
+    @Override
+    protected boolean isResizable() {
+        return true;
+    }
+
+    @Override
+    protected Control createDialogArea(Composite parent) {
+        getShell().setText(Messages.OffsetDialog_Title);
+        Composite area = (Composite) super.createDialogArea(parent);
+        Composite composite = new Composite(area, SWT.NONE);
+        composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+        GridLayout gl = new GridLayout();
+        gl.marginHeight = 0;
+        gl.marginWidth = 0;
+        composite.setLayout(new GridLayout());
+        createBasicMessage(composite);
+        createButtonGroup(composite);
+        createAdvancedMessage(composite);
+        createViewer(composite);
+
+        /* set label width hint equal to tree width */
+        int widthHint = fViewer.getViewer().getTree().computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
+        GridData gd = (GridData) fBasicMessageLabel.getLayoutData();
+        gd.widthHint = widthHint;
+        gd = (GridData) fAdvancedMessageLabel.getLayoutData();
+        gd.widthHint = widthHint;
+        gd = (GridData) composite.getLayoutData();
+        gd.heightHint = composite.computeSize(widthHint, SWT.DEFAULT).y;
+        setBasicMode();
+
+        TmfSignalManager.register(this);
+        composite.addDisposeListener(new DisposeListener() {
+            @Override
+            public void widgetDisposed(DisposeEvent e) {
+                TmfSignalManager.deregister(this);
+            }
+        });
+        return area;
+    }
+
+    private void createBasicMessage(final Composite parent) {
+        fBasicMessageLabel = new Label(parent, SWT.WRAP);
+        fBasicMessageLabel.setText(Messages.OffsetDialog_BasicMessage);
+        GridData gd = new GridData(SWT.FILL, SWT.CENTER, true, false);
+        gd.widthHint = 0;
+        gd.heightHint = SWT.DEFAULT;
+        fBasicMessageLabel.setLayoutData(gd);
+    }
+
+    private void createButtonGroup(final Composite parent) {
+        fButtonGroup = new Group(parent, SWT.SHADOW_NONE);
+        fButtonGroup.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
+        fButtonGroup.setLayout(new RowLayout(SWT.HORIZONTAL));
+
+        final Button basicButton = new Button(fButtonGroup, SWT.RADIO);
+        basicButton.setText(Messages.OffsetDialog_BasicButton);
+        basicButton.addSelectionListener(new SelectionAdapter() {
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                if (!basicButton.getSelection() || !fAdvancedMode) {
+                    return;
+                }
+                setBasicMode();
+                parent.layout();
+            }
+        });
+        basicButton.setSelection(true);
+
+        final Button advancedButton = new Button(fButtonGroup, SWT.RADIO);
+        advancedButton.setText(Messages.OffsetDialog_AdvancedButton);
+        advancedButton.addSelectionListener(new SelectionAdapter() {
+            @Override
+            public void widgetSelected(SelectionEvent e) {
+                if (!advancedButton.getSelection() || fAdvancedMode) {
+                    return;
+                }
+                setAdvancedMode();
+                parent.layout();
+            }
+        });
+    }
+
+    private void createAdvancedMessage(final Composite parent) {
+        fAdvancedMessageLabel = new Label(parent, SWT.WRAP);
+        fAdvancedMessageLabel.setText(Messages.OffsetDialog_AdvancedMessage);
+        GridData gd = new GridData(SWT.FILL, SWT.CENTER, true, false);
+        gd.widthHint = 0;
+        gd.heightHint = SWT.DEFAULT;
+        fAdvancedMessageLabel.setLayoutData(gd);
+    }
+
+    private void createViewer(Composite parent) {
+
+        // Define the TableViewer
+        fViewer = new FilteredTree(parent, SWT.MULTI | SWT.H_SCROLL
+                | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER, new PatternFilter() {
+            @Override
+            protected boolean isLeafMatch(Viewer viewer, Object element) {
+                return wordMatches(((TmfTraceElement) element).getElementPath());
+            }
+        }, true);
+
+        // Make lines and make header visible
+        final Tree tree = fViewer.getViewer().getTree();
+        tree.setHeaderVisible(true);
+        tree.setLinesVisible(true);
+
+        TreeViewerFocusCellManager focusCellManager = new TreeViewerFocusCellManager(fViewer.getViewer(), new FocusCellOwnerDrawHighlighter(fViewer.getViewer()));
+        ColumnViewerEditorActivationStrategy actSupport = new ColumnViewerEditorActivationStrategy(fViewer.getViewer());
+        TreeViewerEditor.create(fViewer.getViewer(), focusCellManager, actSupport, ColumnViewerEditor.TABBING_HORIZONTAL
+                | ColumnViewerEditor.TABBING_MOVE_TO_ROW_NEIGHBOR
+                | ColumnViewerEditor.TABBING_VERTICAL | ColumnViewerEditor.KEYBOARD_ACTIVATION);
+
+        final TextCellEditor textCellEditor = new TextCellEditor(fViewer.getViewer().getTree(), SWT.RIGHT);
+
+        fViewer.getViewer().setColumnProperties(new String[] { Messages.OffsetDialog_TraceName, Messages.OffsetDialog_ReferenceTime, Messages.OffsetDialog_OffsetTime });
+
+        TreeViewerColumn column = createTreeViewerColumn(Messages.OffsetDialog_TraceName, SWT.NONE);
+        column.setLabelProvider(new ColumnLabelProvider() {
+            @Override
+            public String getText(Object element) {
+                return ((TmfTraceElement) element).getElementPath();
+            }
+        });
+
+        column = createTreeViewerColumn(Messages.OffsetDialog_ReferenceTime, SWT.RIGHT);
+        column.setLabelProvider(new ColumnLabelProvider() {
+            @Override
+            public String getText(Object element) {
+                return super.getText(fRefTimeMap.get(element));
+            }
+        });
+        column.setEditingSupport(new RefTimeEditingSupport(fViewer.getViewer(), textCellEditor));
+        fRefTimeColumn = column.getColumn();
+
+        column = createTreeViewerColumn(Messages.OffsetDialog_OffsetTime, SWT.RIGHT);
+        column.setLabelProvider(new ColumnLabelProvider() {
+            @Override
+            public String getText(Object element) {
+                if (fOffsetMap.get(element) != 0) {
+                    return super.getText(OFFSET_FORMAT.format((long) fOffsetMap.get(element)));
+                }
+                return ""; //$NON-NLS-1$
+            }
+        });
+        column.setEditingSupport(new OffsetEditingSupport(fViewer.getViewer(), textCellEditor));
+
+        column = createTreeViewerColumn("", SWT.NONE); //$NON-NLS-1$
+        column.setLabelProvider(new ColumnLabelProvider() {
+            @Override
+            public String getText(Object element) {
+                return ""; //$NON-NLS-1$
+            }
+        });
+        column.getColumn().setWidth(TREE_EDITOR_MIN_WIDTH);
+        column.getColumn().setResizable(false);
+        fButtonViewerColumn = column;
+
+        column = createTreeViewerColumn(Messages.OffsetDialog_TargetTime, SWT.RIGHT);
+        column.setLabelProvider(new ColumnLabelProvider() {
+            @Override
+            public String getText(Object element) {
+                return super.getText(fTargetTimeMap.get(element));
+            }
+        });
+        column.setEditingSupport(new TargetTimeEditingSupport(fViewer.getViewer(), textCellEditor));
+        fTargetTimeColumn = column.getColumn();
+
+        List<TmfTraceElement> traces = new ArrayList<>(fOffsetMap.keySet());
+        Collections.sort(traces, new Comparator<TmfTraceElement>() {
+            @Override
+            public int compare(TmfTraceElement o1, TmfTraceElement o2) {
+                IPath folder1 = new Path(o1.getElementPath()).removeLastSegments(1);
+                IPath folder2 = new Path(o2.getElementPath()).removeLastSegments(1);
+                if (folder1.equals(folder2)) {
+                    return o1.getName().compareToIgnoreCase(o2.getName());
+                }
+                if (folder1.isPrefixOf(folder2)) {
+                    return 1;
+                } else if (folder2.isPrefixOf(folder1)) {
+                    return -1;
+                }
+                return folder1.toString().compareToIgnoreCase(folder2.toString());
+            }
+        });
+
+        fViewer.getViewer().setContentProvider(new ArrayTreeContentProvider());
+        fViewer.getViewer().setInput(traces);
+
+        /* add button as tree editors to fourth column of every item */
+        for (TreeItem treeItem : tree.getItems()) {
+            TreeEditor treeEditor = new TreeEditor(tree);
+            Button applyButton = new Button(tree, SWT.PUSH);
+            applyButton.setText("<<"); //$NON-NLS-1$
+            applyButton.setData(treeItem.getData());
+            applyButton.addSelectionListener(new SelectionAdapter() {
+                @Override
+                public void widgetSelected(SelectionEvent e) {
+                    TmfTraceElement traceElement = (TmfTraceElement) e.widget.getData();
+                    ITmfTimestamp targetTime = fTargetTimeMap.get(traceElement);
+                    ITmfTimestamp refTime = fRefTimeMap.get(traceElement);
+                    if (targetTime != null && refTime != null) {
+                        long offset = new TmfNanoTimestamp(targetTime).getValue() -
+                                new TmfNanoTimestamp(refTime).getValue();
+                        fOffsetMap.put(traceElement, offset);
+                        fViewer.getViewer().update(traceElement, null);
+                    }
+                }
+            });
+            treeEditor.grabHorizontal = true;
+            treeEditor.minimumWidth = TREE_EDITOR_MIN_WIDTH;
+            treeEditor.setEditor(applyButton, treeItem, 3);
+            treeItem.setData(EDITOR_KEY, applyButton);
+        }
+
+        /* put temporary values in maps to pack according to time formats */
+        fRefTimeMap.put(traces.get(0), new TmfNanoTimestamp());
+        fTargetTimeMap.put(traces.get(0), new TmfNanoTimestamp());
+        fViewer.getViewer().update(traces.get(0), null);
+        for (final TreeColumn treeColumn : tree.getColumns()) {
+            if (treeColumn.getResizable()) {
+                treeColumn.pack();
+            }
+        }
+        fRefTimeMap.clear();
+        fTargetTimeMap.clear();
+        fViewer.getViewer().update(traces.get(0), null);
+
+        for (TmfTraceElement traceElement : fOffsetMap.keySet()) {
+            for (ITmfTrace parentTrace : TmfTraceManager.getInstance().getOpenedTraces()) {
+                for (ITmfTrace trace : TmfTraceManager.getTraceSet(parentTrace)) {
+                    if (traceElement.getResource().equals(trace.getResource())) {
+                        fRefTimeMap.put(traceElement, trace.getStartTime());
+                        fViewer.getViewer().update(traceElement, null);
+                        break;
+                    }
+                }
+                if (fRefTimeMap.get(traceElement) != null) {
+                    break;
+                }
+            }
+        }
+
+        /* open trace when double-clicking a tree item */
+        tree.addSelectionListener(new SelectionAdapter() {
+            @Override
+            public void widgetDefaultSelected(SelectionEvent e) {
+                TmfTraceElement traceElement = (TmfTraceElement) e.item.getData();
+                TmfOpenTraceHelper.openTraceFromElement(traceElement);
+            }
+        });
+
+        tree.setFocus();
+    }
+
+    private TreeViewerColumn createTreeViewerColumn(String title, int style) {
+        final TreeViewerColumn viewerColumn = new TreeViewerColumn(fViewer.getViewer(), style);
+        final TreeColumn column = viewerColumn.getColumn();
+        column.setText(title);
+        column.setResizable(true);
+        return viewerColumn;
+    }
+
+    private void setBasicMode() {
+        fAdvancedMode = false;
+        fRefTimeColumn.setData(WIDTH_KEY, fRefTimeColumn.getWidth());
+        fTargetTimeColumn.setData(WIDTH_KEY, fTargetTimeColumn.getWidth());
+        for (TreeItem treeItem : fViewer.getViewer().getTree().getItems()) {
+            Control editor = (Control) treeItem.getData(EDITOR_KEY);
+            editor.setVisible(false);
+        }
+        fRefTimeColumn.setWidth(0);
+        fRefTimeColumn.setResizable(false);
+        fButtonViewerColumn.getColumn().setWidth(0);
+        fTargetTimeColumn.setWidth(0);
+        fTargetTimeColumn.setResizable(false);
+        fAdvancedMessageLabel.setText("");  //$NON-NLS-1$
+    }
+
+    private void setAdvancedMode() {
+        fAdvancedMode = true;
+        fRefTimeColumn.setWidth((Integer) fRefTimeColumn.getData(WIDTH_KEY));
+        fRefTimeColumn.setResizable(true);
+        fButtonViewerColumn.getColumn().setWidth(TREE_EDITOR_MIN_WIDTH);
+        fTargetTimeColumn.setWidth((Integer) fTargetTimeColumn.getData(WIDTH_KEY));
+        fTargetTimeColumn.setResizable(true);
+        for (TreeItem treeItem : fViewer.getViewer().getTree().getItems()) {
+            Control editor = (Control) treeItem.getData(EDITOR_KEY);
+            editor.setVisible(true);
+        }
+        fAdvancedMessageLabel.setText(Messages.OffsetDialog_AdvancedMessage);
+    }
+
+    /**
+     * Handler for the event selected signal
+     *
+     * @param signal
+     *            the event selected signal
+     */
+    @TmfSignalHandler
+    public void eventSelected(final TmfEventSelectedSignal signal) {
+        Display.getDefault().asyncExec(new Runnable() {
+            @Override
+            public void run() {
+                for (TmfTraceElement traceElement : fOffsetMap.keySet()) {
+                    if (traceElement.getResource().equals(signal.getEvent().getTrace().getResource())) {
+                        fRefTimeMap.put(traceElement, signal.getEvent().getTimestamp());
+                        fViewer.getViewer().update(traceElement, null);
+                        break;
+                    }
+                }
+            }
+        });
+    }
+
+    /**
+     * Handler for the time selected signal
+     *
+     * @param signal
+     *            the event selected signal
+     */
+    @TmfSignalHandler
+    public void timeSelected(final TmfTimeSynchSignal signal) {
+        Display.getDefault().asyncExec(new Runnable() {
+            @Override
+            public void run() {
+                for (TmfTraceElement traceElement : fOffsetMap.keySet()) {
+                    fTargetTimeMap.put(traceElement, signal.getBeginTime());
+                    fViewer.getViewer().update(traceElement, null);
+                }
+            }
+        });
+    }
+
+    /**
+     * Handler for the trace opened signal
+     *
+     * @param signal
+     *            the trace opened signal
+     */
+    @TmfSignalHandler
+    public void traceOpened(final TmfTraceOpenedSignal signal) {
+        Display.getDefault().asyncExec(new Runnable() {
+            @Override
+            public void run() {
+                for (ITmfTrace trace : TmfTraceManager.getTraceSet(signal.getTrace())) {
+                    for (TmfTraceElement traceElement : fOffsetMap.keySet()) {
+                        if (traceElement.getResource().equals(trace.getResource())) {
+                            if (fRefTimeMap.get(traceElement) == null) {
+                                fRefTimeMap.put(traceElement, trace.getStartTime());
+                                fViewer.getViewer().update(traceElement, null);
+                            }
+                            break;
+                        }
+                    }
+                }
+            }
+        });
+    }
+}
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/dialogs/offset/messages.properties b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/dialogs/offset/messages.properties
new file mode 100644 (file)
index 0000000..af1de0d
--- /dev/null
@@ -0,0 +1,24 @@
+###############################################################################
+# Copyright (c) 2014 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:
+#   Matthew Khouzam - Initial API and implementation
+#   Patrick Tasse - Initial API and implementation
+###############################################################################
+
+OffsetDialog_AdvancedButton=Advanced
+OffsetDialog_AdvancedMessage=Double-click a trace to open it, and select an event to set a reference time.  \
+If the reference time and target time are set, press the button to compute their offset automatically.  \
+The reference time and target time can be entered in format 'yyyy-mm-dd hh:mm:ss.sss sss sss'.
+OffsetDialog_BasicButton=Basic
+OffsetDialog_BasicMessage=Set the time offset to apply to each trace.
+OffsetDialog_OffsetTime=Offset in seconds
+OffsetDialog_ReferenceTime=Reference Time
+OffsetDialog_TargetTime=Target Time
+OffsetDialog_Title=Apply time offset
+OffsetDialog_TraceName=Trace name
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/handlers/ClearTraceOffsetHandler.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/handlers/ClearTraceOffsetHandler.java
new file mode 100644 (file)
index 0000000..b9df3f0
--- /dev/null
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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:
+ *   Patrick Tasse - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.internal.tmf.ui.project.handlers;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.linuxtools.internal.tmf.ui.project.operations.TmfWorkspaceModifyOperation;
+import org.eclipse.linuxtools.tmf.core.synchronization.TimestampTransformFactory;
+import org.eclipse.linuxtools.tmf.ui.project.model.TmfExperimentElement;
+import org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceElement;
+import org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceFolder;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.MessageBox;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Clear Trace Offset Handler
+ *
+ * @author Patrick Tasse
+ */
+public class ClearTraceOffsetHandler extends AbstractHandler {
+
+    // ------------------------------------------------------------------------
+    // Execution
+    // ------------------------------------------------------------------------
+
+    @Override
+    public Object execute(final ExecutionEvent event) throws ExecutionException {
+
+        ISelection selection = HandlerUtil.getCurrentSelection(event);
+
+        // Get the set of selected trace elements
+        final Set<TmfTraceElement> traceElements = new HashSet<>();
+        if (selection instanceof StructuredSelection) {
+            Iterator<Object> iterator = ((StructuredSelection) selection).iterator();
+            while (iterator.hasNext()) {
+                Object element = iterator.next();
+                if (element instanceof TmfTraceElement) {
+                    TmfTraceElement trace = (TmfTraceElement) element;
+                    traceElements.add(trace.getElementUnderTraceFolder());
+                } else if (element instanceof TmfExperimentElement) {
+                    TmfExperimentElement exp = (TmfExperimentElement) element;
+                    for (TmfTraceElement trace : exp.getTraces()) {
+                        traceElements.add(trace.getElementUnderTraceFolder());
+                    }
+                } else if (element instanceof TmfTraceFolder) {
+                    TmfTraceFolder folder = (TmfTraceFolder) element;
+                    traceElements.addAll(folder.getTraces());
+                }
+            }
+        }
+
+        Shell shell = HandlerUtil.getActiveShellChecked(event);
+        MessageBox mb = new MessageBox(shell, SWT.ICON_QUESTION | SWT.CANCEL | SWT.OK);
+        mb.setText(Messages.ClearTraceOffsetHandler_Title);
+        mb.setMessage(Messages.ClearTraceOffsetHandler_ConfirmMessage);
+        if (mb.open() != SWT.OK) {
+            return null;
+        }
+
+        TmfWorkspaceModifyOperation operation = new TmfWorkspaceModifyOperation() {
+            @Override
+            public void execute(IProgressMonitor monitor) throws CoreException {
+                for (final TmfTraceElement trace : traceElements) {
+                    if (monitor.isCanceled()) {
+                        throw new OperationCanceledException();
+                    }
+                    if (!TimestampTransformFactory.getTimestampTransform(trace.getResource()).equals(TimestampTransformFactory.getDefaultTransform())) {
+                        Display.getDefault().syncExec(new Runnable() {
+                            @Override
+                            public void run() {
+                                trace.closeEditors();
+                            }
+                        });
+                        trace.deleteSupplementaryResources();
+                        TimestampTransformFactory.setTimestampTransform(trace.getResource(), null);
+                        trace.refreshSupplementaryFolder();
+                    }
+                }
+            }
+        };
+        try {
+            PlatformUI.getWorkbench().getProgressService().run(true, true, operation);
+        } catch (InterruptedException e) {
+            return null;
+        } catch (InvocationTargetException e) {
+            MessageDialog.openError(shell, e.toString(), e.getTargetException().toString());
+            return null;
+        }
+
+        return null;
+    }
+}
index 292bc07eca7446e2ae6dd8676c575fa204473b0f..7345391cb28eb305a59a929b2fa424711e837b53 100644 (file)
@@ -42,6 +42,7 @@ import org.eclipse.linuxtools.tmf.ui.project.model.TmfCommonProjectElement;
 import org.eclipse.linuxtools.tmf.ui.project.model.TmfExperimentElement;
 import org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceElement;
 import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.widgets.Display;
 import org.eclipse.ui.IWorkbenchWindow;
 import org.eclipse.ui.PlatformUI;
 import org.eclipse.ui.handlers.HandlerUtil;
@@ -136,7 +137,7 @@ public class DeleteTraceSupplementaryFilesHandler extends AbstractHandler {
 
                 SubMonitor subMonitor = SubMonitor.convert(monitor, allResourcesToDelete.size());
 
-                for (TmfCommonProjectElement element : resourceMap.keySet()) {
+                for (final TmfCommonProjectElement element : resourceMap.keySet()) {
                     if (monitor.isCanceled()) {
                         throw new OperationCanceledException();
                     }
@@ -145,7 +146,12 @@ public class DeleteTraceSupplementaryFilesHandler extends AbstractHandler {
                     if (!traceResourcesToDelete.isEmpty()) {
                         subMonitor.setTaskName(NLS.bind(Messages.DeleteSupplementaryFiles_DeletionTask, element.getElementPath()));
                         // Delete the selected resources
-                        element.closeEditors();
+                        Display.getDefault().syncExec(new Runnable() {
+                            @Override
+                            public void run() {
+                                element.closeEditors();
+                            }
+                        });
                         element.deleteSupplementaryResources(traceResourcesToDelete.toArray(new IResource[0]));
                         projectsToRefresh.add(element.getProject().getResource());
                     }
index df59ebbd0f5129d70eded16ecc5d7cf711a121a8..0b93660ae3155b00d5a5b7bec628edad1f553c1f 100644 (file)
@@ -65,6 +65,9 @@ public class Messages extends NLS {
     public static String SynchronizeTracesHandler_ErrorSynchingExperiment;
     public static String SynchronizeTracesHandler_ErrorSynchingForTrace;
 
+    public static String ClearTraceOffsetHandler_Title;
+    public static String ClearTraceOffsetHandler_ConfirmMessage;
+
     public static String DeleteSupplementaryFiles_DeletionTask;
     public static String DeleteSupplementaryFiles_ProjectRefreshTask;
 
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/handlers/OffsetTraceHandler.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/handlers/OffsetTraceHandler.java
new file mode 100644 (file)
index 0000000..564e9de
--- /dev/null
@@ -0,0 +1,132 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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:
+ *   Matthew Khouzam - Initial API and implementation
+ *   Patrick Tasse - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.internal.tmf.ui.project.handlers;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.window.Window;
+import org.eclipse.linuxtools.internal.tmf.ui.project.dialogs.offset.OffsetDialog;
+import org.eclipse.linuxtools.internal.tmf.ui.project.operations.TmfWorkspaceModifyOperation;
+import org.eclipse.linuxtools.tmf.core.synchronization.ITmfTimestampTransform;
+import org.eclipse.linuxtools.tmf.core.synchronization.TimestampTransformFactory;
+import org.eclipse.linuxtools.tmf.ui.project.model.TmfExperimentElement;
+import org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceElement;
+import org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceFolder;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Offset Handler
+ *
+ * @author Matthew Khouzam
+ */
+public class OffsetTraceHandler extends AbstractHandler {
+
+    // ------------------------------------------------------------------------
+    // Execution
+    // ------------------------------------------------------------------------
+
+    @Override
+    public Object execute(final ExecutionEvent event) throws ExecutionException {
+
+        ISelection selection = HandlerUtil.getCurrentSelection(event);
+
+        // Get the set of selected trace elements
+        final Set<TmfTraceElement> traceElements = new HashSet<>();
+        if (selection instanceof StructuredSelection) {
+            Iterator<Object> iterator = ((StructuredSelection) selection).iterator();
+            while (iterator.hasNext()) {
+                Object element = iterator.next();
+                if (element instanceof TmfTraceElement) {
+                    TmfTraceElement trace = (TmfTraceElement) element;
+                    traceElements.add(trace.getElementUnderTraceFolder());
+                } else if (element instanceof TmfExperimentElement) {
+                    TmfExperimentElement exp = (TmfExperimentElement) element;
+                    for (TmfTraceElement trace : exp.getTraces()) {
+                        traceElements.add(trace.getElementUnderTraceFolder());
+                    }
+                } else if (element instanceof TmfTraceFolder) {
+                    TmfTraceFolder folder = (TmfTraceFolder) element;
+                    traceElements.addAll(folder.getTraces());
+                }
+            }
+        }
+
+        final Map<TmfTraceElement, Long> offsets = new LinkedHashMap<>(traceElements.size());
+        for (TmfTraceElement trace : traceElements) {
+            offsets.put(trace, 0L);
+        }
+
+        Shell shell = HandlerUtil.getActiveShellChecked(event);
+        OffsetDialog dialog = new OffsetDialog(shell, offsets);
+        dialog.open();
+
+        if (dialog.getReturnCode() != Window.OK) {
+            return null;
+        }
+
+        TmfWorkspaceModifyOperation operation = new TmfWorkspaceModifyOperation() {
+            @Override
+            public void execute(IProgressMonitor monitor) throws CoreException {
+                for (final TmfTraceElement trace : offsets.keySet()) {
+                    if (monitor.isCanceled()) {
+                        throw new OperationCanceledException();
+                    }
+                    Long offset = offsets.get(trace);
+                    if (offset != 0 && trace.getResource().exists()) {
+                        Display.getDefault().syncExec(new Runnable() {
+                            @Override
+                            public void run() {
+                                trace.closeEditors();
+                            }
+                        });
+                        long previousOffset = TimestampTransformFactory.getTimestampTransform(trace.getResource()).transform(0);
+                        ITmfTimestampTransform transform = TimestampTransformFactory.createWithOffset(previousOffset + offset);
+                        trace.deleteSupplementaryResources();
+                        // make sure the supplementary folder exists
+                        trace.refreshSupplementaryFolder();
+                        TimestampTransformFactory.setTimestampTransform(trace.getResource(), transform);
+                        trace.refreshSupplementaryFolder();
+                    }
+                }
+            }
+        };
+        try {
+            PlatformUI.getWorkbench().getProgressService().run(true, true, operation);
+        } catch (InterruptedException e) {
+            return null;
+        } catch (InvocationTargetException e) {
+            MessageDialog.openError(shell, e.toString(), e.getTargetException().toString());
+            return null;
+        }
+
+        return null;
+    }
+}
index 685ac69401c0fb106384a01a96cfa74772938052..95ab3da1f38218408c548e4dac598756f9aca120 100644 (file)
@@ -55,6 +55,9 @@ SynchronizeTracesHandler_Error=Error synchronizing experiment
 SynchronizeTracesHandler_ErrorSynchingExperiment=Error synchronizing experiment %s
 SynchronizeTracesHandler_ErrorSynchingForTrace=Error synchronizing experiment %s for trace %s
 
+ClearTraceOffsetHandler_Title=Clear time offset
+ClearTraceOffsetHandler_ConfirmMessage=Are you sure you want to clear the time offset for the selected trace(s)?
+
 # Delete Supplementary Files messages
 DeleteSupplementaryFiles_DeletionTask=Deleting supplementary files for {0}
 DeleteSupplementaryFiles_ProjectRefreshTask=Refreshing project {0}
index 0b422fbb88a1f4f6ae580d097c709eeb8e74bd36..6fe065fdd35045fc958351c51146aebbcbf66e69 100644 (file)
@@ -76,6 +76,10 @@ public class Messages extends NLS {
      * @since 3.0*/
     public static String TmfTraceElement_SourceLocation;
 
+    /** The descriptor for the time offset property
+     * @since 3.2*/
+    public static String TmfTraceElement_TimeOffset;
+
     /** Trace text
      * @since 3.0*/
     public static String TmfTraceElement_TypeName;
index 0ab4546d3150e6d09018237e2bd683e65958fd76..52e53a8fd58008a25d2a0b947125147fea935ecd 100644 (file)
@@ -479,7 +479,12 @@ public abstract class TmfCommonProjectElement extends TmfProjectModelElement {
      * trace resource
      */
     public void refreshSupplementaryFolder() {
-        createSupplementaryFolder();
+        IFolder supplFolder = createSupplementaryFolder();
+        try {
+            supplFolder.refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor());
+        } catch (CoreException e) {
+            Activator.getDefault().logError("Error refreshing supplementary folder " + supplFolder, e); //$NON-NLS-1$
+        }
     }
 
     /**
@@ -534,7 +539,7 @@ public abstract class TmfCommonProjectElement extends TmfProjectModelElement {
         deleteSupplementaryResources(getSupplementaryResources());
     }
 
-    private void createSupplementaryFolder() {
+    private IFolder createSupplementaryFolder() {
         IFolder supplFolder = prepareTraceSupplementaryFolder(getSupplementaryFolderPath(), true);
 
         try {
@@ -542,7 +547,7 @@ public abstract class TmfCommonProjectElement extends TmfProjectModelElement {
         } catch (CoreException e) {
             Activator.getDefault().logError("Error setting persistant property " + TmfCommonConstants.TRACE_SUPPLEMENTARY_FOLDER, e); //$NON-NLS-1$
         }
-
+        return supplFolder;
     }
 
     // -------------------------------------------------------
index e4ca0b84081af297de9ffcbe73c01eba89ee5c7a..ca2d61308ccc6a130545eaf98475a37ab261cc78 100644 (file)
@@ -45,6 +45,8 @@ import org.eclipse.linuxtools.tmf.core.parsers.custom.CustomXmlTrace;
 import org.eclipse.linuxtools.tmf.core.parsers.custom.CustomXmlTraceDefinition;
 import org.eclipse.linuxtools.tmf.core.project.model.TmfTraceType;
 import org.eclipse.linuxtools.tmf.core.project.model.TraceTypeHelper;
+import org.eclipse.linuxtools.tmf.core.synchronization.TimestampTransformFactory;
+import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestampFormat;
 import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
 import org.eclipse.linuxtools.tmf.core.trace.ITmfTraceProperties;
 import org.eclipse.linuxtools.tmf.core.trace.TmfTrace;
@@ -88,6 +90,7 @@ public class TmfTraceElement extends TmfCommonProjectElement implements IActionF
     private static final String sfTraceType = Messages.TmfTraceElement_EventType;
     private static final String sfIsLinked = Messages.TmfTraceElement_IsLinked;
     private static final String sfSourceLocation = Messages.TmfTraceElement_SourceLocation;
+    private static final String sfTimeOffset = Messages.TmfTraceElement_TimeOffset;
     private static final String sfTracePropertiesCategory = Messages.TmfTraceElement_TraceProperties;
 
     private static final ReadOnlyTextPropertyDescriptor sfNameDescriptor = new ReadOnlyTextPropertyDescriptor(sfName, sfName);
@@ -96,9 +99,11 @@ public class TmfTraceElement extends TmfCommonProjectElement implements IActionF
     private static final ReadOnlyTextPropertyDescriptor sfTypeDescriptor = new ReadOnlyTextPropertyDescriptor(sfTraceType, sfTraceType);
     private static final ReadOnlyTextPropertyDescriptor sfIsLinkedDescriptor = new ReadOnlyTextPropertyDescriptor(sfIsLinked, sfIsLinked);
     private static final ReadOnlyTextPropertyDescriptor sfSourceLocationDescriptor = new ReadOnlyTextPropertyDescriptor(sfSourceLocation, sfSourceLocation);
+    private static final ReadOnlyTextPropertyDescriptor sfTimeOffsetDescriptor = new ReadOnlyTextPropertyDescriptor(sfTimeOffset, sfTimeOffset);
 
     private static final IPropertyDescriptor[] sfDescriptors = { sfNameDescriptor, sfPathDescriptor, sfLocationDescriptor,
-            sfTypeDescriptor, sfIsLinkedDescriptor, sfSourceLocationDescriptor };
+            sfTypeDescriptor, sfIsLinkedDescriptor, sfSourceLocationDescriptor,
+            sfTimeOffsetDescriptor};
 
     static {
         sfNameDescriptor.setCategory(sfResourcePropertiesCategory);
@@ -107,8 +112,11 @@ public class TmfTraceElement extends TmfCommonProjectElement implements IActionF
         sfTypeDescriptor.setCategory(sfResourcePropertiesCategory);
         sfIsLinkedDescriptor.setCategory(sfResourcePropertiesCategory);
         sfSourceLocationDescriptor.setCategory(sfResourcePropertiesCategory);
+        sfTimeOffsetDescriptor.setCategory(sfResourcePropertiesCategory);
     }
 
+    private static final TmfTimestampFormat OFFSET_FORMAT = new TmfTimestampFormat("T.SSS SSS SSS s"); //$NON-NLS-1$
+
     // ------------------------------------------------------------------------
     // Static initialization
     // ------------------------------------------------------------------------
@@ -459,6 +467,14 @@ public class TmfTraceElement extends TmfCommonProjectElement implements IActionF
             return ""; //$NON-NLS-1$
         }
 
+        if (sfTimeOffset.equals(id)) {
+            long offset = TimestampTransformFactory.getTimestampTransform(getElementUnderTraceFolder().getResource()).transform(0);
+            if (offset != 0) {
+                return OFFSET_FORMAT.format(offset);
+            }
+            return ""; //$NON-NLS-1$
+        }
+
         Map<String, String> traceProperties = getTraceProperties();
         if (id != null && !traceProperties.isEmpty()) {
             String key = (String) id;
index 1d5c3a924ad43cabb52c8cac34fad0a584b925fd..419252873dfee6bea4eadbbc27ce3d00609dadcd 100644 (file)
@@ -27,6 +27,7 @@ TmfTraceElement_Location = location
 TmfTraceElement_EventType = type
 TmfTraceElement_IsLinked = linked
 TmfTraceElement_SourceLocation = source location
+TmfTraceElement_TimeOffset = time offset
 TmfTraceElement_TypeName=Trace
 TmfTraceType_SelectTraceType=Select Trace Type
 
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/ArrayTreeContentProvider.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/ArrayTreeContentProvider.java
new file mode 100644 (file)
index 0000000..f561e53
--- /dev/null
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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:
+ *   Patrick Tasse - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.tmf.ui.viewers;
+
+import java.util.Collection;
+
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+
+/**
+ * This implementation of <code>ITreeContentProvider</code> handles the case
+ * where the viewer input is an unchanging array or collection of elements.
+ * The elements do not have children.
+ *
+ * @author Patrick Tasse
+ * @since 3.2
+ */
+public class ArrayTreeContentProvider implements ITreeContentProvider {
+
+    @Override
+    public void dispose() {
+    }
+
+    @Override
+    public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+    }
+
+    @Override
+    public Object[] getChildren(Object parentElement) {
+        return null;
+    }
+
+    @Override
+    public Object getParent(Object element) {
+        return null;
+    }
+
+    @Override
+    public boolean hasChildren(Object element) {
+        return false;
+    }
+
+    @Override
+    public Object[] getElements(Object inputElement) {
+        if (inputElement instanceof Object[]) {
+            return (Object[]) inputElement;
+        }
+        if (inputElement instanceof Collection) {
+            return ((Collection<?>) inputElement).toArray();
+        }
+        return new Object[0];
+    }
+
+}
index 31771d70e929ea8c18244bb46df8eb977c20df48..6523a7cf4b294acd62b48f16a0cb9ac568960733 100644 (file)
@@ -93,6 +93,7 @@ import org.eclipse.linuxtools.tmf.core.request.ITmfEventRequest.ExecutionType;
 import org.eclipse.linuxtools.tmf.core.request.TmfEventRequest;
 import org.eclipse.linuxtools.tmf.core.signal.TmfEventFilterAppliedSignal;
 import org.eclipse.linuxtools.tmf.core.signal.TmfEventSearchAppliedSignal;
+import org.eclipse.linuxtools.tmf.core.signal.TmfEventSelectedSignal;
 import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
 import org.eclipse.linuxtools.tmf.core.signal.TmfTimeSynchSignal;
 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceUpdatedSignal;
@@ -473,7 +474,8 @@ public class TmfEventsTable extends TmfComponent implements IGotoMarker, IColorS
                         }
                     }
                 }
-                if (e.item.getData() != null) {
+                if (e.item.getData() instanceof ITmfEvent) {
+                    broadcast(new TmfEventSelectedSignal(TmfEventsTable.this, (ITmfEvent) e.item.getData()));
                     fireSelectionChanged(new SelectionChangedEvent(TmfEventsTable.this, new StructuredSelection(e.item.getData())));
                 } else {
                     fireSelectionChanged(new SelectionChangedEvent(TmfEventsTable.this, StructuredSelection.EMPTY));
This page took 0.052559 seconds and 5 git commands to generate.