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(),
/** 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$
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();
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;
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);
--- /dev/null
+/*******************************************************************************
+ * 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$
+ }
+}
*******************************************************************************/
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;
/**
*/
public final class TimestampTransformFactory {
+ private static final String SYNCHRONIZATION_FORMULA_FILE = "sync_formula"; //$NON-NLS-1$
+
private 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$
+ }
+ }
+ }
+
}
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;
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;
* 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.
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
// ------------------------------------------------------------------------
}
}
- /**
- * 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
// ------------------------------------------------------------------------
@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;
}
@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);
}
/**
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
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$
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,
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
</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
--- /dev/null
+/*******************************************************************************
+ * 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() {
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * 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;
+ }
+ }
+ }
+ }
+ });
+ }
+}
--- /dev/null
+###############################################################################
+# 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
--- /dev/null
+/*******************************************************************************
+ * 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;
+ }
+}
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;
SubMonitor subMonitor = SubMonitor.convert(monitor, allResourcesToDelete.size());
- for (TmfCommonProjectElement element : resourceMap.keySet()) {
+ for (final TmfCommonProjectElement element : resourceMap.keySet()) {
if (monitor.isCanceled()) {
throw new OperationCanceledException();
}
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());
}
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;
--- /dev/null
+/*******************************************************************************
+ * 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;
+ }
+}
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}
* @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;
* 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$
+ }
}
/**
deleteSupplementaryResources(getSupplementaryResources());
}
- private void createSupplementaryFolder() {
+ private IFolder createSupplementaryFolder() {
IFolder supplFolder = prepareTraceSupplementaryFolder(getSupplementaryFolderPath(), true);
try {
} catch (CoreException e) {
Activator.getDefault().logError("Error setting persistant property " + TmfCommonConstants.TRACE_SUPPLEMENTARY_FOLDER, e); //$NON-NLS-1$
}
-
+ return supplFolder;
}
// -------------------------------------------------------
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;
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);
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);
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
// ------------------------------------------------------------------------
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;
TmfTraceElement_EventType = type
TmfTraceElement_IsLinked = linked
TmfTraceElement_SourceLocation = source location
+TmfTraceElement_TimeOffset = time offset
TmfTraceElement_TypeName=Trace
TmfTraceType_SelectTraceType=Select Trace Type
--- /dev/null
+/*******************************************************************************
+ * 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];
+ }
+
+}
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;
}
}
}
- 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));