import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
+import java.math.BigDecimal;
+import java.text.Format;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.aspect.LamiTableEntryAspect;
import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiChartModel;
import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiChartModel.ChartType;
-import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiLabelFormat;
import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiResultTable;
import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiTableEntry;
+import org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.format.LamiLabelFormat;
+import org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.format.LamiTimeStampFormat;
import org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.signals.LamiSelectionUpdateSignal;
import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager;
import org.swtchart.IAxisTick;
private final Map<ISeries, List<Integer>> fIndexMapping;
+ /* Use a scale from 0 to 1 internally for both axes */
+ private LamiGraphRange fXInternalRange = new LamiGraphRange(checkNotNull(BigDecimal.ZERO), checkNotNull(BigDecimal.ONE));
+ private LamiGraphRange fYInternalRange = new LamiGraphRange(checkNotNull(BigDecimal.ZERO), checkNotNull(BigDecimal.ONE));
+
+ private @Nullable LamiGraphRange fXExternalRange = null;
+ private @Nullable LamiGraphRange fYExternalRange = null;
+
/* The current data point for the hovering cross */
private Point fHoveringCrossDataPoint;
*/
if (!areXAspectsContinuous) {
generateLabelMap(xAxisAspects, checkNotNull(xMap));
+ } else {
+ /*
+ * Always clamp the range to min and max
+ *
+ * TODO: in the future this could be based on the result of the
+ * delta between max and min multiplied by a ratio like it is done in
+ * LibreOffice Calc
+ */
+ fXExternalRange = getRange(xAxisAspects, false);
}
/*
*/
if (!areYAspectsContinuous) {
generateLabelMap(yAxisAspects, yMap);
+ } else {
+ /*
+ * Only clamp the range to the minimum value if it is a time stamp since
+ * plotting from 1970 would make little sense.
+ */
+ fYExternalRange = getRange(yAxisAspects, areYAspectsTimeStamp);
}
/* Plot the series */
int index = 0;
for (LamiTableEntryAspect yAspect : getYAxisAspects()) {
- String name = ""; //$NON-NLS-1$
+ String name;
LamiTableEntryAspect xAspect;
if (xAxisAspects.size() == 1) {
/* Always map to the same x series */
name = (yAspect.getName() + ' ' + Messages.LamiScatterViewer_by + ' ' + xAspect.getName());
}
- List<@Nullable Double> xDoubleSeries = new ArrayList<>();
- List<@Nullable Double> yDoubleSeries = new ArrayList<>();
+ List<@Nullable Double> xDoubleSeries;
+ List<@Nullable Double> yDoubleSeries;
if (xAspect.isContinuous()) {
- xDoubleSeries = getResultTable().getEntries().stream().map((entry -> xAspect.resolveDouble(entry))).collect(Collectors.toList());
+ xDoubleSeries = getResultTable().getEntries().stream()
+ .map(entry -> {
+ Number number = xAspect.resolveNumber(entry);
+ if (number != null && fXExternalRange != null) {
+ return getInternalDoubleValue(number, fXInternalRange, fXExternalRange);
+ }
+ return null;
+ })
+ .collect(Collectors.toList());
} else {
- xDoubleSeries = getResultTable().getEntries().stream().map(entry -> {
- String string = xAspect.resolveString(entry);
- Integer value = xMap.get(string);
- if (value != null) {
- return Double.valueOf(value.doubleValue());
- }
- return null;
-
- }).collect(Collectors.toList());
+ xDoubleSeries = getResultTable().getEntries().stream()
+ .map(entry -> {
+ String string = xAspect.resolveString(entry);
+ Integer value = xMap.get(string);
+ if (value != null) {
+ return Double.valueOf(value.doubleValue());
+ }
+ return null;
+ })
+ .collect(Collectors.toList());
}
if (yAspect.isContinuous()) {
- yDoubleSeries = getResultTable().getEntries().stream().map((entry -> yAspect.resolveDouble(entry))).collect(Collectors.toList());
+ yDoubleSeries = getResultTable().getEntries().stream()
+ .map(entry -> {
+ Number number = yAspect.resolveNumber(entry);
+ if (number != null && fYExternalRange != null) {
+ return getInternalDoubleValue(number, fYInternalRange, fYExternalRange);
+ }
+ return null;
+ })
+ .collect(Collectors.toList());
} else {
- yDoubleSeries = getResultTable().getEntries().stream().map(entry -> {
- String string = yAspect.resolveString(entry);
- Integer value = yMap.get(string);
- if (value != null) {
- return Double.valueOf(value.doubleValue());
- }
- return null;
-
- }).collect(Collectors.toList());
+ yDoubleSeries = getResultTable().getEntries().stream()
+ .map(entry -> {
+ String string = yAspect.resolveString(entry);
+ Integer value = yMap.get(string);
+ if (value != null) {
+ return Double.valueOf(value.doubleValue());
+ }
+ return null;
+ })
+ .collect(Collectors.toList());
}
List<@Nullable Double> validXDoubleSeries = new ArrayList<>();
/* Reject this tuple */
continue;
}
- if ((xIsLog && xValue <= ZERO) || (yIsLog && yValue <= ZERO)) {
+ if ((xIsLog && xValue <= ZERO_DOUBLE) || (yIsLog && yValue <= ZERO_DOUBLE)) {
/*
* Equal or less than 0 values can't be plotted on log scale
*/
/* Modify x axis related chart styling */
IAxisTick xTick = getChart().getAxisSet().getXAxis(0).getTick();
if (areXAspectsContinuous) {
- xTick.setFormat(getContinuousAxisFormatter(xAxisAspects, getResultTable().getEntries()));
+ Format xAxisFormat = getContinuousAxisFormatter(xAxisAspects, getResultTable().getEntries(), fXInternalRange, fXExternalRange);
+
+ xTick.setFormat(xAxisFormat);
+
+ if (xAxisFormat instanceof LamiTimeStampFormat) {
+ setXUnits(((LamiTimeStampFormat) xAxisFormat).getPattern());
+ }
} else {
xTick.setFormat(new LamiLabelFormat(checkNotNull(xMap)));
updateTickMark(checkNotNull(xMap), xTick, getChart().getPlotArea().getSize().x);
/* Modify Y axis related chart styling */
IAxisTick yTick = getChart().getAxisSet().getYAxis(0).getTick();
if (areYAspectsContinuous) {
- yTick.setFormat(getContinuousAxisFormatter(yAxisAspects, getResultTable().getEntries()));
+ Format yAxisFormat = getContinuousAxisFormatter(yAxisAspects, getResultTable().getEntries(), fYInternalRange, fYExternalRange);
+
+ yTick.setFormat(yAxisFormat);
+
+ if (yAxisFormat instanceof LamiTimeStampFormat) {
+ setYUnits(((LamiTimeStampFormat) yAxisFormat).getPattern());
+ }
} else {
yTick.setFormat(new LamiLabelFormat(checkNotNull(yMap)));
updateTickMark(checkNotNull(yMap), yTick, getChart().getPlotArea().getSize().y);
- /*
- * SWTChart workaround: SWTChart fiddles with tick mark visibility
- * based on the fact that it can parse the label to double or not.
- *
- * If the label happens to be a double, it checks for the presence
- * of that value in its own tick labels to decide if it should add
- * it or not. If it happens that the parsed value is already present
- * in its map, the tick gets a visibility of false.
- *
- * The X axis does not have this problem since SWTCHART checks on
- * label angle, and if it is != 0 simply does no logic regarding
- * visibility. So simply set a label angle of 1 to the axis.
- */
- yTick.setTickLabelAngle(1);
-
/* Remove horizontal grid line */
getChart().getAxisSet().getYAxis(0).getGrid().setStyle(LineStyle.NONE);
}
+ /*
+ * SWTChart workaround: SWTChart fiddles with tick mark visibility based
+ * on the fact that it can parse the label to double or not.
+ *
+ * If the label happens to be a double, it checks for the presence of
+ * that value in its own tick labels to decide if it should add it or
+ * not. If it happens that the parsed value is already present in its
+ * map, the tick gets a visibility of false.
+ *
+ * The X axis does not have this problem since SWTCHART checks on label
+ * angle, and if it is != 0 simply does no logic regarding visibility.
+ * So simply set a label angle of 1 to the axis.
+ */
+ yTick.setTickLabelAngle(1);
+
setLineSeriesColor();
/* Put log scale if necessary */
Color lightColor = lightColorsIt.next();
Color color = colorsIt.next();
Color[] colors = ((ILineSeries) series).getSymbolColors();
+ if (colors == null) {
+ /* Should never happen */
+ continue;
+ }
if (currentSelections.isEmpty()) {
/* Put all symbols to the normal colors */