This patch adds some formatter used in the chart.
All of them comes from *.lami.* packages, but with
some modifications to work with our interfaces.
Change-Id: I57ac9edffdd39792e787ead5c15838b3888c920d
Signed-off-by: Gabriel-Andrew Pollo-Guilbert <gabrielpolloguilbert@gmail.com>
Reviewed-on: https://git.eclipse.org/r/77157
Reviewed-by: Hudson CI
Reviewed-by: Genevieve Bastien <gbastien+lttng@versatic.net>
Tested-by: Genevieve Bastien <gbastien+lttng@versatic.net>
Require-Bundle: org.eclipse.ui,
org.eclipse.core.runtime,
org.eclipse.jface,
- org.eclipse.tracecompass.common.core
-Export-Package: org.eclipse.tracecompass.internal.tmf.chart.ui;x-internal:=true
+ org.eclipse.tracecompass.common.core,
+ org.eclipse.tracecompass.tmf.core
+Export-Package: org.eclipse.tracecompass.internal.tmf.chart.ui;x-internal:=true,
+ org.eclipse.tracecompass.internal.tmf.chart.ui.data;x-internal:=true,
+ org.eclipse.tracecompass.internal.tmf.chart.ui.format;x-internal:=true
+Import-Package: com.google.common.collect
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2016 EfficiOS Inc., Jonathan Rajotte-Julien
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.chart.ui.data;
+
+import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
+
+import java.math.BigDecimal;
+
+/**
+ * BigDecimal based range representation
+ *
+ * @author Jonathan Rajotte-Julien
+ */
+public class ChartRange {
+
+ // ------------------------------------------------------------------------
+ // Members
+ // ------------------------------------------------------------------------
+
+ private BigDecimal fMinimum;
+ private BigDecimal fMaximum;
+ private BigDecimal fRange;
+
+ // ------------------------------------------------------------------------
+ // Constructors
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ */
+ public ChartRange() {
+ fMinimum = checkNotNull(BigDecimal.ZERO);
+ fMaximum = checkNotNull(BigDecimal.ONE);
+ fRange = checkNotNull(getMaximum().subtract(getMinimum()));
+ }
+
+ /**
+ * Constructor with minimum and maximum values supplied.
+ *
+ * @param minimum
+ * The minimum value of the range
+ * @param maximum
+ * The maximum value of the range
+ */
+ public ChartRange(BigDecimal minimum, BigDecimal maximum) {
+ fMinimum = minimum;
+ fMaximum = maximum;
+ fRange = checkNotNull(maximum.subtract(minimum));
+ }
+
+ // ------------------------------------------------------------------------
+ // Accessors
+ // ------------------------------------------------------------------------
+
+ /**
+ * Accessor that returns the lower bound of the range.
+ *
+ * @return The minimum value of the range
+ */
+ public BigDecimal getMinimum() {
+ return fMinimum;
+ }
+
+ /**
+ * Accessor that returns the upper bound of the range.
+ *
+ * @return The maximum value of the range
+ */
+ public BigDecimal getMaximum() {
+ return fMaximum;
+ }
+
+ /**
+ * Accessor that returns the difference between the lower and the upper
+ * bounds of the range.
+ *
+ * @return The range delta
+ */
+ public BigDecimal getDelta() {
+ return fRange;
+ }
+
+ /**
+ * Method that checks if the delta is equal to zero.
+ *
+ * @return {@code true} if the delta is null, else {@code false}
+ */
+ public boolean isDeltaNull() {
+ return getDelta().compareTo(BigDecimal.ZERO) == 0;
+ }
+
+ // ------------------------------------------------------------------------
+ // Mutators
+ // ------------------------------------------------------------------------
+
+ /**
+ * Mutator that sets the minimum value of the range.
+ *
+ * @param minimum
+ * The new minimum value
+ */
+ public void setMinimum(BigDecimal minimum) {
+ fMinimum = minimum;
+ fRange = checkNotNull(getMaximum().subtract(getMinimum()));
+ }
+
+ /**
+ * Mutator that sets the maximum value of the range.
+ *
+ * @param maximum
+ * The new maximum value
+ */
+ public void setMaximum(BigDecimal maximum) {
+ fMaximum = maximum;
+ fRange = checkNotNull(getMaximum().subtract(getMinimum()));
+ }
+
+ // ------------------------------------------------------------------------
+ // Operations
+ // ------------------------------------------------------------------------
+
+ /**
+ * This method clamps the positive minimum value of this range down to zero.
+ * It returns the current object back with the minimum value modified.
+ *
+ * @return The current range map
+ */
+ public ChartRange clamp() {
+ fMinimum = fMinimum.min(BigDecimal.ZERO);
+
+ return this;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2016 École Polytechnique de Montréal
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.chart.ui.data;
+
+import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
+
+import java.math.BigDecimal;
+
+/**
+ * Simple class that maps two {@link ChartRange} together. The first one is the
+ * plotted range: it represents the range of the chart in which the data will be
+ * plotted. The second one is the input data range: it represents the range of
+ * the incoming data that will be plotted.
+ * <p>
+ * This map is used for mapping values that might be too big for a chart. Values
+ * that are in the external range are mapped to fit the internal range.
+ *
+ * @author Gabriel-Andrew Pollo-Guilbert
+ */
+public class ChartRangeMap {
+
+ // ------------------------------------------------------------------------
+ // Constants
+ // ------------------------------------------------------------------------
+
+ private static final int BIG_DECIMAL_DIVISION_SCALE = 22;
+
+ // ------------------------------------------------------------------------
+ // Members
+ // ------------------------------------------------------------------------
+
+ private ChartRange fPlottedRange;
+ private ChartRange fInputDataRange;
+
+ // ------------------------------------------------------------------------
+ // Constructors
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ */
+ public ChartRangeMap() {
+ fPlottedRange = new ChartRange();
+ fInputDataRange = new ChartRange();
+ }
+
+ /**
+ * Surcharged constructor with the input data range.
+ *
+ * @param input
+ * The range of the input data
+ */
+ public ChartRangeMap(ChartRange input) {
+ fPlottedRange = new ChartRange();
+ fInputDataRange = input;
+ }
+
+ /**
+ * Surcharged constructor with the plotted and input data ranges.
+ *
+ * @param plotted
+ * The plotted range
+ * @param input
+ * The range of the input data
+ */
+ public ChartRangeMap(ChartRange plotted, ChartRange input) {
+ fPlottedRange = plotted;
+ fInputDataRange = input;
+ }
+
+ // ------------------------------------------------------------------------
+ // Accessors
+ // ------------------------------------------------------------------------
+
+ /**
+ * Accessor that returns the plotted range of the map.
+ *
+ * @return The plotted range
+ */
+ public ChartRange getPlottedRange() {
+ return fPlottedRange;
+ }
+
+ /**
+ * Accessor that returns the input data range of the map.
+ *
+ * @return The input data range
+ */
+ public ChartRange getInputDataRange() {
+ return fInputDataRange;
+ }
+
+ // ------------------------------------------------------------------------
+ // Mutators
+ // ------------------------------------------------------------------------
+
+ /**
+ * Mutator that sets the plotted range of the map.
+ *
+ * @param plotted
+ * The new plotted range
+ */
+ public void setPlottedRange(ChartRange plotted) {
+ fPlottedRange = plotted;
+ }
+
+ /**
+ * Mutator that sets the input data range of the map.
+ *
+ * @param input
+ * The new input data range
+ */
+ public void setInputDataRange(ChartRange input) {
+ fInputDataRange = input;
+ }
+
+ // ------------------------------------------------------------------------
+ // Operations
+ // ------------------------------------------------------------------------
+
+ /**
+ * This method transforms a number from the input data range into a number
+ * that fits in the plotted range.
+ * <p>
+ * Incoming numbers from the data might be bigger than the numbers that the
+ * chart library supports (e.g. SWT supports Double and we can pass Long).
+ * While processing the numbers, a loss of precision might occur. In order
+ * to minimize this, we transform the raw values to an internal
+ * representation based on a linear transformation.
+ * <p>
+ * Let <i>e_val</i>, <i>e_min</i>, <i>e_Δ</i> be the external value,
+ * external minimum and external delta respectively and <i>i_min</i>,
+ * <i>i_Δ</i> be the internal minimum and the internal delta. The internal
+ * value <i>i_val</i> is given by the formula:
+ * <p>
+ * i_val=(e_val-e_min)*(i_Δ/e_Δ)+i_min
+ *
+ * @param number
+ * A number to transform
+ * @return The transformed value
+ */
+ public Number getInternalValue(Number number) {
+ BigDecimal value = new BigDecimal(number.toString());
+ ChartRange internal = getPlottedRange();
+ ChartRange external = getInputDataRange();
+
+ /* Apply the formula */
+ BigDecimal internalValue = value
+ .subtract(external.getMinimum())
+ .multiply(internal.getDelta())
+ .divide(external.getDelta(), BIG_DECIMAL_DIVISION_SCALE, BigDecimal.ROUND_DOWN)
+ .add(internal.getMinimum());
+
+ return checkNotNull(internalValue);
+ }
+
+ /**
+ * Util method that transforms an plotted value back into its original
+ * range.
+ * <p>
+ * It is very similar to {@link #getInternalValue(Number)}, except that is
+ * apply the formula in reverse in order to obtain the original value while
+ * minimizing lost in precision.
+ *
+ * @param number
+ * A number to transform
+ * @return A BigDecimal representation of the external value
+ */
+ public BigDecimal getExternalValue(Number number) {
+ ChartRange internal = getPlottedRange();
+ ChartRange external = getInputDataRange();
+
+ /* Apply the formula in reverse */
+ BigDecimal externalValue = (new BigDecimal(number.toString()))
+ .subtract(internal.getMinimum())
+ .multiply(external.getDelta())
+ .divide(internal.getDelta(), BIG_DECIMAL_DIVISION_SCALE, BigDecimal.ROUND_DOWN)
+ .add(external.getMinimum());
+
+ return checkNotNull(externalValue);
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2016 EfficiOS Inc., Jonathan Rajotte-Julien
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.chart.ui.format;
+
+import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
+
+import java.text.FieldPosition;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.common.core.format.DecimalUnitFormat;
+import org.eclipse.tracecompass.internal.tmf.chart.ui.data.ChartRange;
+import org.eclipse.tracecompass.internal.tmf.chart.ui.data.ChartRangeMap;
+
+/**
+ * Decimal formatter for graph
+ *
+ * Since the graph use normalized internal value the initial (external)
+ * representation needs to be obtained. Subsequent formatting is done based on a
+ * Double. Loss of precision could occurs based on the size. For now, loss of
+ * precision for decimal values is not a big concern. If it ever become one the
+ * use of Long while formatting might come in handy.
+ *
+ * @author Jonathan Rajotte-Julien
+ * @author Gabriel-Andrew Pollo-Guilbert
+ */
+public class ChartDecimalUnitFormat extends DecimalUnitFormat {
+
+ // ------------------------------------------------------------------------
+ // Constants
+ // ------------------------------------------------------------------------
+
+ private static final long serialVersionUID = -4288059349658845257L;
+
+ // ------------------------------------------------------------------------
+ // Members
+ // ------------------------------------------------------------------------
+
+ private @Nullable ChartRangeMap fRangeMap;
+
+ // ------------------------------------------------------------------------
+ // Constructors
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructor with a range map supplied.
+ *
+ * @param map
+ * A chart range map for mapping values
+ */
+ public ChartDecimalUnitFormat(@Nullable ChartRangeMap map) {
+ super();
+ fRangeMap = map;
+ }
+
+ /**
+ * Constructor with a multiplication factor and range map.
+ *
+ * @param factor
+ * A multiplication factor to apply to the value
+ * @param map
+ * A chart range map for mapping values
+ */
+ public ChartDecimalUnitFormat(double factor, @Nullable ChartRangeMap map) {
+ super(factor);
+ fRangeMap = map;
+ }
+
+ // ------------------------------------------------------------------------
+ // Mutators
+ // ------------------------------------------------------------------------
+
+ /**
+ * Mutators that sets the chart range map of this formatter.
+ *
+ * @param map
+ * The new chart range map
+ */
+ public void setRangeMap(ChartRangeMap map) {
+ fRangeMap = map;
+ }
+
+ // ------------------------------------------------------------------------
+ // Operations
+ // ------------------------------------------------------------------------
+
+ @Override
+ public StringBuffer format(@Nullable Object obj, @Nullable StringBuffer toAppendTo, @Nullable FieldPosition pos) {
+ if (!(obj instanceof Number) || toAppendTo == null) {
+ throw new IllegalArgumentException("Cannot format given Object as a Number: " + obj); //$NON-NLS-1$
+ }
+
+ Number number = (Number) obj;
+
+ /* If no map was provided, format with the number unchanged */
+ ChartRangeMap rangeMap = fRangeMap;
+ if (rangeMap == null) {
+ StringBuffer buffer = super.format(number, toAppendTo, pos);
+ return (buffer == null ? new StringBuffer() : buffer);
+ }
+
+ ChartRange internalRange = rangeMap.getPlottedRange();
+ ChartRange externalRange = rangeMap.getInputDataRange();
+
+ /* If any range's delta is null, format with the external bounds */
+ if (internalRange.isDeltaNull() || externalRange.isDeltaNull()) {
+ StringBuffer buffer = super.format(externalRange.getMinimum().doubleValue(), toAppendTo, pos);
+ return (buffer == null ? new StringBuffer() : buffer);
+ }
+
+ /* Find external value before formatting */
+ Double externalValue = checkNotNull(fRangeMap).getExternalValue(number).doubleValue();
+ StringBuffer buffer = super.format(externalValue, toAppendTo, pos);
+ return (buffer == null ? new StringBuffer() : buffer);
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2015, 2016 EfficiOS Inc. and others
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.chart.ui.format;
+
+import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
+
+import java.math.BigDecimal;
+import java.text.FieldPosition;
+import java.text.Format;
+import java.text.ParsePosition;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.internal.tmf.chart.ui.data.ChartRange;
+import org.eclipse.tracecompass.internal.tmf.chart.ui.data.ChartRangeMap;
+import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestampFormat;
+
+/**
+ * Formatter for timestamps.
+ *
+ * @author Michael Jeanson
+ * @author Gabriel-Andrew Pollo-Guilbert
+ */
+public class ChartTimeStampFormat extends Format {
+
+ // ------------------------------------------------------------------------
+ // Constants
+ // ------------------------------------------------------------------------
+
+ private static final long serialVersionUID = 8102026791684954897L;
+
+ // ------------------------------------------------------------------------
+ // Members
+ // ------------------------------------------------------------------------
+
+ private final TmfTimestampFormat fFormat;
+ private @Nullable ChartRangeMap fRangeMap;
+
+ // ------------------------------------------------------------------------
+ // Constructors
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructor with a range map supplied.
+ *
+ * @param map
+ * A internal and external ranges map
+ */
+ public ChartTimeStampFormat(@Nullable ChartRangeMap map) {
+ fFormat = checkNotNull(TmfTimestampFormat.getDefaulTimeFormat());
+ fRangeMap = map;
+ }
+
+ /**
+ * Constructor with a pattern and a range map supplied.
+ *
+ * @param pattern
+ * The format pattern
+ * @param map
+ * A chart range map for mapping values
+ */
+ public ChartTimeStampFormat(String pattern, @Nullable ChartRangeMap map) {
+ fFormat = new TmfTimestampFormat(pattern);
+ fRangeMap = map;
+ }
+
+ // ------------------------------------------------------------------------
+ // Mutators
+ // ------------------------------------------------------------------------
+
+ /**
+ * Mutators that sets the chart range map of this formatter.
+ *
+ * @param map
+ * The new chart range map
+ */
+ public void setRangeMap(ChartRangeMap map) {
+ fRangeMap = map;
+ }
+
+ // ------------------------------------------------------------------------
+ // Operations
+ // ------------------------------------------------------------------------
+
+ @Override
+ public StringBuffer format(@Nullable Object obj, @Nullable StringBuffer toAppendTo, @Nullable FieldPosition pos) {
+ if (!(obj instanceof Number) || toAppendTo == null) {
+ throw new IllegalArgumentException("Cannot format given Object as a Number: " + obj); //$NON-NLS-1$
+ }
+
+ Number number = (Number) obj;
+
+ /* If no range was provided, format with the number unchanged */
+ ChartRangeMap rangeMap = fRangeMap;
+ if (rangeMap == null) {
+ long time = ((Number) obj).longValue();
+ return checkNotNull(toAppendTo.append(fFormat.format(time)));
+ }
+
+ ChartRange internalRange = rangeMap.getPlottedRange();
+ ChartRange externalRange = rangeMap.getInputDataRange();
+
+ /* If any range's delta is null, format with the external bounds */
+ if (internalRange.isDeltaNull() || externalRange.isDeltaNull()) {
+ return checkNotNull(toAppendTo.append(fFormat.format(externalRange.getMinimum().doubleValue())));
+ }
+
+ /* Find external value before formatting */
+ BigDecimal externalValue = checkNotNull(fRangeMap).getExternalValue(number);
+ return checkNotNull(toAppendTo.append(fFormat.format(externalValue.longValue())));
+ }
+
+ @Override
+ public @Nullable Object parseObject(@Nullable String source, @Nullable ParsePosition pos) {
+ return null;
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2016 École Polytechnique de Montréal
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.chart.ui.format;
+
+import java.text.FieldPosition;
+import java.text.Format;
+import java.text.ParsePosition;
+
+import org.eclipse.jdt.annotation.Nullable;
+
+import com.google.common.collect.BiMap;
+
+/**
+ * Format label based on a given Map<String, Integer>.
+ *
+ * @author Jonathan Rajotte-Julien
+ * @author Gabriel-Andrew Pollo-Guilbert
+ */
+public class LabelFormat extends Format {
+
+ // ------------------------------------------------------------------------
+ // Constants
+ // ------------------------------------------------------------------------
+
+ private static final long serialVersionUID = -7046922375212377647L;
+ private static final String CHART_EMPTY_LABEL = " "; //$NON-NLS-1$
+
+ // ------------------------------------------------------------------------
+ // Members
+ // ------------------------------------------------------------------------
+
+ private final BiMap<String, Integer> fMap;
+
+ // ------------------------------------------------------------------------
+ // Constructors
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @param map
+ * Map of labels and indices
+ */
+ public LabelFormat(BiMap<String, Integer> map) {
+ super();
+
+ fMap = map;
+ }
+
+ // ------------------------------------------------------------------------
+ // Operations
+ // ------------------------------------------------------------------------
+
+ @Override
+ public @Nullable StringBuffer format(@Nullable Object obj, @Nullable StringBuffer toAppendTo, @Nullable FieldPosition pos) {
+ if (obj == null || toAppendTo == null) {
+ return new StringBuffer(CHART_EMPTY_LABEL);
+ }
+
+ Double doubleObj = (Double) obj;
+
+ /* If the key is not contained in the map, format a empty label */
+ if ((doubleObj % 1 != 0) || !fMap.containsValue((doubleObj.intValue()))) {
+ return new StringBuffer(CHART_EMPTY_LABEL);
+ }
+
+ /* If the value is null in the map, format an unknown label */
+ String key = fMap.inverse().get(doubleObj.intValue());
+
+ return toAppendTo.append(key);
+ }
+
+ @Override
+ public @Nullable Object parseObject(@Nullable String source, @Nullable ParsePosition pos) {
+ return fMap.get(source);
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2016 École Polytechnique de Montréal
+ *
+ * All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+@org.eclipse.jdt.annotation.NonNullByDefault
+package org.eclipse.tracecompass.internal.tmf.chart.ui.format;