tmf: Add cycles time format and delta format in time graph
authorPatrick Tasse <patrick.tasse@gmail.com>
Thu, 21 Aug 2014 19:27:39 +0000 (15:27 -0400)
committerPatrick Tasse <patrick.tasse@gmail.com>
Tue, 16 Sep 2014 22:06:15 +0000 (18:06 -0400)
Change-Id: Iaa0e750971bf7b06a6209f7528e8c293be816d9c
Signed-off-by: Patrick Tasse <patrick.tasse@gmail.com>
Reviewed-on: https://git.eclipse.org/r/33339
Tested-by: Hudson CI
Reviewed-by: Alexandre Montplaisir <alexmonthy@voxpopuli.im>
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/Messages.java
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/messages.properties
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/widgets/timegraph/TimeGraphViewer.java
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/widgets/timegraph/widgets/ITimeDataProviderConverter.java [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/widgets/timegraph/widgets/TimeDataProviderCyclesConverter.java [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/widgets/timegraph/widgets/TimeGraphControl.java
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/widgets/timegraph/widgets/TimeGraphScale.java
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/widgets/timegraph/widgets/TimeGraphTooltipHandler.java
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/widgets/timegraph/widgets/Utils.java

index 06e3683c70010e3a7248e46f1846036e1bba0078..17a6591dacf1b14cf253cea76348b5ceeb3924be 100644 (file)
@@ -119,6 +119,8 @@ public class Messages extends NLS {
     public static String TmfTimeGraphViewer_FollowArrowBackwardActionNameText;
     public static String TmfTimeGraphViewer_FollowArrowBackwardActionToolTipText;
 
+    public static String Utils_ClockCyclesUnit;
+
     public static String ColorsView_AddActionToolTipText;
     public static String ColorsView_BackgroundButtonText;
     public static String ColorsView_BackgroundDialogText;
index 4b3c6bc997dac00add25f721f1564237b91aedba..07789b254d1d3a505106610de7f4e913e2878e7f 100644 (file)
@@ -115,6 +115,8 @@ TmfTimeGraphViewer_FollowArrowForwardActionToolTipText=Follow Arrow Forward
 TmfTimeGraphViewer_FollowArrowBackwardActionNameText=Follow Arrow Backward
 TmfTimeGraphViewer_FollowArrowBackwardActionToolTipText=Follow Arrow Backward
 
+Utils_ClockCyclesUnit=\u0020cc
+
 # org.eclipse.linuxtools.tmf.ui.views.colors
 ColorsView_AddActionToolTipText=Insert new color setting
 ColorsView_BackgroundButtonText=BG
index 5b7ab9a284b67d473fb777c78392fc24d1c829e9..db8c53d45ac96d09a9bc90dc97ac6be5b6e7e0cb 100644 (file)
@@ -33,6 +33,7 @@ import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ILinkEvent;
 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeEvent;
 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.ITimeDataProvider;
+import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.TimeDataProviderCyclesConverter;
 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.TimeGraphColorScheme;
 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.TimeGraphControl;
 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.TimeGraphScale;
@@ -77,6 +78,7 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
     private static final int DEFAULT_HEIGHT = 22;
     private static final long RECENTERING_MARGIN_FACTOR = 50;
     private static final String HIDE_ARROWS_KEY = "hide.arrows"; //$NON-NLS-1$
+    private static final long DEFAULT_FREQUENCY = 1000000000L;
 
     private long fMinTimeInterval;
     private ITimeGraphEntry fSelectedEntry;
@@ -103,14 +105,18 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
     private Object fInputElement;
     private ITimeGraphContentProvider fTimeGraphContentProvider;
     private ITimeGraphPresentationProvider fTimeGraphProvider;
+    private ITimeDataProvider fTimeDataProvider = this;
+    private TimeGraphTooltipHandler fToolTipHandler;
 
     private List<ITimeGraphSelectionListener> fSelectionListeners = new ArrayList<>();
     private List<ITimeGraphTimeListener> fTimeListeners = new ArrayList<>();
     private List<ITimeGraphRangeListener> fRangeListeners = new ArrayList<>();
 
-    // Time format, using Epoch reference, Relative time format(default) or
-    // Number
+    // Time format, using Epoch reference, Relative time format(default),
+    // Number, or Cycles
     private TimeFormat fTimeFormat = TimeFormat.RELATIVE;
+    // Clock frequency to use for Cycles time format
+    private long fClockFrequency = DEFAULT_FREQUENCY;
     private int fBorderWidth = 0;
     private int fTimeScaleHeight = DEFAULT_HEIGHT;
 
@@ -181,8 +187,8 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
     public void setTimeGraphProvider(ITimeGraphPresentationProvider timeGraphProvider) {
         fTimeGraphProvider = timeGraphProvider;
         fTimeGraphCtrl.setTimeGraphProvider(timeGraphProvider);
-        TimeGraphTooltipHandler toolTipHandler = new TimeGraphTooltipHandler(fTimeGraphProvider, this);
-        toolTipHandler.activateHoverHelp(fTimeGraphCtrl);
+        fToolTipHandler = new TimeGraphTooltipHandler(fTimeGraphProvider, fTimeDataProvider);
+        fToolTipHandler.activateHoverHelp(fTimeGraphCtrl);
     }
 
     /**
@@ -345,7 +351,7 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
         fDataViewer.setLayout(gl);
 
         fTimeScaleCtrl = new TimeGraphScale(fDataViewer, fColorScheme);
-        fTimeScaleCtrl.setTimeProvider(this);
+        fTimeScaleCtrl.setTimeProvider(fTimeDataProvider);
         fTimeScaleCtrl.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, false));
         fTimeScaleCtrl.setHeight(fTimeScaleHeight);
 
@@ -1057,6 +1063,33 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener {
      */
     public void setTimeFormat(TimeFormat tf) {
         this.fTimeFormat = tf;
+        if (tf == TimeFormat.CYCLES) {
+            fTimeDataProvider = new TimeDataProviderCyclesConverter(this, fClockFrequency);
+        } else {
+            fTimeDataProvider = this;
+        }
+        fTimeScaleCtrl.setTimeProvider(fTimeDataProvider);
+        if (fToolTipHandler != null) {
+            fToolTipHandler.setTimeProvider(fTimeDataProvider);
+        }
+    }
+
+    /**
+     * Sets the clock frequency. Used when the time format is set to CYCLES.
+     *
+     * @param clockFrequency
+     *            the clock frequency in Hz
+     * @since 3.1
+     */
+    public void setClockFrequency(long clockFrequency) {
+        fClockFrequency = clockFrequency;
+        if (fTimeFormat == TimeFormat.CYCLES) {
+            fTimeDataProvider = new TimeDataProviderCyclesConverter(this, fClockFrequency);
+            fTimeScaleCtrl.setTimeProvider(fTimeDataProvider);
+            if (fToolTipHandler != null) {
+                fToolTipHandler.setTimeProvider(fTimeDataProvider);
+            }
+        }
     }
 
     /**
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/widgets/timegraph/widgets/ITimeDataProviderConverter.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/widgets/timegraph/widgets/ITimeDataProviderConverter.java
new file mode 100644 (file)
index 0000000..c859aec
--- /dev/null
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * 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.widgets.timegraph.widgets;
+
+/**
+ * Time data provider that converts between time data units used internally and
+ * time in display units used by the caller.
+ *
+ * @since 3.1
+ */
+public interface ITimeDataProviderConverter extends ITimeDataProvider {
+
+    /**
+     * Convert a time in time data provider units to a time in display units.
+     *
+     * @param time the time in time data provider units
+     *
+     * @return the time in display units
+     */
+    long convertTime(long time);
+}
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/widgets/timegraph/widgets/TimeDataProviderCyclesConverter.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/widgets/timegraph/widgets/TimeDataProviderCyclesConverter.java
new file mode 100644 (file)
index 0000000..aa4cd06
--- /dev/null
@@ -0,0 +1,178 @@
+/*******************************************************************************
+ * 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.widgets.timegraph.widgets;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat;
+
+/**
+ * Time Data Provider wrapper that converts nanoseconds to cycles.
+ *
+ * The user of the wrapper uses cycles, the wrapped provider uses nanoseconds.
+ * @since 3.1
+ *
+ */
+public class TimeDataProviderCyclesConverter implements ITimeDataProviderConverter {
+
+    private static final long GIGAHERTZ = 1000000000L;
+
+    private final @NonNull ITimeDataProvider fProvider;
+    private final long fFreq;
+
+    /**
+     * Constructor
+     *
+     * @param provider
+     *            the original time data provider
+     * @param clockFrequency
+     *            the clock frequency in Hz
+     */
+    public TimeDataProviderCyclesConverter(@NonNull ITimeDataProvider provider, long clockFrequency) {
+        fProvider = provider;
+        fFreq = clockFrequency;
+    }
+
+    /**
+     * Convert nanoseconds to cycles
+     *
+     * @param nanos
+     *            time in nanoseconds
+     * @return time in cycles
+     */
+    public long toCycles(long nanos) {
+        return Math.round(nanos * ((double) fFreq / GIGAHERTZ));
+    }
+
+    /**
+     * Convert cycles to nanoseconds
+     *
+     * @param cycles
+     *            time in cycles
+     * @return time in nanoseconds
+     */
+    public long toNanos(long cycles) {
+        return Math.round(cycles * ((double) GIGAHERTZ / fFreq));
+    }
+
+    @Override
+    public long convertTime(long time) {
+        return toCycles(time);
+    }
+
+    @Override
+    public void setSelectionRangeNotify(long beginTime, long endTime) {
+        fProvider.setSelectionRangeNotify(toNanos(beginTime), toNanos(endTime));
+    }
+
+    @Override
+    public void setSelectionRange(long beginTime, long endTime) {
+        fProvider.setSelectionRange(toNanos(beginTime), toNanos(endTime));
+    }
+
+    @Override
+    public long getSelectionBegin() {
+        return toCycles(fProvider.getSelectionBegin());
+    }
+
+    @Override
+    public long getSelectionEnd() {
+        return toCycles(fProvider.getSelectionEnd());
+    }
+
+    @Override
+    public long getBeginTime() {
+        return toCycles(fProvider.getBeginTime());
+    }
+
+    @Override
+    public long getEndTime() {
+        return toCycles(fProvider.getEndTime());
+    }
+
+    @Override
+    public long getMinTime() {
+        return toCycles(fProvider.getMinTime());
+    }
+
+    @Override
+    public long getMaxTime() {
+        return toCycles(fProvider.getMaxTime());
+    }
+
+    @Override
+    public long getTime0() {
+        return toCycles(fProvider.getTime0());
+    }
+
+    @Override
+    public long getTime1() {
+        return toCycles(fProvider.getTime1());
+    }
+
+    @Override
+    public long getMinTimeInterval() {
+        // do not convert: this is in integer units
+        return fProvider.getMinTimeInterval();
+    }
+
+    @Override
+    public void setStartFinishTimeNotify(long time0, long time1) {
+        fProvider.setStartFinishTimeNotify(toNanos(time0), toNanos(time1));
+    }
+
+    @Override
+    public void setStartFinishTime(long time0, long time1) {
+        fProvider.setStartFinishTime(toNanos(time0), toNanos(time1));
+    }
+
+    @Override
+    public void notifyStartFinishTime() {
+        fProvider.notifyStartFinishTime();
+    }
+
+    @Override
+    public void setSelectedTimeNotify(long time, boolean ensureVisible) {
+        fProvider.setSelectedTimeNotify(toNanos(time), ensureVisible);
+    }
+
+    @Override
+    public void setSelectedTime(long time, boolean ensureVisible) {
+        fProvider.setSelectedTime(toNanos(time), ensureVisible);
+    }
+
+    @Override
+    public void resetStartFinishTime() {
+        fProvider.resetStartFinishTime();
+    }
+
+    @Override
+    public int getNameSpace() {
+        return fProvider.getNameSpace();
+    }
+
+    @Override
+    public void setNameSpace(int width) {
+        fProvider.setNameSpace(width);
+    }
+
+    @Override
+    public int getTimeSpace() {
+        return fProvider.getTimeSpace();
+    }
+
+    @Override
+    public TimeFormat getTimeFormat() {
+        return fProvider.getTimeFormat();
+    }
+
+}
index d053ccc618ffa53c4d37ebe08f2114124a8f8d2d..8b433a8ec612417d0c95ad6820303eeacc1aae71 100644 (file)
@@ -35,9 +35,6 @@ import org.eclipse.jface.viewers.ISelection;
 import org.eclipse.jface.viewers.ISelectionChangedListener;
 import org.eclipse.jface.viewers.ISelectionProvider;
 import org.eclipse.jface.viewers.ViewerFilter;
-import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp;
-import org.eclipse.linuxtools.tmf.core.timestamp.TmfNanoTimestamp;
-import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestampDelta;
 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphColorListener;
 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphPresentationProvider;
 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphPresentationProvider2;
@@ -49,6 +46,9 @@ import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphTreeExpansionEve
 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ILinkEvent;
 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeEvent;
 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
+import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.Utils.Resolution;
+import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat;
+import org.eclipse.osgi.util.NLS;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.ControlEvent;
 import org.eclipse.swt.events.ControlListener;
@@ -2054,38 +2054,54 @@ public class TimeGraphControl extends TimeGraphBaseControl
     }
 
     private void updateStatusLine(int x) {
-        if (fStatusLineManager == null || null == fTimeProvider ||
-                fTimeProvider.getTime0() == fTimeProvider.getTime1()) {
+        // use the time provider of the time graph scale for the status line
+        ITimeDataProvider tdp = fTimeGraphScale.getTimeProvider();
+        if (fStatusLineManager == null || null == tdp ||
+                tdp.getTime0() == tdp.getTime1()) {
             return;
         }
+        TimeFormat tf = tdp.getTimeFormat();
+        Resolution res = Resolution.NANOSEC;
         StringBuilder message = new StringBuilder();
         if (x >= 0 && fDragState == DRAG_NONE) {
             long time = getTimeAtX(x);
             if (time >= 0) {
-                message.append("T: "); //$NON-NLS-1$
-                message.append(new TmfNanoTimestamp(time).toString());
-                message.append("     T1: "); //$NON-NLS-1$
-                long selectionBegin = fTimeProvider.getSelectionBegin();
-                long selectionEnd = fTimeProvider.getSelectionEnd();
-                message.append(new TmfNanoTimestamp(Math.min(selectionBegin, selectionEnd)).toString());
+                if (tdp instanceof ITimeDataProviderConverter) {
+                    time = ((ITimeDataProviderConverter) tdp).convertTime(time);
+                }
+                long selectionBegin = tdp.getSelectionBegin();
+                long selectionEnd = tdp.getSelectionEnd();
+                message.append(NLS.bind("T: {0}{1}     T1: {2}{3}", //$NON-NLS-1$
+                        new Object[] {
+                                tf == TimeFormat.CALENDAR ? Utils.formatDate(time) + ' ' : "", //$NON-NLS-1$
+                                Utils.formatTime(time, tf, res),
+                                tf == TimeFormat.CALENDAR ? Utils.formatDate(Math.min(selectionBegin, selectionEnd)) + ' ' : "", //$NON-NLS-1$
+                                Utils.formatTime(Math.min(selectionBegin, selectionEnd), tf, res)
+                        }));
                 if (selectionBegin != selectionEnd) {
-                    message.append("     T2: "); //$NON-NLS-1$
-                    message.append(new TmfNanoTimestamp(Math.max(selectionBegin, selectionEnd)).toString());
-                    message.append("     \u0394: "); //$NON-NLS-1$
-                    message.append(new TmfTimestampDelta(Math.abs(selectionBegin - selectionEnd), ITmfTimestamp.NANOSECOND_SCALE));
+                    message.append(NLS.bind("     T2: {0}{1}     \u0394: {2}", //$NON-NLS-1$
+                            new Object[] {
+                                    tf == TimeFormat.CALENDAR ? Utils.formatDate(Math.max(selectionBegin, selectionEnd)) + ' ' : "", //$NON-NLS-1$
+                                    Utils.formatTime(Math.max(selectionBegin, selectionEnd), tf, res),
+                                    Utils.formatDelta(Math.abs(selectionBegin - selectionEnd), tf, res)
+                            }));
                 }
             }
         } else if (fDragState == DRAG_SELECTION || fDragState == DRAG_ZOOM) {
             long time0 = fDragTime0;
             long time = getTimeAtX(fDragX);
-            message.append("T1: "); //$NON-NLS-1$
-            message.append(new TmfNanoTimestamp(Math.min(time, time0)).toString());
-            if (time != time0) {
-                message.append("     T2: "); //$NON-NLS-1$
-                message.append(new TmfNanoTimestamp(Math.max(time, time0)).toString());
-                message.append("     \u0394: "); //$NON-NLS-1$
-                message.append(new TmfTimestampDelta(Math.abs(time - time0), ITmfTimestamp.NANOSECOND_SCALE));
-            }
+            if (tdp instanceof ITimeDataProviderConverter) {
+                time0 = ((ITimeDataProviderConverter) tdp).convertTime(time0);
+                time = ((ITimeDataProviderConverter) tdp).convertTime(time);
+            }
+            message.append(NLS.bind("T1: {0}{1}     T2: {2}{3}     \u0394: {4}", //$NON-NLS-1$
+                    new Object[] {
+                            tf == TimeFormat.CALENDAR ? Utils.formatDate(Math.min(time, time0)) + ' ' : "", //$NON-NLS-1$
+                            Utils.formatTime(Math.min(time, time0), tf, res),
+                            tf == TimeFormat.CALENDAR ? Utils.formatDate(Math.max(time, time0)) + ' ' : "", //$NON-NLS-1$
+                            Utils.formatTime(Math.max(time, time0), tf, res),
+                            Utils.formatDelta(Math.abs(time - time0), tf, res)
+                    }));
         }
         fStatusLineManager.setMessage(message.toString());
     }
@@ -2251,6 +2267,7 @@ public class TimeGraphControl extends TimeGraphBaseControl
             setCapture(true);
             fDragX = Math.min(Math.max(e.x, fTimeProvider.getNameSpace()), getCtrlSize().x - RIGHT_MARGIN);
             fDragX0 = fDragX;
+            fDragTime0 = getTimeAtX(fDragX0);
             fDragState = DRAG_ZOOM;
             fDragButton = e.button;
             redraw();
index 1dda20588f8b8e8eef1de11dffc504fe2dfbb8fa..a67b748e98204069d099a0babbc1725d6e810272 100644 (file)
@@ -21,6 +21,7 @@ import java.util.Calendar;
 import java.util.Date;
 import java.util.TimeZone;
 
+import org.eclipse.linuxtools.internal.tmf.ui.Messages;
 import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
 import org.eclipse.linuxtools.tmf.core.signal.TmfSignalManager;
 import org.eclipse.linuxtools.tmf.core.signal.TmfTimestampFormatUpdateSignal;
@@ -79,6 +80,7 @@ public class TimeGraphScale extends TimeGraphBaseControl implements
     private static final TimeDraw TIMEDRAW_ABS_MONTH = new TimeDrawAbsMonth();
     private static final TimeDraw TIMEDRAW_ABS_YEAR = new TimeDrawAbsYear();
     private static final TimeDraw TIMEDRAW_NUMBER = new TimeDrawNumber();
+    private static final TimeDraw TIMEDRAW_CYCLES = new TimeDrawCycles();
 
     private static final int DRAG_EXTERNAL = -1;
     private static final int NO_BUTTON = 0;
@@ -125,6 +127,16 @@ public class TimeGraphScale extends TimeGraphBaseControl implements
         fTimeProvider = timeProvider;
     }
 
+    /**
+     * Get the time provider used by this scale
+     *
+     * @return The time provider
+     * @since 3.1
+     */
+    public ITimeDataProvider getTimeProvider() {
+        return fTimeProvider;
+    }
+
     @Override
     public Point computeSize(int wHint, int hHint, boolean changed) {
         return super.computeSize(wHint, fHeight, changed);
@@ -166,7 +178,7 @@ public class TimeGraphScale extends TimeGraphBaseControl implements
         long timeDelta;
         double minDelta = (pixelsPerNanoSec == 0) ? YEAR_IN_NS : width / pixelsPerNanoSec;
         long unit = 1;
-        if (fTimeProvider != null && fTimeProvider.getTimeFormat().equals(TimeFormat.CALENDAR)) {
+        if (fTimeProvider != null && fTimeProvider.getTimeFormat() == TimeFormat.CALENDAR) {
             if (minDelta > 6 * MONTH_IN_NS) {
                 unit = YEAR_IN_NS;
             } else if (minDelta > 3 * MONTH_IN_NS) {
@@ -213,8 +225,8 @@ public class TimeGraphScale extends TimeGraphBaseControl implements
     TimeDraw getTimeDraw(long timeDelta) {
         TimeDraw timeDraw;
         if (fTimeProvider != null) {
-
-            if (fTimeProvider.getTimeFormat() == TimeFormat.CALENDAR) {
+            switch (fTimeProvider.getTimeFormat()) {
+            case CALENDAR:
                 if (timeDelta >= YEAR_IN_NS) {
                     timeDraw = TIMEDRAW_ABS_YEAR;
                 } else if (timeDelta >= MONTH_IN_NS) {
@@ -235,9 +247,12 @@ public class TimeGraphScale extends TimeGraphBaseControl implements
                     timeDraw = TIMEDRAW_ABS_NANOSEC;
                 }
                 return timeDraw;
-            } else if (fTimeProvider.getTimeFormat() == TimeFormat.NUMBER) {
-                timeDraw = TIMEDRAW_NUMBER;
-                return timeDraw;
+            case NUMBER:
+                return TIMEDRAW_NUMBER;
+            case CYCLES:
+                return TIMEDRAW_CYCLES;
+            case RELATIVE:
+            default:
             }
 
         }
@@ -329,7 +344,7 @@ public class TimeGraphScale extends TimeGraphBaseControl implements
         rect0.width = labelWidth;
 
         long time;
-        if (fTimeProvider != null && fTimeProvider.getTimeFormat().equals(TimeFormat.CALENDAR)) {
+        if (fTimeProvider != null && fTimeProvider.getTimeFormat() == TimeFormat.CALENDAR) {
             time = floorToCalendar(time0, timeDelta);
         } else {
             time = (time0 / timeDelta) * timeDelta;
@@ -340,7 +355,7 @@ public class TimeGraphScale extends TimeGraphBaseControl implements
 
         int y = rect0.y + rect0.height;
 
-        if (fTimeProvider != null && fTimeProvider.getTimeFormat().equals(TimeFormat.CALENDAR)) {
+        if (fTimeProvider != null && fTimeProvider.getTimeFormat() == TimeFormat.CALENDAR) {
             timeDraw.drawAbsHeader(gc, time, absHeaderRect);
         }
 
@@ -359,7 +374,7 @@ public class TimeGraphScale extends TimeGraphBaseControl implements
             if (pixelsPerNanoSec == 0 || time > Long.MAX_VALUE - timeDelta || timeDelta == 0) {
                 break;
             }
-            if (fTimeProvider != null && fTimeProvider.getTimeFormat().equals(TimeFormat.CALENDAR)) {
+            if (fTimeProvider != null && fTimeProvider.getTimeFormat() == TimeFormat.CALENDAR) {
                 if (timeDelta >= YEAR_IN_NS) {
                     long millis = time / MILLISEC_IN_NS;
                     GREGORIAN_CALENDAR.setTime(new Date(millis));
@@ -452,7 +467,7 @@ public class TimeGraphScale extends TimeGraphBaseControl implements
         int numDigits = 5;
         long timeRange = time1 - time0;
 
-        if (fTimeProvider.getTimeFormat().equals(TimeFormat.CALENDAR)) {
+        if (fTimeProvider.getTimeFormat() == TimeFormat.CALENDAR) {
             // Calculate the number of digits to represent the minutes provided
             // 11:222
             // HH:mm:ss
@@ -470,6 +485,9 @@ public class TimeGraphScale extends TimeGraphBaseControl implements
             int thousandGroups = (numDigits - 1) / 3;
             numDigits += thousandGroups;
             numDigits += 12; // .000 000 000
+            if (fTimeProvider.getTimeFormat() == TimeFormat.CYCLES) {
+                numDigits += Messages.Utils_ClockCyclesUnit.length();
+            }
         }
 
         return numDigits;
@@ -619,7 +637,7 @@ abstract class TimeDraw {
         return s + n;
     }
 
-    public abstract void draw(GC gc, long time, Rectangle rect);
+    public abstract int draw(GC gc, long time, Rectangle rect);
 
     /**
      * Override to draw absolute time header. This is for the time information
@@ -638,68 +656,68 @@ abstract class TimeDraw {
 
 class TimeDrawSec extends TimeDraw {
     @Override
-    public void draw(GC gc, long nanosec, Rectangle rect) {
+    public int draw(GC gc, long nanosec, Rectangle rect) {
         long sec = nanosec / SEC_IN_NS;
-        Utils.drawText(gc, sep(sec), rect, true);
+        return Utils.drawText(gc, sep(sec), rect, true);
     }
 }
 
 class TimeDrawMillisec extends TimeDraw {
     @Override
-    public void draw(GC gc, long nanosec, Rectangle rect) {
+    public int draw(GC gc, long nanosec, Rectangle rect) {
         long millisec = nanosec / MILLISEC_IN_NS;
         long ms = millisec % PAD_1000;
         long sec = millisec / SEC_IN_MS;
-        Utils.drawText(gc, sep(sec) + "." + pad(ms), rect, true); //$NON-NLS-1$
+        return Utils.drawText(gc, sep(sec) + "." + pad(ms), rect, true); //$NON-NLS-1$
     }
 }
 
 class TimeDrawMicrosec extends TimeDraw {
     @Override
-    public void draw(GC gc, long nanosec, Rectangle rect) {
+    public int draw(GC gc, long nanosec, Rectangle rect) {
         long microsec = nanosec / MICROSEC_IN_NS;
         long us = microsec % PAD_1000;
         long millisec = microsec / MILLISEC_IN_US;
         long ms = millisec % PAD_1000;
         long sec = millisec / SEC_IN_MS;
-        Utils.drawText(gc, sep(sec) + "." + pad(ms) + " " + pad(us), rect, true); //$NON-NLS-1$ //$NON-NLS-2$
+        return Utils.drawText(gc, sep(sec) + "." + pad(ms) + " " + pad(us), rect, true); //$NON-NLS-1$ //$NON-NLS-2$
     }
 }
 
 class TimeDrawNanosec extends TimeDraw {
     @Override
-    public void draw(GC gc, long nanosec, Rectangle rect) {
+    public int draw(GC gc, long nanosec, Rectangle rect) {
         long ns = nanosec % PAD_1000;
         long microsec = nanosec / MICROSEC_IN_NS;
         long us = microsec % PAD_1000;
         long millisec = microsec / MILLISEC_IN_US;
         long ms = millisec % PAD_1000;
         long sec = millisec / SEC_IN_MS;
-        Utils.drawText(gc, sep(sec) + "." + pad(ms) + " " + pad(us) + " " + pad(ns), rect, true); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+        return Utils.drawText(gc, sep(sec) + "." + pad(ms) + " " + pad(us) + " " + pad(ns), rect, true); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
     }
 }
 
 class TimeDrawAbsYear extends TimeDraw {
     @Override
-    public void draw(GC gc, long nanosec, Rectangle rect) {
+    public int draw(GC gc, long nanosec, Rectangle rect) {
         String stime = YEAR_FORMAT.format(new Date(nanosec / MILLISEC_IN_NS));
-        Utils.drawText(gc, stime, rect, true);
+        return Utils.drawText(gc, stime, rect, true);
     }
 }
 
 class TimeDrawAbsMonth extends TimeDraw {
     @Override
-    public void draw(GC gc, long nanosec, Rectangle rect) {
+    public int draw(GC gc, long nanosec, Rectangle rect) {
         String stime = MONTH_FORMAT.format(new Date(nanosec / MILLISEC_IN_NS));
-        Utils.drawText(gc, stime, rect, true);
+        return Utils.drawText(gc, stime, rect, true);
     }
 }
 
 class TimeDrawAbsDay extends TimeDraw {
     @Override
-    public void draw(GC gc, long nanosec, Rectangle rect) {
+    public int draw(GC gc, long nanosec, Rectangle rect) {
         String stime = DAY_FORMAT.format(new Date(nanosec / MILLISEC_IN_NS));
-        Utils.drawText(gc, stime, rect, true);
+        return Utils.drawText(gc, stime, rect, true);
     }
 
     @Override
@@ -715,9 +733,9 @@ class TimeDrawAbsDay extends TimeDraw {
 
 class TimeDrawAbsHrs extends TimeDraw {
     @Override
-    public void draw(GC gc, long nanosec, Rectangle rect) {
+    public int draw(GC gc, long nanosec, Rectangle rect) {
         String stime = HOURS_FORMAT.format(new Date(nanosec / MILLISEC_IN_NS));
-        Utils.drawText(gc, stime, rect, true);
+        return Utils.drawText(gc, stime, rect, true);
     }
 
     @Override
@@ -733,9 +751,9 @@ class TimeDrawAbsHrs extends TimeDraw {
 
 class TimeDrawAbsMin extends TimeDraw {
     @Override
-    public void draw(GC gc, long nanosec, Rectangle rect) {
+    public int draw(GC gc, long nanosec, Rectangle rect) {
         String stime = MIN_FORMAT.format(new Date(nanosec / MILLISEC_IN_NS));
-        Utils.drawText(gc, stime, rect, true);
+        return Utils.drawText(gc, stime, rect, true);
     }
 
     @Override
@@ -751,9 +769,9 @@ class TimeDrawAbsMin extends TimeDraw {
 
 class TimeDrawAbsSec extends TimeDraw {
     @Override
-    public void draw(GC gc, long nanosec, Rectangle rect) {
+    public int draw(GC gc, long nanosec, Rectangle rect) {
         String stime = SEC_FORMAT.format(new Date(nanosec / MILLISEC_IN_NS));
-        Utils.drawText(gc, stime, rect, true);
+        return Utils.drawText(gc, stime, rect, true);
     }
 
     @Override
@@ -769,11 +787,10 @@ class TimeDrawAbsSec extends TimeDraw {
 
 class TimeDrawAbsMillisec extends TimeDraw {
     @Override
-    public void draw(GC gc, long nanosec, Rectangle rect) {
+    public int draw(GC gc, long nanosec, Rectangle rect) {
         String stime = SEC_FORMAT.format(new Date(nanosec / MILLISEC_IN_NS));
         String ns = Utils.formatNs(nanosec, Resolution.MILLISEC);
-
-        Utils.drawText(gc, stime + "." + ns, rect, true); //$NON-NLS-1$
+        return Utils.drawText(gc, stime + "." + ns, rect, true); //$NON-NLS-1$
     }
 
     @Override
@@ -789,10 +806,10 @@ class TimeDrawAbsMillisec extends TimeDraw {
 
 class TimeDrawAbsMicroSec extends TimeDraw {
     @Override
-    public void draw(GC gc, long nanosec, Rectangle rect) {
+    public int draw(GC gc, long nanosec, Rectangle rect) {
         String stime = SEC_FORMAT.format(new Date(nanosec / MILLISEC_IN_NS));
         String micr = Utils.formatNs(nanosec, Resolution.MICROSEC);
-        Utils.drawText(gc, stime + "." + micr, rect, true); //$NON-NLS-1$
+        return Utils.drawText(gc, stime + "." + micr, rect, true); //$NON-NLS-1$
     }
 
     @Override
@@ -808,10 +825,10 @@ class TimeDrawAbsMicroSec extends TimeDraw {
 
 class TimeDrawAbsNanoSec extends TimeDraw {
     @Override
-    public void draw(GC gc, long nanosec, Rectangle rect) {
+    public int draw(GC gc, long nanosec, Rectangle rect) {
         String stime = SEC_FORMAT.format(new Date(nanosec / MILLISEC_IN_NS));
         String ns = Utils.formatNs(nanosec, Resolution.NANOSEC);
-        Utils.drawText(gc, stime + "." + ns, rect, true); //$NON-NLS-1$
+        return Utils.drawText(gc, stime + "." + ns, rect, true); //$NON-NLS-1$
     }
 
     @Override
@@ -827,8 +844,16 @@ class TimeDrawAbsNanoSec extends TimeDraw {
 
 class TimeDrawNumber extends TimeDraw {
     @Override
-    public void draw(GC gc, long time, Rectangle rect) {
+    public int draw(GC gc, long time, Rectangle rect) {
         String stime = NumberFormat.getInstance().format(time);
-        Utils.drawText(gc, stime, rect, true);
+        return Utils.drawText(gc, stime, rect, true);
+    }
+}
+
+class TimeDrawCycles extends TimeDraw {
+    @Override
+    public int draw(GC gc, long time, Rectangle rect) {
+        String stime = Utils.formatTime(time, TimeFormat.CYCLES, Resolution.SECONDS);
+        return Utils.drawText(gc, stime, rect, true);
     }
 }
index 9bc79c36d2b72f17477956be15e695732e7a7ce2..672108f22efde54158e0d81e64a8ebc2cbf76ace 100644 (file)
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * Copyright (c) 2007, 2013 Intel Corporation, Ericsson
+ * Copyright (c) 2007, 2014 Intel Corporation, 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
@@ -53,7 +53,7 @@ public class TimeGraphTooltipHandler {
 
     private Shell fTipShell;
     private Composite fTipComposite;
-    private final ITimeDataProvider fTimeDataProvider;
+    private ITimeDataProvider fTimeDataProvider;
     private ITimeGraphPresentationProvider fTimeGraphProvider = null;
 
     /**
@@ -73,6 +73,18 @@ public class TimeGraphTooltipHandler {
         this.fTimeDataProvider = timeProv;
     }
 
+    /**
+     * Set the time data provider
+     *
+     * @param timeDataProvider
+     *            The time data provider
+     *
+     * @since 3.1
+     */
+    public void setTimeProvider(ITimeDataProvider timeDataProvider) {
+        fTimeDataProvider = timeDataProvider;
+    }
+
     private void createTooltipShell(Shell parent) {
         final Display display = parent.getDisplay();
         if (fTipShell != null && ! fTipShell.isDisposed()) {
@@ -209,33 +221,46 @@ public class TimeGraphTooltipHandler {
 
                         Resolution res = Resolution.NANOSEC;
                         TimeFormat tf = fTimeDataProvider.getTimeFormat();
+                        String startTime = "?"; //$NON-NLS-1$
+                        String duration = "?"; //$NON-NLS-1$
+                        String endTime = "?"; //$NON-NLS-1$
+                        if (fTimeDataProvider instanceof ITimeDataProviderConverter) {
+                            ITimeDataProviderConverter tdp = (ITimeDataProviderConverter) fTimeDataProvider;
+                            if (eventStartTime > -1) {
+                                eventStartTime = tdp.convertTime(eventStartTime);
+                                startTime = Utils.formatTime(eventStartTime, tf, res);
+                            }
+                            if (eventEndTime > -1) {
+                                eventEndTime = tdp.convertTime(eventEndTime);
+                                endTime = Utils.formatTime(eventEndTime, tf, res);
+                            }
+                            if (eventDuration > -1) {
+                                duration = Utils.formatDelta(eventEndTime - eventStartTime, tf, res);
+                            }
+                        } else {
+                            if (eventStartTime > -1) {
+                                startTime = Utils.formatTime(eventStartTime, tf, res);
+                            }
+                            if (eventEndTime > -1) {
+                                endTime = Utils.formatTime(eventEndTime, tf, res);
+                            }
+                            if (eventDuration > -1) {
+                                duration = Utils.formatDelta(eventDuration, tf, res);
+                            }
+                        }
                         if (tf == TimeFormat.CALENDAR) {
-                            addItem(Messages.TmfTimeTipHandler_TRACE_DATE, eventStartTime > -1 ?
-                                    Utils.formatDate(eventStartTime)
-                                    : "?"); //$NON-NLS-1$
+                            addItem(Messages.TmfTimeTipHandler_TRACE_DATE,
+                                    eventStartTime > -1 ? Utils.formatDate(eventStartTime) : "?"); //$NON-NLS-1$
                         }
                         if (eventDuration > 0) {
-                            addItem(Messages.TmfTimeTipHandler_TRACE_START_TIME, eventStartTime > -1 ?
-                                    Utils.formatTime(eventStartTime, tf, res)
-                                    : "?"); //$NON-NLS-1$
-
-                            addItem(Messages.TmfTimeTipHandler_TRACE_STOP_TIME, eventEndTime > -1 ?
-                                    Utils.formatTime(eventEndTime, tf, res)
-                                    : "?"); //$NON-NLS-1$
+                            addItem(Messages.TmfTimeTipHandler_TRACE_START_TIME, startTime);
+                            addItem(Messages.TmfTimeTipHandler_TRACE_STOP_TIME, endTime);
                         } else {
-                            addItem(Messages.TmfTimeTipHandler_TRACE_EVENT_TIME, eventStartTime > -1 ?
-                                    Utils.formatTime(eventStartTime, tf, res)
-                                    : "?"); //$NON-NLS-1$
+                            addItem(Messages.TmfTimeTipHandler_TRACE_EVENT_TIME, startTime);
                         }
 
                         if (eventDuration > 0) {
-                            // Duration in relative format in any case
-                            if (tf == TimeFormat.CALENDAR) {
-                                tf = TimeFormat.RELATIVE;
-                            }
-                            addItem(Messages.TmfTimeTipHandler_DURATION, eventDuration > -1 ?
-                                    Utils.formatTime(eventDuration, tf, res)
-                                    : "?"); //$NON-NLS-1$
+                            addItem(Messages.TmfTimeTipHandler_DURATION, duration);
                         }
                     }
                 }
@@ -257,7 +282,12 @@ public class TimeGraphTooltipHandler {
                     long sourceTime = linkEvent.getTime();
                     long duration = linkEvent.getDuration();
                     long targetTime = sourceTime + duration;
-
+                    if (fTimeDataProvider instanceof ITimeDataProviderConverter) {
+                        ITimeDataProviderConverter tdp = (ITimeDataProviderConverter) fTimeDataProvider;
+                        sourceTime = tdp.convertTime(sourceTime);
+                        targetTime = tdp.convertTime(targetTime);
+                        duration = targetTime - sourceTime;
+                    }
                     Resolution res = Resolution.NANOSEC;
                     TimeFormat tf = fTimeDataProvider.getTimeFormat();
                     if (tf == TimeFormat.CALENDAR) {
@@ -266,11 +296,7 @@ public class TimeGraphTooltipHandler {
                     if (duration > 0) {
                         addItem(Messages.TmfTimeTipHandler_LINK_SOURCE_TIME, Utils.formatTime(sourceTime, tf, res));
                         addItem(Messages.TmfTimeTipHandler_LINK_TARGET_TIME, Utils.formatTime(targetTime, tf, res));
-                        // Duration in relative format in any case
-                        if (tf == TimeFormat.CALENDAR) {
-                            tf = TimeFormat.RELATIVE;
-                        }
-                        addItem(Messages.TmfTimeTipHandler_DURATION, Utils.formatTime(duration, tf, res));
+                        addItem(Messages.TmfTimeTipHandler_DURATION, Utils.formatDelta(duration, tf, res));
                     } else {
                         addItem(Messages.TmfTimeTipHandler_LINK_TIME, Utils.formatTime(sourceTime, tf, res));
                     }
index 364c90cccb82f2a3da696931d6d5543d056a3061..f10a9061a87b81b1628f67a51573b45996270953 100644 (file)
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * Copyright (c) 2007, 2013 Intel Corporation, Ericsson
+ * Copyright (c) 2007, 2014 Intel Corporation, 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
@@ -20,7 +20,9 @@ import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.Iterator;
 import java.util.TimeZone;
+import java.util.concurrent.TimeUnit;
 
+import org.eclipse.linuxtools.internal.tmf.ui.Messages;
 import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimePreferences;
 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeEvent;
 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
@@ -59,6 +61,12 @@ public class Utils {
          * @since 2.0
          */
         NUMBER,
+
+        /**
+         * Timestamp displayed as cycles
+         * @since 3.1
+         */
+        CYCLES
     }
 
     /**
@@ -80,6 +88,9 @@ public class Utils {
 
     private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss"); //$NON-NLS-1$
     private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); //$NON-NLS-1$
+    private static final long HOURS_PER_DAY = 24;
+    private static final long MIN_PER_HOUR = 60;
+    private static final long SEC_PER_MIN = 60;
     private static final long SEC_IN_NS = 1000000000;
     private static final long MILLISEC_IN_NS = 1000000;
 
@@ -251,8 +262,8 @@ public class Utils {
      * @param rect
      *            The rectangle object which is being drawn
      * @param transp
-     *            Should we transpose the color
-     * @return The X coordinate where we have written
+     *            If true the background will be transparent
+     * @return The width of the written text
      */
     public static int drawText(GC gc, String text, Rectangle rect, boolean transp) {
         Point size = gc.stringExtent(text);
@@ -272,8 +283,8 @@ public class Utils {
      * @param y
      *            the Y coordinate of the starting point
      * @param transp
-     *            Should we transpose the color
-     * @return The X coordinate where we have written
+     *            If true the background will be transparent
+     * @return The width of the written text
      */
     public static int drawText(GC gc, String text, int x, int y, boolean transp) {
         Point size = gc.stringExtent(text);
@@ -334,11 +345,15 @@ public class Utils {
      * @return the formatted time
      */
     public static String formatTime(long time, TimeFormat format, Resolution resolution) {
-        // if format is absolute (Calendar)
-        if (format == TimeFormat.CALENDAR) {
+        switch (format) {
+        case CALENDAR:
             return formatTimeAbs(time, resolution);
-        } else if (format == TimeFormat.NUMBER) {
+        case NUMBER:
             return NumberFormat.getInstance().format(time);
+        case CYCLES:
+            return NumberFormat.getInstance().format(time) + Messages.Utils_ClockCyclesUnit;
+        case RELATIVE:
+        default:
         }
 
         StringBuffer str = new StringBuffer();
@@ -394,6 +409,66 @@ public class Utils {
         return str.toString();
     }
 
+    /**
+     * Formats time delta
+     *
+     * @param delta
+     *            The time delta, in ns
+     * @param format
+     *            The time format to use
+     * @param resolution
+     *            The resolution to use
+     * @since 3.1
+     * @return the formatted time delta
+     */
+    public static String formatDelta(long delta, TimeFormat format, Resolution resolution) {
+        if (format == TimeFormat.CALENDAR) {
+            return formatDeltaAbs(delta, resolution);
+        }
+        return formatTime(delta, format, resolution);
+    }
+
+    /**
+     * Formats time delta in ns to Calendar format, only formatting the years,
+     * days, hours or minutes if necessary.
+     *
+     * @param delta
+     *            The time delta, in ns
+     * @param resolution
+     *            The resolution to use
+     * @return the formatted time delta
+     * @since 3.1
+     */
+    public static String formatDeltaAbs(long delta, Resolution resolution) {
+        StringBuffer str = new StringBuffer();
+        if (delta < 0) {
+            str.append('-');
+        }
+        long ns = Math.abs(delta);
+        long seconds = TimeUnit.NANOSECONDS.toSeconds(ns);
+        long minutes = TimeUnit.NANOSECONDS.toMinutes(ns);
+        long hours = TimeUnit.NANOSECONDS.toHours(ns);
+        long days = TimeUnit.NANOSECONDS.toDays(ns);
+        if (days > 0) {
+            str.append(days);
+            str.append("d "); //$NON-NLS-1$
+        }
+        if (hours > 0) {
+            str.append(hours % HOURS_PER_DAY);
+            str.append("h "); //$NON-NLS-1$
+        }
+        if (minutes > 0) {
+            str.append(minutes % MIN_PER_HOUR);
+            str.append("m "); //$NON-NLS-1$
+        }
+        str.append(seconds % SEC_PER_MIN);
+        str.append('.');
+        // append the ms, us and ns as specified in the resolution
+        str.append(formatNs(delta, resolution));
+        str.append("s"); //$NON-NLS-1$
+        return str.toString();
+    }
+
     /**
      * Obtains the remainder fraction on unit Seconds of the entered value in
      * nanoseconds. e.g. input: 1241207054171080214 ns The number of fraction
This page took 0.042654 seconds and 5 git commands to generate.