From a805f10b443e89ff2f23792dcf2cf93759d9e6a9 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Genevi=C3=A8ve=20Bastien?= Date: Thu, 2 Feb 2017 15:09:31 -0500 Subject: [PATCH] lami.ui: Remove previous lami charts MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Only the custom charts are now used for lami Change-Id: I6d5cda15916b32dc89e116965da63445fb2ceaa3 Signed-off-by: Geneviève Bastien Reviewed-on: https://git.eclipse.org/r/90217 Reviewed-by: Hudson CI --- .../META-INF/MANIFEST.MF | 2 - .../lami/ui/format/LamiDecimalUnitFormat.java | 129 --- .../lami/ui/format/LamiLabelFormat.java | 83 -- .../lami/ui/format/LamiTimeStampFormat.java | 115 --- .../analysis/lami/ui/format/package-info.java | 11 - .../ui/signals/LamiSelectionUpdateSignal.java | 77 -- .../lami/ui/signals/package-info.java | 11 - .../analysis/lami/ui/viewers/ILamiViewer.java | 24 - .../lami/ui/viewers/LamiBarChartViewer.java | 498 ---------- .../lami/ui/viewers/LamiScatterViewer.java | 711 -------------- .../lami/ui/viewers/LamiTableViewer.java | 72 +- .../lami/ui/viewers/LamiXYChartViewer.java | 925 ------------------ .../analysis/lami/ui/viewers/Messages.java | 38 - .../lami/ui/viewers/messages.properties | 13 - .../lami/ui/views/LamiReportView.java | 26 - .../lami/ui/views/LamiReportViewTabPage.java | 350 +------ .../lami/ui/views/LamiSeriesDialog.java | 510 ---------- .../lami/ui/views/LamiViewerControl.java | 36 +- .../analysis/lami/ui/views/Messages.java | 19 - .../lami/ui/views/messages.properties | 19 - 20 files changed, 41 insertions(+), 3628 deletions(-) delete mode 100644 analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/format/LamiDecimalUnitFormat.java delete mode 100644 analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/format/LamiLabelFormat.java delete mode 100644 analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/format/LamiTimeStampFormat.java delete mode 100644 analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/format/package-info.java delete mode 100644 analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/signals/LamiSelectionUpdateSignal.java delete mode 100644 analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/signals/package-info.java delete mode 100644 analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/viewers/LamiBarChartViewer.java delete mode 100644 analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/viewers/LamiScatterViewer.java delete mode 100644 analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/viewers/LamiXYChartViewer.java delete mode 100644 analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/viewers/Messages.java delete mode 100644 analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/viewers/messages.properties delete mode 100644 analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/views/LamiSeriesDialog.java diff --git a/analysis/org.eclipse.tracecompass.analysis.lami.ui/META-INF/MANIFEST.MF b/analysis/org.eclipse.tracecompass.analysis.lami.ui/META-INF/MANIFEST.MF index 472ebddd25..0fadd8c52c 100644 --- a/analysis/org.eclipse.tracecompass.analysis.lami.ui/META-INF/MANIFEST.MF +++ b/analysis/org.eclipse.tracecompass.analysis.lami.ui/META-INF/MANIFEST.MF @@ -19,9 +19,7 @@ Require-Bundle: org.eclipse.ui, org.eclipse.tracecompass.tmf.chart.core, org.eclipse.tracecompass.tmf.chart.ui Export-Package: org.eclipse.tracecompass.internal.analysis.lami.ui;x-internal:=true, - org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.format;x-internal:=true, org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.handler;x-internal:=true, - org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.signals;x-internal:=true, org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.viewers;x-internal:=true, org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.views;x-internal:=true Import-Package: com.google.common.collect, diff --git a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/format/LamiDecimalUnitFormat.java b/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/format/LamiDecimalUnitFormat.java deleted file mode 100644 index 552edd595e..0000000000 --- a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/format/LamiDecimalUnitFormat.java +++ /dev/null @@ -1,129 +0,0 @@ -/******************************************************************************* - * 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.provisional.analysis.lami.ui.format; - -import java.math.BigDecimal; -import java.text.FieldPosition; - -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.tracecompass.common.core.format.DecimalUnitFormat; -import org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.viewers.LamiGraphRange; - -/** - * Decimal formatter for Lami 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 - */ -public class LamiDecimalUnitFormat extends DecimalUnitFormat { - - /** Maximum amount of digits that can be represented into a double */ - private static final int BIG_DECIMAL_DIVISION_SCALE = 22; - - private static final long serialVersionUID = 977671266270661188L; - - private final @Nullable LamiGraphRange fInternalRange; - private final @Nullable LamiGraphRange fExternalRange; - - /** - * Default constructor - */ - public LamiDecimalUnitFormat() { - super(); - fInternalRange = null; - fExternalRange = null; - } - - /** - * Constructor with internal and external LamiRange for scale transformation - * - * @param internalRange - * The internal range used for graph representation - * - * @param externalRange - * The external (real value) range shown to the user - */ - public LamiDecimalUnitFormat(@Nullable LamiGraphRange internalRange, @Nullable LamiGraphRange externalRange) { - super(); - fInternalRange = internalRange; - fExternalRange = externalRange; - } - - /** - * Constructor with multiplication factor and internal and external - * LamiRange for scale transformation. - * - * @param factor - * Multiplication factor to apply to the value - * @param internalRange - * The internal range used for graph representation - * @param externalRange - * The external (real value) range shown to the user - */ - public LamiDecimalUnitFormat(double factor, @Nullable LamiGraphRange internalRange, @Nullable LamiGraphRange externalRange) { - super(factor); - fInternalRange = internalRange; - fExternalRange = externalRange; - } - - /** - * @return the internal range definition - */ - public @Nullable LamiGraphRange getInternalRange() { - return fInternalRange; - } - - /** - * @return the external range definition - */ - public @Nullable LamiGraphRange getExternalRange() { - return fExternalRange; - } - - @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$ - } - - @Nullable LamiGraphRange internalRange = fInternalRange; - @Nullable LamiGraphRange externalRange = fExternalRange; - if (internalRange == null || externalRange == null) { - StringBuffer buffer = super.format(obj, toAppendTo, pos); - return (buffer == null ? new StringBuffer() : buffer); - } - - if (internalRange.getDelta().compareTo(BigDecimal.ZERO) == 0) { - StringBuffer buffer = super.format(externalRange.getMinimum().doubleValue(), toAppendTo, pos); - return (buffer == null ? new StringBuffer() : buffer); - } - - if (externalRange.getDelta().compareTo(BigDecimal.ZERO) == 0) { - StringBuffer buffer = super.format(externalRange.getMinimum().doubleValue(), toAppendTo, pos); - return (buffer == null ? new StringBuffer() : buffer); - } - - /* Find external value before formatting */ - BigDecimal externalValue = (new BigDecimal(obj.toString())) - .subtract(internalRange.getMinimum()) - .multiply(externalRange.getDelta()) - .divide(internalRange.getDelta(), BIG_DECIMAL_DIVISION_SCALE, BigDecimal.ROUND_DOWN) - .add(externalRange.getMinimum()); - - Double value = externalValue.doubleValue(); - StringBuffer buffer = super.format(value, toAppendTo, pos); - return (buffer == null ? new StringBuffer() : buffer); - } -} diff --git a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/format/LamiLabelFormat.java b/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/format/LamiLabelFormat.java deleted file mode 100644 index 95747899c4..0000000000 --- a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/format/LamiLabelFormat.java +++ /dev/null @@ -1,83 +0,0 @@ -/******************************************************************************* - * 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.provisional.analysis.lami.ui.format; - -import java.text.FieldPosition; -import java.text.Format; -import java.text.ParsePosition; -import java.util.Map.Entry; - - -import org.eclipse.jdt.annotation.Nullable; - -import com.google.common.collect.BiMap; - -/** - * Format label based on a given Map - * - * @author Jonathan Rajotte-Julien - */ -public class LamiLabelFormat extends Format { - - private static final long serialVersionUID = 4939553034329681316L; - - private static final String SWTCHART_EMPTY_LABEL = " "; //$NON-NLS-1$ - private static final String UNKNOWN_REPRESENTATION = "?"; //$NON-NLS-1$ - private final BiMap<@Nullable String, Integer> fMap; - - /** - * Constructor - * - * @param map - * Map of indices to labels - */ - public LamiLabelFormat(BiMap<@Nullable String, Integer> map) { - super(); - fMap = map; - } - - @Override - public @Nullable StringBuffer format(@Nullable Object obj, @Nullable StringBuffer toAppendTo, @Nullable FieldPosition pos) { - if (obj == null || toAppendTo == null) { - return new StringBuffer(SWTCHART_EMPTY_LABEL); - } - - Double doubleObj = (Double) obj; - - /* - * Return a string buffer with a space in it since SWT does not like to - * draw empty strings. - */ - if ((doubleObj % 1 != 0) || !fMap.containsValue((doubleObj.intValue()))) { - return new StringBuffer(SWTCHART_EMPTY_LABEL); - } - - for (Entry<@Nullable String, Integer> entry : fMap.entrySet()) { - /* - * FIXME: Find if the elements are the same, based on their double - * value, because SWTChart uses double values so we do the same - * check. The loss of precision could lead to false positives. - */ - if (Double.compare(entry.getValue().doubleValue(), doubleObj.doubleValue()) == 0) { - if (entry.getKey() == null) { - return new StringBuffer(UNKNOWN_REPRESENTATION); - } - return toAppendTo.append(entry.getKey()); - } - } - return new StringBuffer(SWTCHART_EMPTY_LABEL); - } - - @Override - public @Nullable Object parseObject(@Nullable String source, @Nullable ParsePosition pos) { - return fMap.get(source); - } - -} diff --git a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/format/LamiTimeStampFormat.java b/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/format/LamiTimeStampFormat.java deleted file mode 100644 index 731a99c428..0000000000 --- a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/format/LamiTimeStampFormat.java +++ /dev/null @@ -1,115 +0,0 @@ -/******************************************************************************* - * 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.provisional.analysis.lami.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.provisional.analysis.lami.ui.viewers.LamiGraphRange; -import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestampFormat; - -/** - * Formatter for time stamps - */ -public class LamiTimeStampFormat extends Format { - - private static final int BIG_DECIMAL_DIVISION_SCALE = 22; - - private static final long serialVersionUID = 4285447886537779762L; - - private final TmfTimestampFormat fFormat; - - private final @Nullable LamiGraphRange fInternalRange; - private final @Nullable LamiGraphRange fExternalRange; - - // ------------------------------------------------------------------------ - // Constructors - // ------------------------------------------------------------------------ - - /** - * The normal constructor - * - * @param pattern - * the format pattern - * @param internalRange - * The internal range used for graph representation - * @param externalRange - * The external (real value) range shown to the user - */ - public LamiTimeStampFormat(String pattern, @Nullable LamiGraphRange internalRange, @Nullable LamiGraphRange externalRange) { - fFormat = new TmfTimestampFormat(pattern); - fInternalRange = internalRange; - fExternalRange = externalRange; - } - - // ------------------------------------------------------------------------ - // Operations - // ------------------------------------------------------------------------ - - /** - * @return the internal range definition - */ - public @Nullable LamiGraphRange getInternalRange() { - return fInternalRange; - } - - /** - * @return the external range definition - */ - public @Nullable LamiGraphRange getExternalRange() { - return fExternalRange; - } - - @Override - public StringBuffer format(@Nullable Object obj, @Nullable StringBuffer toAppendTo, @Nullable FieldPosition pos) { - if (obj != null && obj instanceof Number && toAppendTo != null) { - @Nullable LamiGraphRange internalRange = fInternalRange; - @Nullable LamiGraphRange externalRange = fExternalRange; - if (internalRange == null || externalRange == null) { - long time = ((Number)obj).longValue(); - return checkNotNull(toAppendTo.append(fFormat.format(time))); - } - - if (internalRange.getDelta().compareTo(BigDecimal.ZERO) == 0 || - externalRange.getDelta().compareTo(BigDecimal.ZERO) == 0) { - return checkNotNull(toAppendTo.append(fFormat.format(externalRange.getMinimum().doubleValue()))); - } - - /* Find external value before formatting */ - BigDecimal externalValue = (new BigDecimal(obj.toString())) - .subtract(internalRange.getMinimum()) - .multiply(externalRange.getDelta()) - .divide(internalRange.getDelta(), BIG_DECIMAL_DIVISION_SCALE, BigDecimal.ROUND_DOWN) - .add(externalRange.getMinimum()); - - return checkNotNull(toAppendTo.append(fFormat.format(externalValue.longValue()))); - } - return new StringBuffer(); - } - - @Override - public @Nullable Object parseObject(@Nullable String source, @Nullable ParsePosition pos) { - return null; - } - - /** - * Get the pattern string of the format. - * - * @return the pattern string. - */ - public String getPattern() { - return fFormat.toPattern(); - } -} diff --git a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/format/package-info.java b/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/format/package-info.java deleted file mode 100644 index c91e0f030a..0000000000 --- a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/format/package-info.java +++ /dev/null @@ -1,11 +0,0 @@ -/******************************************************************************* - * 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 - *******************************************************************************/ - -@org.eclipse.jdt.annotation.NonNullByDefault -package org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.format; \ No newline at end of file diff --git a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/signals/LamiSelectionUpdateSignal.java b/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/signals/LamiSelectionUpdateSignal.java deleted file mode 100644 index 52c1edd32d..0000000000 --- a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/signals/LamiSelectionUpdateSignal.java +++ /dev/null @@ -1,77 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015, 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.provisional.analysis.lami.ui.signals; - -import java.util.HashSet; -import java.util.Set; - -import org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.views.LamiReportViewTabPage; -import org.eclipse.tracecompass.tmf.core.signal.TmfSignal; - -/** - * Enable signal sending on selection inside a LamiViewer implementation. - * - * @author Jonathan Rajotte-Julien - */ -public class LamiSelectionUpdateSignal extends TmfSignal { - - private final Set fEntryIndexes; - - /** - * Use the {@link LamiReportViewTabPage LamiReportViewTabPage} object as the - * unique key for LAMI internal signaling. The {@link LamiReportViewTabPage} - * object is also the synchronization point for LAMI internal signaling. - */ - private final LamiReportViewTabPage fSignalKey; - - /** - * Constructor for a new signal. - * - * @param source - * The object sending this signal - * @param entryIndexList - * The list of selected indices - * @param signalKey - * The {@link LamiReportViewTabPage LamiReportViewTabPage} acting - * as a key for the signal. - */ - public LamiSelectionUpdateSignal(Object source, Set entryIndexList, LamiReportViewTabPage signalKey) { - super(source); - fEntryIndexes = new HashSet<>(entryIndexList); - fSignalKey = signalKey; - } - - - @Override - public String toString() { - return "[" + this.getClass().getSimpleName() + " (" + fEntryIndexes + ")]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - } - - /** - * Getter for the entryIndex - * - * @return - * The new selected entry - */ - public Set getEntryIndex() { - return fEntryIndexes; - } - - - /** - * Getter for the exclusivity key - * - * @return - * The exclusivity key - */ - public LamiReportViewTabPage getSignalKey() { - return fSignalKey; - } -} diff --git a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/signals/package-info.java b/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/signals/package-info.java deleted file mode 100644 index 4a22c89347..0000000000 --- a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/signals/package-info.java +++ /dev/null @@ -1,11 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir - * - * 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.provisional.analysis.lami.ui.signals; diff --git a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/viewers/ILamiViewer.java b/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/viewers/ILamiViewer.java index 12832d81e6..40acd1fe91 100644 --- a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/viewers/ILamiViewer.java +++ b/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/viewers/ILamiViewer.java @@ -12,7 +12,6 @@ package org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.viewers; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; -import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiChartModel; import org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.views.LamiReportViewTabPage; /** @@ -41,27 +40,4 @@ public interface ILamiViewer { return new LamiTableViewer(tableViewer, page); } - /** - * Factory method to create a new chart viewer. The chart type is specified - * by the 'chartModel' parameter. - * - * @param parent - * The parent composite - * @param page - * The {@link LamiReportViewTabPage} parent page - * @param chartModel - * The information about the chart to display - * @return The new viewer - */ - static ILamiViewer createLamiChart(Composite parent, LamiReportViewTabPage page, LamiChartModel chartModel) { - switch (chartModel.getChartType()) { - case BAR_CHART: - return new LamiBarChartViewer(parent, page, chartModel); - case XY_SCATTER: - return new LamiScatterViewer(parent, page, chartModel); - case PIE_CHART: - default: - throw new UnsupportedOperationException("Unsupported chart type: " + chartModel.toString()); //$NON-NLS-1$ - } - } } diff --git a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/viewers/LamiBarChartViewer.java b/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/viewers/LamiBarChartViewer.java deleted file mode 100644 index 86ddfbca64..0000000000 --- a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/viewers/LamiBarChartViewer.java +++ /dev/null @@ -1,498 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015, 2016 EfficiOS Inc., Alexandre Montplaisir - * - * 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.provisional.analysis.lami.ui.viewers; - -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.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Stream; - -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.MouseAdapter; -import org.eclipse.swt.events.MouseEvent; -import org.eclipse.swt.events.PaintEvent; -import org.eclipse.swt.events.PaintListener; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.GC; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.widgets.Composite; -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.LamiChartType; -import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiTableEntry; -import org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.signals.LamiSelectionUpdateSignal; -import org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.views.LamiReportViewTabPage; -import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager; -import org.swtchart.IAxis; -import org.swtchart.IAxisTick; -import org.swtchart.IBarSeries; -import org.swtchart.ISeries; -import org.swtchart.ISeries.SeriesType; -import org.swtchart.Range; - -import com.google.common.collect.Iterators; - -/** - * Bar chart Viewer for LAMI views. - * - * @author Alexandre Montplaisir - * @author Jonathan Rajotte-Julien - * @author Mathieu Desnoyers - */ -public class LamiBarChartViewer extends LamiXYChartViewer { - - private static final double LOGSCALE_EPSILON_FACTOR = 100.0; - - private class Mapping { - final private @Nullable Integer fInternalValue; - final private @Nullable Integer fModelValue; - - public Mapping(@Nullable Integer internalValue, @Nullable Integer modelValue) { - fInternalValue = internalValue; - fModelValue = modelValue; - } - - public @Nullable Integer getInternalValue() { - return fInternalValue; - } - - public @Nullable Integer getModelValue() { - return fModelValue; - } - } - - private final String[] fCategories; - private final Map> fIndexPerSeriesMapping; - private final Map fEntryToCategoriesMap; - - private LamiGraphRange fYInternalRange = new LamiGraphRange(BigDecimal.ZERO, BigDecimal.ONE); - private LamiGraphRange fYExternalRange; - - - /** - * Creates a bar chart Viewer instance based on SWTChart. - * - * @param parent - * The parent composite to draw in. - * @param page - * The {@link LamiReportViewTabPage} parent page - * @param chartModel - * The information about the chart to build - */ - public LamiBarChartViewer(Composite parent, LamiReportViewTabPage page, LamiChartModel chartModel) { - super(parent, page, chartModel); - - List xAxisAspects = getXAxisAspects(); - List yAxisAspects = getYAxisAspects(); - - /* bar chart cannot deal with multiple X series */ - if (getChartModel().getChartType() != LamiChartType.BAR_CHART && xAxisAspects.size() != 1) { - throw new IllegalArgumentException("Invalid configuration passed to a bar chart."); //$NON-NLS-1$ - } - - /* Enable categories */ - getChart().getAxisSet().getXAxis(0).enableCategory(true); - - LamiTableEntryAspect xAxisAspect = xAxisAspects.get(0); - List entries = getResultTable().getEntries(); - boolean logscale = chartModel.yAxisIsLog(); - fIndexPerSeriesMapping = new HashMap<>(); - fEntryToCategoriesMap = new HashMap<>(); - - /* Categories index mapping */ - Format formatter = null; - if (xAxisAspect.isContinuous()) { - formatter = getContinuousAxisFormatter(xAxisAspects, entries, null, null); - } - - List<@Nullable String> xCategories = new ArrayList<>(); - for (int i = 0; i < entries.size(); i++) { - String string = xAxisAspect.resolveString(entries.get(i)); - if (string == null) { - fEntryToCategoriesMap.put(entries.get(i), new Mapping(null, i)); - continue; - } - - fEntryToCategoriesMap.put(entries.get(i), new Mapping(xCategories.size(), i)); - if (formatter != null) { - string = formatter.format(xAxisAspect.resolveNumber(entries.get(i))); - } - - xCategories.add(string); - - } - fCategories = xCategories.toArray(new String[0]); - - /* The y values range */ - /* Clamp minimum to zero or negative value */ - fYExternalRange = getRange(yAxisAspects, true); - - /* - * Log scale magic course 101: - * - * It uses the relative difference divided by a factor - * (100) to get as close as it can to the actual minimum but still a - * little bit smaller. This is used as a workaround of SWTCHART - * limitations regarding custom scale drawing in log scale mode, bogus - * representation of NaN double values and limited support of multiple - * size series. - * - * This should be good enough for most users. - */ - double min = Double.MAX_VALUE; - double max = Double.MIN_VALUE; - double logScaleEpsilon = ZERO_DOUBLE; - if (logscale) { - - /* Find minimum and maximum values excluding <= 0 values */ - for (LamiTableEntryAspect aspect : yAxisAspects) { - for (LamiTableEntry entry : entries) { - Number externalValue = aspect.resolveNumber(entry); - if (externalValue == null) { - continue; - } - Double value = getInternalDoubleValue(externalValue, fYInternalRange, fYExternalRange); - if (value <= 0) { - continue; - } - min = Math.min(min, value); - max = Math.max(max, value); - } - } - - if (min == Double.MAX_VALUE) { - /* Series are empty in log scale*/ - return; - } - - double delta = max - min; - logScaleEpsilon = min - ((min * delta) / (LOGSCALE_EPSILON_FACTOR * max)); - } - - for (LamiTableEntryAspect yAxisAspect : yAxisAspects) { - if (!yAxisAspect.isContinuous() || yAxisAspect.isTimeStamp()) { - /* Only plot continuous aspects */ - continue; - } - - List validXValues = new ArrayList<>(); - List validYValues = new ArrayList<>(); - List indexMapping = new ArrayList<>(); - - for (int i = 0; i < entries.size(); i++) { - Integer categoryIndex = checkNotNull(fEntryToCategoriesMap.get(checkNotNull(entries.get(i)))).fInternalValue; - - if (categoryIndex == null) { - /* Invalid value do not show */ - continue; - } - - Double yValue = ZERO_DOUBLE; - @Nullable Number number = yAxisAspect.resolveNumber(entries.get(i)); - - if (number == null) { - /* - * Null value for y is the same as zero since this is a bar - * chart - */ - yValue = ZERO_DOUBLE; - } else { - yValue = getInternalDoubleValue(number, fYInternalRange, fYExternalRange); - } - - if (logscale && yValue <= ZERO_DOUBLE) { - /* - * Less or equal to 0 values can't be plotted on a log - * scale. We map them to the mean of the >=0 minimal value - * and the calculated log scale magic epsilon. - */ - yValue = (min + logScaleEpsilon) / 2.0; - } - - validXValues.add(checkNotNull(categoryIndex).doubleValue()); - validYValues.add(yValue.doubleValue()); - indexMapping.add(new Mapping(categoryIndex, checkNotNull(fEntryToCategoriesMap.get(checkNotNull(entries.get(i)))).fModelValue)); - } - - String name = yAxisAspect.getLabel(); - - if (validXValues.isEmpty() || validYValues.isEmpty()) { - /* No need to plot an empty series */ - continue; - } - - IBarSeries barSeries = (IBarSeries) getChart().getSeriesSet().createSeries(SeriesType.BAR, name); - barSeries.setXSeries(validXValues.stream().mapToDouble(Double::doubleValue).toArray()); - barSeries.setYSeries(validYValues.stream().mapToDouble(Double::doubleValue).toArray()); - fIndexPerSeriesMapping.put(barSeries, indexMapping); - } - - setBarSeriesColors(); - - /* Set all y axis logscale mode */ - Stream.of(getChart().getAxisSet().getYAxes()).forEach(axis -> axis.enableLogScale(logscale)); - - /* Set the formatter on the Y axis */ - IAxisTick yTick = getChart().getAxisSet().getYAxis(0).getTick(); - yTick.setFormat(getContinuousAxisFormatter(yAxisAspects, entries, fYInternalRange, fYExternalRange)); - - /* - * 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); - - /* Adjust the chart range */ - getChart().getAxisSet().adjustRange(); - - if (logscale && logScaleEpsilon != max) { - getChart().getAxisSet().getYAxis(0).setRange(new Range(logScaleEpsilon, max)); - } - - /* Once the chart is filled, refresh the axis labels */ - refreshDisplayLabels(); - - /* Add mouse listener */ - getChart().getPlotArea().addMouseListener(new LamiBarChartMouseDownListener()); - - /* Custom Painter listener to highlight the current selection */ - getChart().getPlotArea().addPaintListener(new LamiBarChartPainterListener()); - } - - private final class LamiBarChartMouseDownListener extends MouseAdapter { - - @Override - public void mouseDown(@Nullable MouseEvent event) { - if (event == null || event.button != 1) { - return; - } - - boolean ctrlMode = false; - int xMouseLocation = event.x; - int yMouseLocation = event.y; - - Set selections; - if ((event.stateMask & SWT.CTRL) != 0) { - ctrlMode = true; - selections = getSelection(); - } else { - /* Reset selection state */ - unsetSelection(); - selections = new HashSet<>(); - } - - ISeries[] series = getChart().getSeriesSet().getSeries(); - - /* - * Iterate over all series, get the rectangle bounds for each - * category, and find the category index under the mouse. - * - * Since categories map directly to the index of the fResultTable - * and that this table is immutable the index of the entry - * corresponds to the categories index. Signal to all LamiViewer and - * LamiView the update of selection. - */ - for (ISeries oneSeries : series) { - IBarSeries barSerie = ((IBarSeries) oneSeries); - Rectangle[] recs = barSerie.getBounds(); - - for (int j = 0; j < recs.length; j++) { - Rectangle rectangle = recs[j]; - if (rectangle.contains(xMouseLocation, yMouseLocation)) { - int index = getTableEntryIndexFromGraphIndex(checkNotNull(oneSeries), j); - if (!ctrlMode || (index >= 0 && !selections.remove(index))) { - selections.add(index); - } - } - } - } - - /* Save the current selection internally */ - setSelection(selections); - /* Signal all Lami viewers & views of the selection */ - LamiSelectionUpdateSignal signal = new LamiSelectionUpdateSignal(this, - selections, getPage()); - TmfSignalManager.dispatchSignal(signal); - redraw(); - } - } - - @Override - protected void redraw() { - setBarSeriesColors(); - super.redraw(); - } - - /** - * Set the chart series colors according to the selection state. Use light - * colors when a selection is present. - */ - private void setBarSeriesColors() { - Iterator colorsIt; - - if (isSelected()) { - colorsIt = Iterators.cycle(LIGHT_COLORS); - } else { - colorsIt = Iterators.cycle(COLORS); - } - - for (ISeries series : getChart().getSeriesSet().getSeries()) { - ((IBarSeries) series).setBarColor(colorsIt.next()); - } - } - - private final class LamiBarChartPainterListener implements PaintListener { - @Override - public void paintControl(@Nullable PaintEvent e) { - if (e == null || !isSelected()) { - return; - } - - Iterator colorsIt = Iterators.cycle(COLORS); - GC gc = e.gc; - - for (ISeries series : getChart().getSeriesSet().getSeries()) { - Color color = colorsIt.next(); - for (int index : getSelection()) { - int graphIndex = getGraphIndexFromTableEntryIndex(series, index); - if (graphIndex < 0) { - /* Invalid index */ - continue; - } - - Rectangle[] bounds = ((IBarSeries) series).getBounds(); - if (bounds.length != fCategories.length) { - /* - * The plot is too cramped and SWTChart currently does - * its best on rectangle drawing and returns the - * rectangle that it is able to draw. - * - * For now we simply do not draw since it is really hard - * to see anyway. A better way to visualize the value - * would be a full cross for each selection based on - * their coordinates. - */ - continue; - } - Rectangle rectangle = bounds[graphIndex]; - gc.setBackground(color); - gc.fillRectangle(rectangle); - } - } - } - } - - @Override - protected void refreshDisplayLabels() { - /* Only if we have at least 1 category */ - if (fCategories.length == 0) { - return; - } - - /* Only refresh if labels are visible */ - IAxis xAxis = getChart().getAxisSet().getXAxis(0); - if (!xAxis.getTick().isVisible() || !xAxis.isCategoryEnabled()) { - return; - } - - /* - * Shorten all the labels to 5 characters plus "…" when the longest - * label length is more than 50% of the chart height. - */ - - Rectangle rect = getChart().getClientArea(); - int lengthLimit = (int) (rect.height * 0.40); - - GC gc = new GC(fParent); - gc.setFont(xAxis.getTick().getFont()); - - /* Find the longest category string */ - String longestString = Arrays.stream(fCategories).max(Comparator.comparingInt(String::length)).orElse(fCategories[0]); - - /* Get the length and height of the longest label in pixels */ - Point pixels = gc.stringExtent(longestString); - - // Completely arbitrary - int cutLen = 5; - - String[] displayCategories = new String[fCategories.length]; - if (pixels.x > lengthLimit) { - /* We have to cut down some strings */ - for (int i = 0; i < fCategories.length; i++) { - if (fCategories[i].length() > cutLen) { - displayCategories[i] = fCategories[i].substring(0, cutLen) + ELLIPSIS; - } else { - displayCategories[i] = fCategories[i]; - } - } - } else { - /* All strings should fit */ - displayCategories = Arrays.copyOf(fCategories, fCategories.length); - } - xAxis.setCategorySeries(displayCategories); - - /* Cleanup */ - gc.dispose(); - } - - private int getTableEntryIndexFromGraphIndex(ISeries series, int index) { - List indexes = fIndexPerSeriesMapping.get(series); - if (indexes == null || index > indexes.size() || index < 0) { - return -1; - } - - Mapping mapping = indexes.get(index); - Integer modelValue = mapping.getModelValue(); - if (modelValue != null) { - return modelValue.intValue(); - } - return -1; - } - - private int getGraphIndexFromTableEntryIndex(ISeries series, int index) { - List indexes = fIndexPerSeriesMapping.get(series); - if (indexes == null || index < 0) { - return -1; - } - - int internalIndex = -1; - for (Mapping mapping : indexes) { - if (mapping.getModelValue() == index) { - Integer internalValue = mapping.getInternalValue(); - if (internalValue != null) { - internalIndex = internalValue.intValue(); - break; - } - } - } - return internalIndex; - } -} diff --git a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/viewers/LamiScatterViewer.java b/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/viewers/LamiScatterViewer.java deleted file mode 100644 index 2e512fc230..0000000000 --- a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/viewers/LamiScatterViewer.java +++ /dev/null @@ -1,711 +0,0 @@ -/******************************************************************************* - * 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.provisional.analysis.lami.ui.viewers; - -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 java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.MouseAdapter; -import org.eclipse.swt.events.MouseEvent; -import org.eclipse.swt.events.MouseMoveListener; -import org.eclipse.swt.events.PaintEvent; -import org.eclipse.swt.events.PaintListener; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.GC; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Listener; -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.LamiChartType; -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.internal.provisional.analysis.lami.ui.views.LamiReportViewTabPage; -import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager; -import org.swtchart.IAxisTick; -import org.swtchart.ILineSeries; -import org.swtchart.ISeries; -import org.swtchart.ISeries.SeriesType; -import org.swtchart.LineStyle; - -import com.google.common.collect.BiMap; -import com.google.common.collect.HashBiMap; -import com.google.common.collect.Iterators; - -/** - * XY Scatter chart viewer for Lami views - * - * @author Jonathan Rajotte-Julien - */ -public class LamiScatterViewer extends LamiXYChartViewer { - - private static final int SELECTION_SNAP_RANGE_MULTIPLIER = 20; - private static final int SELECTION_CROSS_SIZE_MULTIPLIER = 3; - - private final Map> fIndexMapping; - - /* Use a scale from 0 to 1 internally for both axes */ - private LamiGraphRange fXInternalRange = new LamiGraphRange(BigDecimal.ZERO, BigDecimal.ONE); - private LamiGraphRange fYInternalRange = new LamiGraphRange(BigDecimal.ZERO, BigDecimal.ONE); - - private @Nullable LamiGraphRange fXExternalRange = null; - private @Nullable LamiGraphRange fYExternalRange = null; - - /* The current data point for the hovering cross */ - private Point fHoveringCrossDataPoint; - - /** - * Constructor - * - * @param parent - * parent - * @param page - * The {@link LamiReportViewTabPage} parent page - * @param graphModel - * Model of this chart - */ - public LamiScatterViewer(Composite parent, LamiReportViewTabPage page, LamiChartModel graphModel) { - super(parent, page, graphModel); - if (getChartModel().getChartType() != LamiChartType.XY_SCATTER) { - throw new IllegalStateException("Chart type not a Scatter Chart " + getChartModel().getChartType().toString()); //$NON-NLS-1$ - } - - /* Inspect X series */ - fIndexMapping = new HashMap<>(); - - fHoveringCrossDataPoint = new Point(-1, -1); - - List xAxisAspects = getXAxisAspects(); - if (xAxisAspects.stream().distinct().count() == 1) { - LamiTableEntryAspect singleXAspect = xAxisAspects.get(0); - xAxisAspects.clear(); - xAxisAspects.add(singleXAspect); - } - - BiMap<@Nullable String, Integer> xMap = HashBiMap.create(); - boolean xIsLog = graphModel.xAxisIsLog(); - - boolean areXAspectsContinuous = areAspectsContinuous(xAxisAspects); - boolean areXAspectsTimeStamp = areAspectsTimeStamp(xAxisAspects); - - /* Check all aspect are the same type */ - for (LamiTableEntryAspect aspect : xAxisAspects) { - if (aspect.isContinuous() != areXAspectsContinuous) { - throw new IllegalStateException("Some X aspects are continuous and some are not"); //$NON-NLS-1$ - } - if (aspect.isTimeStamp() != areXAspectsTimeStamp) { - throw new IllegalStateException("Some X aspects are time based and some are not"); //$NON-NLS-1$ - } - } - - /* - * When xAxisAspects are discrete create a map for all values of all - * series - */ - 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); - } - - /* - * Create Y series - */ - List yAxisAspects = getYAxisAspects(); - BiMap<@Nullable String, Integer> yMap = HashBiMap.create(); - boolean yIsLog = graphModel.yAxisIsLog(); - - boolean areYAspectsContinuous = areAspectsContinuous(yAxisAspects); - boolean areYAspectsTimeStamp = areAspectsTimeStamp(yAxisAspects); - - /* Check all aspect are the same type */ - for (LamiTableEntryAspect aspect : yAxisAspects) { - if (aspect.isContinuous() != areYAspectsContinuous) { - throw new IllegalStateException("Some Y aspects are continuous and some are not"); //$NON-NLS-1$ - } - if (aspect.isTimeStamp() != areYAspectsTimeStamp) { - throw new IllegalStateException("Some Y aspects are time based and some are not"); //$NON-NLS-1$ - } - } - - /* - * When yAspects are discrete create a map for all values of all series - */ - 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; - LamiTableEntryAspect xAspect; - if (xAxisAspects.size() == 1) { - /* Always map to the same x series */ - xAspect = xAxisAspects.get(0); - name = yAspect.getLabel(); - } else { - xAspect = xAxisAspects.get(index); - name = (yAspect.getName() + ' ' + Messages.LamiScatterViewer_by + ' ' + xAspect.getName()); - } - - List<@Nullable Double> xDoubleSeries; - List<@Nullable Double> yDoubleSeries; - - if (xAspect.isContinuous()) { - 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()); - } - - if (yAspect.isContinuous()) { - 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()); - } - - List<@Nullable Double> validXDoubleSeries = new ArrayList<>(); - List<@Nullable Double> validYDoubleSeries = new ArrayList<>(); - List indexSeriesCorrespondance = new ArrayList<>(); - - if (xDoubleSeries.size() != yDoubleSeries.size()) { - throw new IllegalStateException("Series sizes don't match!"); //$NON-NLS-1$ - } - - /* Check for invalid tuple value. Any null elements are invalid */ - for (int i = 0; i < xDoubleSeries.size(); i++) { - Double xValue = xDoubleSeries.get(i); - Double yValue = yDoubleSeries.get(i); - if (xValue == null || yValue == null) { - /* Reject this tuple */ - continue; - } - if ((xIsLog && xValue <= ZERO_DOUBLE) || (yIsLog && yValue <= ZERO_DOUBLE)) { - /* - * Equal or less than 0 values can't be plotted on log scale - */ - continue; - } - validXDoubleSeries.add(xValue); - validYDoubleSeries.add(yValue); - indexSeriesCorrespondance.add(i); - } - - if (validXDoubleSeries.isEmpty() || validXDoubleSeries.isEmpty()) { - /* No need to plot an empty series */ - index++; - continue; - } - - ILineSeries scatterSeries = (ILineSeries) getChart().getSeriesSet().createSeries(SeriesType.LINE, name); - scatterSeries.setLineStyle(LineStyle.NONE); - - double[] xserie = validXDoubleSeries.stream().mapToDouble(elem -> checkNotNull(elem).doubleValue()).toArray(); - double[] yserie = validYDoubleSeries.stream().mapToDouble(elem -> checkNotNull(elem).doubleValue()).toArray(); - scatterSeries.setXSeries(xserie); - scatterSeries.setYSeries(yserie); - fIndexMapping.put(scatterSeries, indexSeriesCorrespondance); - index++; - } - - /* Modify x axis related chart styling */ - IAxisTick xTick = getChart().getAxisSet().getXAxis(0).getTick(); - if (areXAspectsContinuous) { - 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); - - /* Remove vertical grid line */ - getChart().getAxisSet().getXAxis(0).getGrid().setStyle(LineStyle.NONE); - } - - /* Modify Y axis related chart styling */ - IAxisTick yTick = getChart().getAxisSet().getYAxis(0).getTick(); - if (areYAspectsContinuous) { - 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); - - /* 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 */ - if (xIsLog && areXAspectsContinuous && !areXAspectsTimeStamp) { - Stream.of(getChart().getAxisSet().getXAxes()).forEach(axis -> axis.enableLogScale(xIsLog)); - } - - if (yIsLog && areYAspectsContinuous && !areYAspectsTimeStamp) { - /* Set the axis as logscale */ - Stream.of(getChart().getAxisSet().getYAxes()).forEach(axis -> axis.enableLogScale(yIsLog)); - } - getChart().getAxisSet().adjustRange(); - - /* - * Selection listener - */ - getChart().getPlotArea().addMouseListener(new LamiScatterMouseDownListener()); - - /* - * Hovering cross listener - */ - getChart().getPlotArea().addMouseMoveListener(new HoveringCrossListener()); - - /* - * Mouse exit listener: reset state of hovering cross on mouse exit. - */ - getChart().getPlotArea().addListener(SWT.MouseExit, new Listener() { - - @Override - public void handleEvent(@Nullable Event event) { - if (event != null) { - fHoveringCrossDataPoint.x = -1; - fHoveringCrossDataPoint.y = -1; - redraw(); - } - } - }); - - /* - * Selections and hovering cross painting - */ - getChart().getPlotArea().addPaintListener(new LamiScatterPainterListener()); - - /* On resize check for axis tick updating */ - getChart().addListener(SWT.Resize, new Listener() { - @Override - public void handleEvent(@Nullable Event event) { - if (yTick.getFormat() instanceof LamiLabelFormat) { - updateTickMark(checkNotNull(yMap), yTick, getChart().getPlotArea().getSize().y); - } - if (xTick.getFormat() instanceof LamiLabelFormat) { - updateTickMark(checkNotNull(xMap), xTick, getChart().getPlotArea().getSize().x); - } - } - }); - } - - private void generateLabelMap(List aspects, BiMap<@Nullable String, Integer> map) { - TreeSet<@Nullable String> set = new TreeSet<>(); - for (LamiTableEntryAspect aspect : aspects) { - for (LamiTableEntry entry : getResultTable().getEntries()) { - String string = aspect.resolveString(entry); - if (string != null) { - set.add(string); - } - } - } - /* Ordered label mapping to double */ - for (String string : set) { - map.put(string, map.size()); - } - } - - /** - * Set the chart series colors. - */ - private void setLineSeriesColor() { - Iterator colorsIt; - - colorsIt = Iterators.cycle(COLORS); - - for (ISeries series : getChart().getSeriesSet().getSeries()) { - ((ILineSeries) series).setSymbolColor((colorsIt.next())); - /* - * Generate initial array of Color to enable per point color change - * on selection in the future - */ - ArrayList colors = new ArrayList<>(); - for (int i = 0; i < series.getXSeries().length; i++) { - Color color = ((ILineSeries) series).getSymbolColor(); - colors.add(checkNotNull(color)); - } - ((ILineSeries) series).setSymbolColors(colors.toArray(new Color[colors.size()])); - } - } - - // ------------------------------------------------------------------------ - // Listeners - // ------------------------------------------------------------------------ - - private final class HoveringCrossListener implements MouseMoveListener { - - @Override - public void mouseMove(@Nullable MouseEvent e) { - if (e == null) { - return; - } - ISeries[] series = getChart().getSeriesSet().getSeries(); - @Nullable Point closest = null; - double closestDistance = -1.0; - - for (ISeries oneSeries : series) { - ILineSeries lineSerie = (ILineSeries) oneSeries; - for (int i = 0; i < lineSerie.getXSeries().length; i++) { - Point dataPoint = lineSerie.getPixelCoordinates(i); - - /* - * Find the distance between the data point and the mouse - * location and compare it to the symbol size * the range - * multiplier, so when a user hovers the mouse near the dot - * the cursor cross snaps to it. - */ - int snapRangeRadius = lineSerie.getSymbolSize() * SELECTION_SNAP_RANGE_MULTIPLIER; - - /* - * FIXME if and only if performance of this code is an issue - * for large sets, this can be accelerated by getting the - * distance squared, and if it is smaller than - * snapRangeRadius squared, then check hypot. - */ - double distance = Math.hypot(dataPoint.x - e.x, dataPoint.y - e.y); - if (distance < snapRangeRadius) { - if (closestDistance == -1 || distance < closestDistance) { - closest = dataPoint; - closestDistance = distance; - } - } - } - } - if (closest != null) { - fHoveringCrossDataPoint.x = closest.x; - fHoveringCrossDataPoint.y = closest.y; - } else { - fHoveringCrossDataPoint.x = -1; - fHoveringCrossDataPoint.y = -1; - } - refresh(); - } - } - - private final class LamiScatterMouseDownListener extends MouseAdapter { - - @Override - public void mouseDown(@Nullable MouseEvent event) { - if (event == null || event.button != 1) { - return; - } - - int xMouseLocation = event.x; - int yMouseLocation = event.y; - - boolean ctrlMode = false; - - ISeries[] series = getChart().getSeriesSet().getSeries(); - Set selections = getSelection(); - - /* Check for ctrl on click */ - if ((event.stateMask & SWT.CTRL) != 0) { - selections = getSelection(); - ctrlMode = true; - } else { - /* Reset selection */ - unsetSelection(); - selections = new HashSet<>(); - } - - for (ISeries oneSeries : series) { - ILineSeries lineSerie = (ILineSeries) oneSeries; - - int closest = -1; - double closestDistance = -1; - for (int i = 0; i < lineSerie.getXSeries().length; i++) { - Point dataPoint = lineSerie.getPixelCoordinates(i); - - /* - * Find the distance between the data point and the mouse - * location, and compare it to the symbol size so when a - * user clicks on a symbol it selects it. - */ - double distance = Math.hypot(dataPoint.x - xMouseLocation, dataPoint.y - yMouseLocation); - int snapRangeRadius = lineSerie.getSymbolSize() * SELECTION_SNAP_RANGE_MULTIPLIER; - if (distance < snapRangeRadius) { - if (closestDistance == -1 || distance < closestDistance) { - closest = i; - closestDistance = distance; - } - } - } - if (closest != -1) { - /* Translate to global index */ - int tableEntryIndex = getTableEntryIndexFromGraphIndex(checkNotNull(oneSeries), closest); - if (tableEntryIndex < 0) { - continue; - } - LamiTableEntry entry = getResultTable().getEntries().get(tableEntryIndex); - int index = getResultTable().getEntries().indexOf(entry); - - if (!ctrlMode || !selections.remove(index)) { - selections.add(index); - } - /* Do no iterate since we already found a match */ - break; - } - } - setSelection(selections); - /* Signal all Lami viewers & views of the selection */ - LamiSelectionUpdateSignal signal = new LamiSelectionUpdateSignal(this, - selections, getPage()); - TmfSignalManager.dispatchSignal(signal); - refresh(); - } - } - - private final class LamiScatterPainterListener implements PaintListener { - - @Override - public void paintControl(@Nullable PaintEvent e) { - if (e == null) { - return; - } - GC gc = e.gc; - - /* Draw the selection */ - drawSelectedDot(checkNotNull(gc)); - - /* Draw the hovering cross */ - drawHoveringCross(checkNotNull(gc)); - } - - private void drawSelectedDot(GC gc) { - if (isSelected()) { - Iterator colorsIt; - colorsIt = Iterators.cycle(COLORS); - for (ISeries series : getChart().getSeriesSet().getSeries()) { - - /* Get series colors */ - Color color = colorsIt.next(); - int symbolSize = ((ILineSeries) series).getSymbolSize(); - - for (int index : getInternalSelections()) { - int graphIndex = getGraphIndexFromTableEntryIndex(series, index); - - if (graphIndex < 0) { - continue; - } - Point point = series.getPixelCoordinates(graphIndex); - - /* Create a colored dot for selection */ - gc.setBackground(color); - gc.fillOval(point.x - symbolSize, point.y - symbolSize, symbolSize * 2, symbolSize * 2); - - /* Draw cross */ - gc.setLineWidth(2); - gc.setLineStyle(SWT.LINE_SOLID); - /* Vertical line */ - int drawingDelta = SELECTION_CROSS_SIZE_MULTIPLIER * symbolSize; - gc.drawLine(point.x, point.y - drawingDelta, point.x, point.y + drawingDelta); - /* Horizontal line */ - gc.drawLine(point.x - drawingDelta, point.y, point.x + drawingDelta, point.y); - - } - } - } - } - - private void drawHoveringCross(GC gc) { - gc.setLineWidth(1); - gc.setLineStyle(SWT.LINE_SOLID); - gc.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_BLACK)); - gc.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE)); - /* Vertical line */ - gc.drawLine(fHoveringCrossDataPoint.x, 0, fHoveringCrossDataPoint.x, getChart().getPlotArea().getSize().y); - /* Horizontal line */ - gc.drawLine(0, fHoveringCrossDataPoint.y, getChart().getPlotArea().getSize().x, fHoveringCrossDataPoint.y); - } - } - - // ------------------------------------------------------------------------ - // Utility functions - // ------------------------------------------------------------------------ - - private int getTableEntryIndexFromGraphIndex(ISeries series, int index) { - List indexes = fIndexMapping.get(series); - if (indexes == null || index > indexes.size() || index < 0) { - return -1; - } - return indexes.get(index); - } - - private int getGraphIndexFromTableEntryIndex(ISeries series, int index) { - List indexes = fIndexMapping.get(series); - if (indexes == null || !indexes.contains(index)) { - return -1; - } - return indexes.indexOf(index); - } - - @Override - protected void refreshDisplayLabels() { - } - - /** - * Return the current selection in internal mapping - * - * @return the internal selections - */ - protected Set getInternalSelections() { - /* Translate to internal table location */ - Set indexes = super.getSelection(); - Set internalIndexes = indexes.stream() - .mapToInt(index -> getResultTable().getEntries().indexOf((getResultTable().getEntries().get(index)))) - .boxed() - .collect(Collectors.toSet()); - return internalIndexes; - } - - private static void updateTickMark(BiMap<@Nullable String, Integer> map, IAxisTick tick, int availableLenghtPixel) { - int nbLabels = Math.max(1, map.size()); - int stepSizePixel = availableLenghtPixel / nbLabels; - /* - * This step is a limitation on swtchart side regarding minimal grid - * step hint size. When the step size are smaller it get defined as the - * "default" value for the axis instead of the smallest one. - */ - if (IAxisTick.MIN_GRID_STEP_HINT > stepSizePixel) { - stepSizePixel = (int) IAxisTick.MIN_GRID_STEP_HINT; - } - tick.setTickMarkStepHint(stepSizePixel); - } - - @Override - protected void setSelection(@NonNull Set<@NonNull Integer> selection) { - super.setSelection(selection); - - /* Set color of selected symbol */ - Iterator colorsIt = Iterators.cycle(COLORS); - Iterator lightColorsIt = Iterators.cycle(LIGHT_COLORS); - - Set currentSelections = getInternalSelections(); - - for (ISeries series : getChart().getSeriesSet().getSeries()) { - /* Series color */ - 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 */ - Arrays.fill(colors, color); - } else { - /* - * Fill with light colors to represent the deselected state. The - * paint listener is then responsible for drawing the cross and - * the dark colors for the selection. - */ - Arrays.fill(colors, lightColor); - } - ((ILineSeries) series).setSymbolColors(colors); - } - } - -} diff --git a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/viewers/LamiTableViewer.java b/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/viewers/LamiTableViewer.java index 439202a990..ea65f9b968 100644 --- a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/viewers/LamiTableViewer.java +++ b/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/viewers/LamiTableViewer.java @@ -24,11 +24,11 @@ import org.eclipse.jface.viewers.TableViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.aspect.LamiTableEntryAspect; import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiTableEntry; -import org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.signals.LamiSelectionUpdateSignal; import org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.views.LamiReportView; import org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.views.LamiReportViewTabPage; import org.eclipse.tracecompass.internal.provisional.tmf.chart.core.signal.ChartSelectionUpdateSignal; @@ -49,7 +49,6 @@ public final class LamiTableViewer extends TmfSimpleTableViewer implements ILami // ------------------------------------------------------------------------ private final LamiReportViewTabPage fPage; - private Set fSelections; private Set fSelection; // ------------------------------------------------------------------------ @@ -87,18 +86,6 @@ public final class LamiTableViewer extends TmfSimpleTableViewer implements ILami public void widgetSelected(@Nullable SelectionEvent event) { IStructuredSelection selections = getTableViewer().getStructuredSelection(); - // Lami selections - Set selectionIndexes = new HashSet<>(); - for (Object selectedEntry : selections.toArray() ) { - selectionIndexes.add(fPage.getResultTable().getEntries().indexOf(selectedEntry)); - } - - fSelections = selectionIndexes; - - /* Signal all Lami viewers & views of the selection */ - LamiSelectionUpdateSignal signal = new LamiSelectionUpdateSignal(LamiTableViewer.this, selectionIndexes, fPage); - TmfSignalManager.dispatchSignal(signal); - /* Find all selected entries */ Set selectionSet = new HashSet<>(); for (Object selectedEntry : selections.toArray()) { @@ -132,7 +119,6 @@ public final class LamiTableViewer extends TmfSimpleTableViewer implements ILami tableViewer.getTable().moveAbove(null); fPage = page; - fSelections = new HashSet<>(); fSelection = new HashSet<>(); /* Default sort order of the content provider is by its first column */ @@ -143,6 +129,20 @@ public final class LamiTableViewer extends TmfSimpleTableViewer implements ILami fillData(); } + /** + * Factory method to create a new Table viewer. + * + * @param parent + * The parent composite + * @param page + * The {@link LamiReportViewTabPage} parent page + * @return The new viewer + */ + public static LamiTableViewer createLamiTable(Composite parent, LamiReportViewTabPage page) { + TableViewer tableViewer = new TableViewer(parent, SWT.FULL_SELECTION | SWT.MULTI | SWT.VIRTUAL); + return new LamiTableViewer(tableViewer, page); + } + // ------------------------------------------------------------------------ // Operations // ------------------------------------------------------------------------ @@ -198,17 +198,6 @@ public final class LamiTableViewer extends TmfSimpleTableViewer implements ILami * asynchronous task we cannot use the normal signal handler since * we have no guarantee of time of execution of the fill data. */ - if (!fSelections.isEmpty()) { - int[] selectionsIndexes = fSelections.stream() - .map(index -> fPage.getResultTable().getEntries().get(index)) - .mapToInt(entry -> ((LamiTableContentProvider) getTableViewer().getContentProvider()).getIndexOf(entry)) - .toArray(); - - Display.getDefault().asyncExec(() -> { - getTableViewer().getTable().setSelection(selectionsIndexes); - getTableViewer().getTable().redraw(); - }); - } if (!fSelection.isEmpty()) { LamiTableContentProvider provider = (LamiTableContentProvider) getTableViewer().getContentProvider(); @@ -241,37 +230,6 @@ public final class LamiTableViewer extends TmfSimpleTableViewer implements ILami // Signals // ------------------------------------------------------------------------ - /** - * The signal handler for selection update. - * - * @param signal - * The selection update signal - */ - @TmfSignalHandler - public void updateSelection(LamiSelectionUpdateSignal signal) { - - if (fPage != signal.getSignalKey() || equals(signal.getSource())) { - /* The signal is not for us */ - return; - } - /* Fetch the position of the selected entry in the actual table since it could be sorted by another column */ - LamiTableContentProvider latencyContentProvider = (LamiTableContentProvider) getTableViewer().getContentProvider(); - - Set selections = signal.getEntryIndex(); - - int[] selectionsIndexes = selections.stream() - .map(index -> fPage.getResultTable().getEntries().get(index)) - .mapToInt(entry -> latencyContentProvider.getIndexOf(entry)) - .toArray(); - - fSelections = new HashSet<>(selections); - - Display.getDefault().asyncExec(() -> { - getTableViewer().getTable().setSelection(selectionsIndexes); - getTableViewer().getTable().redraw(); - }); - } - /** * The signal handler for selection update. * diff --git a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/viewers/LamiXYChartViewer.java b/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/viewers/LamiXYChartViewer.java deleted file mode 100644 index 5b8f92b7d4..0000000000 --- a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/viewers/LamiXYChartViewer.java +++ /dev/null @@ -1,925 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015, 2016 EfficiOS Inc., Michael Jeanson - * - * 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.provisional.analysis.lami.ui.viewers; - -import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull; -import static org.eclipse.tracecompass.common.core.NonNullUtils.nullToEmptyString; - -import java.math.BigDecimal; -import java.text.Format; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.function.ToDoubleFunction; - -import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.Font; -import org.eclipse.swt.graphics.GC; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Listener; -import org.eclipse.swt.widgets.ToolBar; -import org.eclipse.swt.widgets.ToolItem; -import org.eclipse.tracecompass.common.core.format.DecimalUnitFormat; -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.LamiResultTable; -import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiTableEntry; -import org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.format.LamiDecimalUnitFormat; -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.internal.provisional.analysis.lami.ui.views.LamiReportViewTabPage; -import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler; -import org.eclipse.tracecompass.tmf.ui.viewers.TmfViewer; -import org.eclipse.ui.ISharedImages; -import org.eclipse.ui.PlatformUI; -import org.swtchart.Chart; -import org.swtchart.ITitle; - -import com.google.common.collect.ImmutableList; - -/** - * Abstract XYChart Viewer for LAMI views. - * - * @author Michael Jeanson - * - */ -public abstract class LamiXYChartViewer extends TmfViewer implements ILamiViewer { - - /** Ellipsis character */ - protected static final String ELLIPSIS = "…"; //$NON-NLS-1$ - - /** - * String representing unknown values. Can be present even in numerical - * aspects! - */ - protected static final String UNKNOWN = "?"; //$NON-NLS-1$ - - /** Zero long value */ - protected static final long ZERO_LONG = 0L; - /** Zero double value */ - protected static final double ZERO_DOUBLE = 0.0; - - /** - * Function to use to map Strings read from the data table to doubles for - * use in SWTChart series. - */ - protected static final ToDoubleFunction<@Nullable String> DOUBLE_MAPPER = str -> { - if (str == null || str.equals(UNKNOWN)) { - return ZERO_LONG; - } - return Double.parseDouble(str); - }; - - /** - * List of standard colors - */ - protected static final List<@NonNull Color> COLORS = ImmutableList.of( - new Color(Display.getDefault(), 72, 120, 207), - new Color(Display.getDefault(), 106, 204, 101), - new Color(Display.getDefault(), 214, 95, 95), - new Color(Display.getDefault(), 180, 124, 199), - new Color(Display.getDefault(), 196, 173, 102), - new Color(Display.getDefault(), 119, 190, 219) - ); - - /** - * List of "light" colors (when unselected) - */ - protected static final List<@NonNull Color> LIGHT_COLORS = ImmutableList.of( - new Color(Display.getDefault(), 173, 195, 233), - new Color(Display.getDefault(), 199, 236, 197), - new Color(Display.getDefault(), 240, 196, 196), - new Color(Display.getDefault(), 231, 213, 237), - new Color(Display.getDefault(), 231, 222, 194), - new Color(Display.getDefault(), 220, 238, 246) - ); - - /** - * Time stamp formatter pattern for intervals in the days range. - */ - protected static final String DAYS_FORMATTER_PATTERN = "dd HH:mm"; //$NON-NLS-1$ - - /** - * Time stamp formatter pattern for intervals in the hours range. - */ - protected static final String HOURS_FORMATTER_PATTERN = "HH:mm"; //$NON-NLS-1$ - - /** - * Time stamp formatter pattern for intervals in the minutes range. - */ - protected static final String MINUTES_FORMATTER_PATTERN = "mm:ss"; //$NON-NLS-1$ - - /** - * Time stamp formatter pattern for intervals in the seconds range. - */ - protected static final String SECONDS_FORMATTER_PATTERN = "ss"; //$NON-NLS-1$ - - /** - * Time stamp formatter pattern for intervals in the milliseconds range. - */ - protected static final String MILLISECONDS_FORMATTER_PATTERN = "ss.SSS"; //$NON-NLS-1$ - - /** - * Decimal formatter factor to display nanoseconds as seconds. - */ - protected static final double NANO_TO_SECS_FORMATTER_FACTOR = 0.000000001; - - /** - * Default decimal formatter. - */ - protected static final DecimalUnitFormat DECIMAL_FORMATTER = new LamiDecimalUnitFormat(); - - /** Symbol for seconds (used in the custom ns -> s conversion) */ - private static final String SECONDS_SYMBOL = "s"; //$NON-NLS-1$ - - /** Symbol for nanoseconds (used in the custom ns -> s conversion) */ - private static final String NANOSECONDS_SYMBOL = "ns"; //$NON-NLS-1$ - - /** Maximum amount of digits that can be represented into a double */ - private static final int BIG_DECIMAL_DIVISION_SCALE = 22; - - private final Listener fResizeListener = event -> { - /* Refresh the titles to fit the current chart size */ - refreshDisplayTitles(); - - /* Refresh the Axis labels to fit the current chart size */ - refreshDisplayLabels(); - }; - - private final LamiChartModel fChartModel; - private final LamiReportViewTabPage fPage; - - private final Chart fChart; - - private final String fChartTitle; - - private String fXLabel; - private @Nullable String fXUnits; - - private String fYLabel; - private @Nullable String fYUnits; - - private boolean fSelected; - private Set fSelection; - - private final ToolBar fToolBar; - - /** - * Creates a Viewer instance based on SWTChart. - * - * @param parent - * The parent composite to draw in. - * @param page - * The {@link LamiReportViewTabPage} parent page - * @param chartModel - * The information about the chart to build - */ - public LamiXYChartViewer(Composite parent, LamiReportViewTabPage page, LamiChartModel chartModel) { - super(parent); - - fParent = parent; - fPage = page; - fChartModel = chartModel; - fSelection = new HashSet<>(); - - fXLabel = ""; //$NON-NLS-1$ - fYLabel = ""; //$NON-NLS-1$ - - fChart = new Chart(parent, SWT.NONE); - fChart.addListener(SWT.Resize, fResizeListener); - - /* Set Chart title */ - fChartTitle = fPage.getResultTable().getTableClass().getTableTitle(); - - /* Set X axis title */ - if (fChartModel.getXSeriesColumns().size() == 1) { - /* - * There is only 1 series in the chart, we will use its name as the - * X axis. - */ - innerSetXTitle(getXAxisAspects().get(0).getName(), getXAxisAspects().get(0).getUnits()); - } else { - /* - * There are multiple series in the chart, if they all share the same - * units, display that. - */ - long nbDiffAspectsUnits = getXAxisAspects().stream() - .map(aspect -> aspect.getUnits()) - .distinct() - .count(); - - long nbDiffAspectName = getXAxisAspects().stream() - .map(aspect -> aspect.getName()) - .distinct() - .count(); - - String xBaseTitle = Messages.LamiViewer_DefaultValueName; - if (nbDiffAspectName == 1) { - xBaseTitle = getXAxisAspects().get(0).getName(); - } - - String units = null; - if (nbDiffAspectsUnits == 1) { - /* All aspects use the same unit type */ - units = getXAxisAspects().get(0).getUnits(); - } - - innerSetXTitle(xBaseTitle, units); - } - - /* Set Y axis title */ - if (fChartModel.getYSeriesColumns().size() == 1) { - /* - * There is only 1 series in the chart, we will use its name as the - * Y axis (and hide the legend). - */ - innerSetYTitle(getYAxisAspects().get(0).getName(), getYAxisAspects().get(0).getUnits()); - - /* Hide the legend */ - fChart.getLegend().setVisible(false); - } else { - /* - * There are multiple series in the chart, if they all share the same - * units, display that. - */ - long nbDiffAspectsUnits = getYAxisAspects().stream() - .map(aspect -> aspect.getUnits()) - .distinct() - .count(); - - long nbDiffAspectName = getYAxisAspects().stream() - .map(aspect -> aspect.getName()) - .distinct() - .count(); - - String yBaseTitle = Messages.LamiViewer_DefaultValueName; - if (nbDiffAspectName == 1) { - yBaseTitle = getYAxisAspects().get(0).getName(); - } - - String units = null; - if (nbDiffAspectsUnits == 1) { - /* All aspects use the same unit type */ - units = getYAxisAspects().get(0).getUnits(); - } - - innerSetYTitle(yBaseTitle, units); - - /* Put legend at the bottom */ - fChart.getLegend().setPosition(SWT.BOTTOM); - } - - /* Set all titles and labels font color to black */ - fChart.getTitle().setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK)); - fChart.getAxisSet().getXAxis(0).getTitle().setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK)); - fChart.getAxisSet().getYAxis(0).getTitle().setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK)); - fChart.getAxisSet().getXAxis(0).getTick().setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK)); - fChart.getAxisSet().getYAxis(0).getTick().setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK)); - - /* Set X label 90 degrees */ - fChart.getAxisSet().getXAxis(0).getTick().setTickLabelAngle(90); - - /* Refresh the titles to fit the current chart size */ - refreshDisplayTitles(); - - fToolBar = createChartToolBar(); - - fChart.addDisposeListener(e -> { - /* Dispose resources of this class */ - LamiXYChartViewer.super.dispose(); - }); - } - - /** - * Set the Y axis title and refresh the chart. - * - * @param label - * the label string. - * @param units - * the units string. - */ - protected void setYTitle(@Nullable String label, @Nullable String units) { - innerSetYTitle(label, units); - } - - private void innerSetYTitle(@Nullable String label, @Nullable String units) { - fYLabel = nullToEmptyString(label); - innerSetYUnits(units); - refreshDisplayTitles(); - } - - /** - * Set the units on the Y Axis title and refresh the chart. - * - * @param units - * the units string. - */ - protected void setYUnits(@Nullable String units) { - innerSetYUnits(units); - } - - private void innerSetYUnits(@Nullable String units) { - /* - * All time durations in the Lami protocol are nanoseconds, on the - * charts we use an axis formater that converts back to seconds as a - * base unit and then uses prefixes like nano and milli depending on the - * range. - * - * So set the units to seconds in the title to match the base unit of - * the formater. - */ - if (NANOSECONDS_SYMBOL.equals(units)) { - fYUnits = SECONDS_SYMBOL; - } else { - fYUnits = units; - } - refreshDisplayTitles(); - } - - /** - * Get the Y axis title string. - * - * If the units is non-null, the title will be: "label (units)" - * - * If the units is null, the title will be: "label" - * - * @return the title of the Y axis. - */ - protected String getYTitle() { - if (fYUnits == null) { - return fYLabel; - } - return fYLabel + " (" + fYUnits + ")"; //$NON-NLS-1$ //$NON-NLS-2$ - } - - /** - * Set the X axis title and refresh the chart. - * - * @param label - * the label string. - * @param units - * the units string. - */ - protected void setXTitle(@Nullable String label, @Nullable String units) { - innerSetXTitle(label, units); - } - - private void innerSetXTitle(@Nullable String label, @Nullable String units) { - fXLabel = nullToEmptyString(label); - innerSetXUnits(units); - refreshDisplayTitles(); - } - - /** - * Set the units on the X Axis title. - * - * @param units - * the units string - */ - protected void setXUnits(@Nullable String units) { - innerSetXUnits(units); - } - - private void innerSetXUnits(@Nullable String units) { - /* The time duration formatter converts ns to s on the axis */ - if (NANOSECONDS_SYMBOL.equals(units)) { - fXUnits = SECONDS_SYMBOL; - } else { - fXUnits = units; - } - refreshDisplayTitles(); - } - - /** - * Get the X axis title string. - * - * If the units is non-null, the title will be: "label (units)" - * - * If the units is null, the title will be: "label" - * - * @return the title of the Y axis. - */ - protected String getXTitle() { - if (fXUnits == null) { - return fXLabel; - } - return fXLabel + " (" + fXUnits + ")"; //$NON-NLS-1$ //$NON-NLS-2$ - } - - /** - * Util method to check if a list of aspects are all continuous. - * - * @param axisAspects - * The list of aspects to check. - * @return true is all aspects are continuous, otherwise false. - */ - protected static boolean areAspectsContinuous(List axisAspects) { - return axisAspects.stream().allMatch(aspect -> aspect.isContinuous()); - } - - /** - * Util method to check if a list of aspects are all time stamps. - * - * @param axisAspects - * The list of aspects to check. - * @return true is all aspects are time stamps, otherwise false. - */ - protected static boolean areAspectsTimeStamp(List axisAspects) { - return axisAspects.stream().allMatch(aspect -> aspect.isTimeStamp()); - } - - /** - * Util method to check if a list of aspects are all time durations. - * - * @param axisAspects - * The list of aspects to check. - * @return true is all aspects are time durations, otherwise false. - */ - protected static boolean areAspectsTimeDuration(List axisAspects) { - return axisAspects.stream().allMatch(aspect -> aspect.isTimeDuration()); - } - - /** - * Util method that will return a formatter based on the aspects linked to an axis - * - * If all aspects are time stamps, return a timestamp formatter tuned to the interval. - * If all aspects are time durations, return the nanoseconds to seconds formatter. - * Otherwise, return the generic decimal formatter. - * - * @param axisAspects - * The list of aspects of the axis. - * @param entries - * The list of entries of the chart. - * @param internalRange - * The internal range for value transformation - * @param externalRange - * The external range for value transformation - * @return a formatter for the axis. - */ - protected static Format getContinuousAxisFormatter(List axisAspects, List entries , @Nullable LamiGraphRange internalRange, @Nullable LamiGraphRange externalRange) { - - Format formatter = null; - - if (areAspectsTimeStamp(axisAspects)) { - /* Set a TimeStamp formatter depending on the duration between the first and last value */ - BigDecimal max = new BigDecimal(Long.MIN_VALUE); - BigDecimal min = new BigDecimal(Long.MAX_VALUE); - - for (LamiTableEntry entry : entries) { - for (LamiTableEntryAspect aspect : axisAspects) { - @Nullable Number number = aspect.resolveNumber(entry); - if (number != null) { - BigDecimal current = new BigDecimal(number.toString()); - max = current.max(max); - min = current.min(min); - } - } - } - - long duration = max.subtract(min).longValue(); - if (duration > TimeUnit.DAYS.toNanos(1)) { - formatter = new LamiTimeStampFormat(DAYS_FORMATTER_PATTERN, internalRange, externalRange); - } else if (duration > TimeUnit.HOURS.toNanos(1)) { - formatter = new LamiTimeStampFormat(HOURS_FORMATTER_PATTERN, internalRange, externalRange); - } else if (duration > TimeUnit.MINUTES.toNanos(1)) { - formatter = new LamiTimeStampFormat(MINUTES_FORMATTER_PATTERN, internalRange, externalRange); - } else if (duration > TimeUnit.SECONDS.toNanos(15)) { - formatter = new LamiTimeStampFormat(SECONDS_FORMATTER_PATTERN, internalRange, externalRange); - } else { - formatter = new LamiTimeStampFormat(MILLISECONDS_FORMATTER_PATTERN, internalRange, externalRange); - } - } else if (areAspectsTimeDuration(axisAspects)) { - /* Set the time duration formatter. */ - formatter = new LamiDecimalUnitFormat(NANO_TO_SECS_FORMATTER_FACTOR, internalRange, externalRange); - } else { - /* - * For other numeric aspects, use the default lami decimal unit - * formatter. - */ - formatter = new LamiDecimalUnitFormat(internalRange, externalRange); - } - - return formatter; - } - - /** - * Get the chart result table. - * - * @return The chart result table. - */ - protected LamiResultTable getResultTable() { - return fPage.getResultTable(); - } - - /** - * Get the chart {@code LamiReportViewTabPage} parent. - * - * @return The {@code LamiReportViewTabPage} parent. - */ - protected LamiReportViewTabPage getPage() { - return fPage; - } - - /** - * Get the chart model. - * - * @return The chart model. - */ - protected LamiChartModel getChartModel() { - return fChartModel; - } - - /** - * Get the chart object. - * @return The chart object. - */ - protected Chart getChart() { - return fChart; - } - - /** - * @return the toolBar - */ - public ToolBar getToolBar() { - return fToolBar; - } - - /** - * Is a selection made in the chart. - * - * @return true if there is a selection. - */ - protected boolean isSelected() { - return fSelected; - } - - /** - * Set the selection index. - * - * @param selection the index to select. - */ - protected void setSelection(Set selection) { - fSelection = selection; - fSelected = !selection.isEmpty(); - } - - /** - * Unset the chart selection. - */ - protected void unsetSelection() { - fSelection.clear(); - fSelected = false; - } - - /** - * Get the current selection index. - * - * @return the current selection index. - */ - protected Set getSelection() { - return fSelection; - } - - @Override - public @Nullable Control getControl() { - return fChart.getParent(); - } - - @Override - public void refresh() { - Display.getDefault().asyncExec(() -> { - if (!fChart.isDisposed()) { - fChart.redraw(); - } - }); - } - - @Override - public void dispose() { - fChart.dispose(); - /* The control's DisposeListener will call super.dispose() */ - } - - /** - * Get a list of all the aspect of the Y axis. - * - * @return The aspects for the Y axis - */ - protected List getYAxisAspects() { - - List yAxisAspects = new ArrayList<>(); - - for (String colName : getChartModel().getYSeriesColumns()) { - yAxisAspects.add(checkNotNull(getAspectFromName(getResultTable().getTableClass().getAspects(), colName))); - } - - return yAxisAspects; - } - - /** - * Get a list of all the aspect of the X axis. - * - * @return The aspects for the X axis - */ - protected List getXAxisAspects() { - - List xAxisAspects = new ArrayList<>(); - - for (String colName : getChartModel().getXSeriesColumns()) { - xAxisAspects.add(checkNotNull(getAspectFromName(getResultTable().getTableClass().getAspects(), colName))); - } - - return xAxisAspects; - } - - /** - * Set the ITitle object text to a substring of canonicalTitle that when - * rendered in the chart will fit maxPixelLength. - */ - private void refreshDisplayTitle(ITitle title, String canonicalTitle, int maxPixelLength) { - if (title.isVisible()) { - - String newTitle = canonicalTitle; - - /* Get the title font */ - Font font = title.getFont(); - - GC gc = new GC(fParent); - gc.setFont(font); - - /* Get the length and height of the canonical title in pixels */ - Point pixels = gc.stringExtent(canonicalTitle); - - /* - * If the title is too long, generate a shortened version based on the - * average character width of the current font. - */ - if (pixels.x > maxPixelLength) { - int charwidth = gc.getFontMetrics().getAverageCharWidth(); - - int minimum = 3; - - int strLen = ((maxPixelLength / charwidth) - minimum); - - if (strLen > minimum) { - newTitle = canonicalTitle.substring(0, strLen) + ELLIPSIS; - } else { - newTitle = ELLIPSIS; - } - } - - title.setText(newTitle); - - // Cleanup - gc.dispose(); - } - } - - /** - * Refresh the Chart, XAxis and YAxis titles to fit the current - * chart size. - */ - private void refreshDisplayTitles() { - Rectangle chartRect = fChart.getClientArea(); - Rectangle plotRect = fChart.getPlotArea().getClientArea(); - - ITitle chartTitle = checkNotNull(fChart.getTitle()); - refreshDisplayTitle(chartTitle, fChartTitle, chartRect.width); - - ITitle xTitle = checkNotNull(fChart.getAxisSet().getXAxis(0).getTitle()); - refreshDisplayTitle(xTitle, getXTitle(), plotRect.width); - - ITitle yTitle = checkNotNull(fChart.getAxisSet().getYAxis(0).getTitle()); - refreshDisplayTitle(yTitle, getYTitle(), plotRect.height); - } - - /** - * Get the aspect with the given name - * - * @param aspects - * The list of aspects to search into - * @param aspectName - * The name of the aspect we are looking for - * @return The corresponding aspect - */ - protected static @Nullable LamiTableEntryAspect getAspectFromName(List aspects, String aspectName) { - for (LamiTableEntryAspect lamiTableEntryAspect : aspects) { - - if (lamiTableEntryAspect.getLabel().equals(aspectName)) { - return lamiTableEntryAspect; - } - } - - return null; - } - - /** - * Refresh the axis labels to fit the current chart size. - */ - protected abstract void refreshDisplayLabels(); - - /** - * Redraw the chart. - */ - protected void redraw() { - refresh(); - } - - /** - * Signal handler for selection update. - * - * @param signal - * The selection update signal - */ - @TmfSignalHandler - public void updateSelection(LamiSelectionUpdateSignal signal) { - if (getPage() != signal.getSignalKey() || equals(signal.getSource())) { - /* The signal is not for us */ - return; - } - setSelection(signal.getEntryIndex()); - - redraw(); - } - - /** - * Create a tool bar on top right of the chart. Contained actions: - *
    - *
  • Dispose the current viewer, also known as "Close the chart"
  • - *
- * - * This tool bar should only appear when the mouse enters the composite. - * - * @return the tool bar - */ - protected ToolBar createChartToolBar() { - Image removeImage = PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_ELCL_REMOVE); - ToolBar toolBar = new ToolBar(getChart(), SWT.HORIZONTAL); - - /* Default state */ - toolBar.moveAbove(null); - toolBar.setVisible(false); - - /* - * Close chart button - */ - ToolItem closeButton = new ToolItem(toolBar, SWT.PUSH); - closeButton.setImage(removeImage); - closeButton.setToolTipText(Messages.LamiXYChartViewer_CloseChartToolTip); - closeButton.addSelectionListener(new SelectionListener() { - @Override - public void widgetSelected(@Nullable SelectionEvent e) { - Composite parent = getParent(); - dispose(); - parent.layout(); - } - - @Override - public void widgetDefaultSelected(@Nullable SelectionEvent e) { - } - }); - - toolBar.pack(); - toolBar.setLocation(new Point(getChart().getSize().x - toolBar.getSize().x, 0)); - - /* Visibility toggle filter */ - Listener toolBarVisibilityToggleListener = e -> { - if (e.widget instanceof Control) { - Control control = (Control) e.widget; - Point display = control.toDisplay(e.x, e.y); - Point location = getChart().getParent().toControl(display); - - /* - * Only set to visible if we are at the right location, in the - * right shell. - */ - boolean visible = getChart().getBounds().contains(location) && - control.getShell().equals(getChart().getShell()); - getToolBar().setVisible(visible); - } - }; - - /* Filter to make sure we hide the toolbar if we exit the window */ - Listener hideToolBarListener = (e -> getToolBar().setVisible(false)); - - /* - * Add the filters to the main Display, and remove them when we dispose - * the chart. - */ - Display display = getChart().getDisplay(); - display.addFilter(SWT.MouseEnter, toolBarVisibilityToggleListener); - display.addFilter(SWT.MouseExit, hideToolBarListener); - - getChart().addDisposeListener(e -> { - display.removeFilter(SWT.MouseEnter, toolBarVisibilityToggleListener); - display.removeFilter(SWT.MouseExit, hideToolBarListener); - }); - - /* Reposition the tool bar on resize */ - getChart().addListener(SWT.Resize, new Listener() { - @Override - public void handleEvent(@Nullable Event event) { - toolBar.setLocation(new Point(getChart().getSize().x - toolBar.getSize().x, 0)); - } - }); - - return toolBar; - } - - /** - * Get a {@link LamiGraphRange} that covers all data points in the result - * table. - *

- * The returned range will be the minimum and maximum of the resolved values - * of the passed aspects for all result entries. If clampToZero - * is true, a positive minimum value will be clamped down to zero. - * - * @param aspects - * The aspects that the range will represent - * @param clampToZero - * If true, a positive minimum value will be clamped down to zero - * @return the range - */ - protected LamiGraphRange getRange(List aspects, boolean clampToZero) { - /* Find the minimum and maximum values */ - BigDecimal min = new BigDecimal(Long.MAX_VALUE); - BigDecimal max = new BigDecimal(Long.MIN_VALUE); - for (LamiTableEntryAspect lamiTableEntryAspect : aspects) { - for (LamiTableEntry entry : getResultTable().getEntries()) { - @Nullable Number number = lamiTableEntryAspect.resolveNumber(entry); - if (number != null) { - BigDecimal current = new BigDecimal(number.toString()); - min = current.min(min); - max = current.max(max); - } - } - } - - if (clampToZero) { - min = min.min(BigDecimal.ZERO); - } - - /* Do not allow a range with a zero delta default to 1 */ - if (max.equals(min)) { - max = min.add(BigDecimal.ONE); - } - - return new LamiGraphRange(checkNotNull(min), checkNotNull(max)); - } - - /** - * Transform an external value into an internal value. Since SWTChart only - * support Double and Lami can pass Long values, loss of precision might - * happen. To minimize this, transform the raw values to an internal - * representation based on a linear transformation. - * - * The internal value = - * - * ((rawValue - rawMinimum) * (internalRangeDelta/rawRangeDelta)) + - * internalMinimum - * - * @param number - * The number to transform - * @param internalRange - * The internal range definition to be used - * @param externalRange - * The external range definition to be used - * @return the transformed value in Double comprised inside the internal - * range - */ - protected static double getInternalDoubleValue(Number number, LamiGraphRange internalRange, LamiGraphRange externalRange) { - BigDecimal value = new BigDecimal(number.toString()); - - if (externalRange.getDelta().compareTo(BigDecimal.ZERO) == 0) { - return internalRange.getMinimum().doubleValue(); - } - - BigDecimal internalValue = value - .subtract(externalRange.getMinimum()) - .multiply(internalRange.getDelta()) - .divide(externalRange.getDelta(), BIG_DECIMAL_DIVISION_SCALE, BigDecimal.ROUND_DOWN) - .add(internalRange.getMinimum()); - - return internalValue.doubleValue(); - } -} diff --git a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/viewers/Messages.java b/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/viewers/Messages.java deleted file mode 100644 index 6461df7195..0000000000 --- a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/viewers/Messages.java +++ /dev/null @@ -1,38 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015, 2016 EfficiOS Inc., Alexandre Montplaisir - * - * 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.provisional.analysis.lami.ui.viewers; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.osgi.util.NLS; - -/** - * Message bundle for the package - * - * @noreference Messages class - */ -@NonNullByDefault({}) -@SuppressWarnings("javadoc") -public class Messages extends NLS { - - private static final String BUNDLE_NAME = Messages.class.getPackage().getName() + ".messages"; //$NON-NLS-1$ - - public static String LamiScatterViewer_by; - - public static String LamiXYChartViewer_CloseChartToolTip; - - public static String LamiViewer_DefaultValueName; - - static { - NLS.initializeMessages(BUNDLE_NAME, Messages.class); - } - - private Messages() { - } -} diff --git a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/viewers/messages.properties b/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/viewers/messages.properties deleted file mode 100644 index 163eb5dbe9..0000000000 --- a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/viewers/messages.properties +++ /dev/null @@ -1,13 +0,0 @@ -############################################################################### -# 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 -############################################################################### - - -LamiScatterViewer_by = by -LamiXYChartViewer_CloseChartToolTip = Close chart -LamiViewer_DefaultValueName = Value diff --git a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/views/LamiReportView.java b/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/views/LamiReportView.java index f324538110..753b944ef2 100644 --- a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/views/LamiReportView.java +++ b/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/views/LamiReportView.java @@ -27,7 +27,6 @@ import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.widgets.Composite; import org.eclipse.tracecompass.internal.analysis.lami.ui.Activator; import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiAnalysisReport; -import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiChartModel.LamiChartType; import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiResultTable; import org.eclipse.tracecompass.tmf.ui.views.TmfView; @@ -68,24 +67,6 @@ public final class LamiReportView extends TmfView { } } - private class NewChartAction extends Action { - - private final LamiChartType fChartType; - - public NewChartAction(LamiChartType chartType) { - fChartType = chartType; - } - - @Override - public void run() { - LamiReportViewTabPage page = getCurrentSelectedPage(); - if (page == null) { - return; - } - page.createNewCustomChart(fChartType); - } - } - private class NewCustomChartAction extends Action { @Override @@ -148,11 +129,6 @@ public final class LamiReportView extends TmfView { toolbarMgr.add(toggleTableAction); IMenuManager menuMgr = getViewSite().getActionBars().getMenuManager(); - IAction newBarChartAction = new NewChartAction(LamiChartType.BAR_CHART); - IAction newXYScatterAction = new NewChartAction(LamiChartType.XY_SCATTER); - - newBarChartAction.setText(Messages.LamiReportView_NewCustomBarChart); - newXYScatterAction.setText(Messages.LamiReportView_NewCustomScatterChart); IAction newChartAction = new NewCustomChartAction(); newChartAction.setText(Messages.LamiReportView_NewCustomChart); @@ -170,8 +146,6 @@ public final class LamiReportView extends TmfView { }; clearCustomViewsAction.setText(Messages.LamiReportView_ClearAllCustomViews); - menuMgr.add(newBarChartAction); - menuMgr.add(newXYScatterAction); menuMgr.add(newChartAction); menuMgr.add(new Separator()); menuMgr.add(clearCustomViewsAction); diff --git a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/views/LamiReportViewTabPage.java b/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/views/LamiReportViewTabPage.java index f75a85078d..0e369d2a52 100644 --- a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/views/LamiReportViewTabPage.java +++ b/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/views/LamiReportViewTabPage.java @@ -9,40 +9,19 @@ package org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.views; -import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull; -import static org.eclipse.tracecompass.common.core.NonNullUtils.nullToEmptyString; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashSet; -import java.util.List; import java.util.Set; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.jface.viewers.ArrayContentProvider; -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.LabelProvider; + import org.eclipse.jface.window.Window; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Shell; -import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.aspect.LamiEmptyAspect; -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.LamiChartType; 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.core.module.LamiXYSeriesDescription; import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.types.LamiTimeRange; -import org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.signals.LamiSelectionUpdateSignal; import org.eclipse.tracecompass.internal.provisional.tmf.chart.core.chart.ChartData; import org.eclipse.tracecompass.internal.provisional.tmf.chart.core.chart.ChartModel; import org.eclipse.tracecompass.internal.provisional.tmf.chart.core.signal.ChartSelectionUpdateSignal; -import org.eclipse.tracecompass.internal.provisional.tmf.chart.ui.chart.IChartViewer; import org.eclipse.tracecompass.internal.provisional.tmf.chart.ui.dialog.ChartMakerDialog; import org.eclipse.tracecompass.tmf.core.component.TmfComponent; import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal; @@ -75,9 +54,6 @@ public final class LamiReportViewTabPage extends TmfComponent { private final Set fCustomGraphViewerControls = new LinkedHashSet<>(); private final Composite fControl; - private Set fSelectionIndexes; - - private @Nullable IChartViewer fChart; private Set fSelection; // ------------------------------------------------------------------------ @@ -96,8 +72,6 @@ public final class LamiReportViewTabPage extends TmfComponent { super(table.getTableClass().getTableTitle()); fResultTable = table; - fSelectionIndexes = new HashSet<>(); - fSelectionIndexes = getIndexOfEntriesIntersectingTimerange(checkNotNull(fResultTable), TmfTraceManager.getInstance().getCurrentTraceContext().getSelectionRange()); fControl = parent; @@ -112,8 +86,6 @@ public final class LamiReportViewTabPage extends TmfComponent { fTableViewerControl.getToggleAction().run(); /* Simulate a new external signal to the default viewer */ - LamiSelectionUpdateSignal signal = new LamiSelectionUpdateSignal(LamiReportViewTabPage.this, fSelectionIndexes, this); - TmfSignalManager.dispatchSignal(signal); ChartSelectionUpdateSignal chartSignal = new ChartSelectionUpdateSignal(this, fResultTable, fSelection); TmfSignalManager.dispatchSignal(chartSignal); @@ -164,11 +136,15 @@ public final class LamiReportViewTabPage extends TmfComponent { } /* Make a chart with the factory constructor */ - fChart = IChartViewer.createChart(fControl, data, model); + LamiViewerControl viewerControl = new LamiViewerControl(fControl, data, model); + fCustomGraphViewerControls.add(viewerControl); + viewerControl.getToggleAction().run(); /* Signal the current selection to the newly created graph */ ChartSelectionUpdateSignal signal = new ChartSelectionUpdateSignal(LamiReportViewTabPage.this, fResultTable, fSelection); TmfSignalManager.dispatchSignal(signal); + + } /** @@ -209,282 +185,10 @@ public final class LamiReportViewTabPage extends TmfComponent { return fResultTable; } - /** - * Add a new chart viewer to this tab. - * - * The method only needs a chart type (currently selected via separate - * actions), all other information will be found in the result table or in - * dialogs shown to the user as part of the execution of this method. - * - * @param chartType - * The type of chart to create - */ - public void createNewCustomChart(LamiChartType chartType) { - int xLogScaleOptionIndex = -1; - int yLogScaleOptionIndex = -1; - - List xStringColumn = fResultTable.getTableClass().getAspects().stream() - .filter(aspect -> !(aspect instanceof LamiEmptyAspect)) - .collect(Collectors.toList()); - - /* Get the flattened aspects for Y since mapping an aggregate aspect to y series make no sense so far */ - List yStringColumn = fResultTable.getTableClass().getAspects().stream() - .filter(aspect -> !(aspect instanceof LamiEmptyAspect)) - .collect(Collectors.toList()); - - switch (chartType) { - case BAR_CHART: - /* Y value must strictly continous and non timestamp */ - yStringColumn = yStringColumn.stream() - .filter(aspect -> !aspect.isTimeStamp() && aspect.isContinuous()) - .collect(Collectors.toList()); - break; - case PIE_CHART: - break; - case XY_SCATTER: - break; - default: - break; - } - - IStructuredContentProvider contentProvider = checkNotNull(ArrayContentProvider.getInstance()); - - LamiSeriesDialog dialog = new LamiSeriesDialog(getControl().getShell(), - chartType, - xStringColumn, - yStringColumn, - contentProvider, - new LabelProvider() { - @Override - public String getText(@Nullable Object element) { - return ((LamiTableEntryAspect) checkNotNull(element)).getLabel(); - } - }, - contentProvider, - new LabelProvider() { - @Override - public String getText(@Nullable Object element) { - return ((LamiTableEntryAspect) checkNotNull(element)).getLabel(); - } - }); - dialog.setTitle(chartType.toString() + ' ' + Messages.LamiSeriesDialog_creation); - - /* X options per chart type */ - switch (chartType) { - case XY_SCATTER: - xLogScaleOptionIndex = dialog.addXCheckBoxOption( - Messages.LamiSeriesDialog_x_axis + ' ' + Messages.LamiReportView_LogScale, - false, new Predicate() { - @Override - public boolean test(@NonNull LamiTableEntryAspect t) { - return t.isContinuous() && !t.isTimeStamp(); - } - }); - break; - case BAR_CHART: - case PIE_CHART: - default: - break; - } - - /* Y options per chart type */ - switch (chartType) { - case BAR_CHART: - case XY_SCATTER: - yLogScaleOptionIndex = dialog.addYCheckBoxOption( - Messages.LamiSeriesDialog_y_axis + ' ' + Messages.LamiReportView_LogScale, - false, new Predicate() { - @Override - public boolean test(@NonNull LamiTableEntryAspect t) { - return t.isContinuous() && !t.isTimeStamp(); - } - }); - break; - - case PIE_CHART: - default: - break; - } - - if (dialog.open() != Window.OK) { - return; - } - - List results = Arrays.stream(dialog.getResult()) - .map(serie -> (LamiXYSeriesDescription) serie) - .collect(Collectors.toList()); - - boolean[] xCheckBoxOptionsResults = dialog.getXCheckBoxOptionValues(); - boolean[] yCheckBoxOptionsResults = dialog.getYCheckBoxOptionValues(); - - boolean isXLogScale = false; - boolean isYLogScale = false; - - /* Get X log scale option */ - if (xLogScaleOptionIndex > -1 && xLogScaleOptionIndex < xCheckBoxOptionsResults.length) { - isXLogScale = xCheckBoxOptionsResults[xLogScaleOptionIndex]; - } - /* Get Y log scale option */ - if (yLogScaleOptionIndex > -1 && yLogScaleOptionIndex < yCheckBoxOptionsResults.length) { - isYLogScale = yCheckBoxOptionsResults[yLogScaleOptionIndex]; - } - - List xAxisColString = new ArrayList<>(); - List yAxisColString = new ArrayList<>(); - - /* Specific chart type result fetching */ - switch (chartType) { - case PIE_CHART: - case BAR_CHART: - /* Validate that we only have 1 X aspect */ - if (results.stream() - .map(element -> element.getXAspect().getLabel()) - .distinct() - .count() != 1) { - throw new IllegalStateException(); - } - xAxisColString = results.stream() - .map(element -> element.getXAspect().getLabel()) - .distinct() - .collect(Collectors.toList()); - break; - case XY_SCATTER: - xAxisColString = results.stream() - .map(element -> element.getXAspect().getLabel()) - .collect(Collectors.toList()); - break; - default: - break; - } - - yAxisColString = results.stream() - .map(element -> element.getYAspect().getLabel()) - .collect(Collectors.toList()); - - LamiChartModel model = new LamiChartModel(chartType, - nullToEmptyString(Messages.LamiReportView_Custom), - xAxisColString, - yAxisColString, - isXLogScale, - isYLogScale); - - LamiViewerControl viewerControl = new LamiViewerControl(fControl, this, model); - fCustomGraphViewerControls.add(viewerControl); - viewerControl.getToggleAction().run(); - - /* Signal the current selection to the newly created graph */ - LamiSelectionUpdateSignal signal = new LamiSelectionUpdateSignal(LamiReportViewTabPage.this, - fSelectionIndexes, this); - TmfSignalManager.dispatchSignal(signal); - } - // ------------------------------------------------------------------------ // Signals // ------------------------------------------------------------------------ - // Lami signals - /** - * Signal handler for selection update. - * Propagate a TmfSelectionRangeUpdatedSignal if possible. - * - * @param signal - * The selection update signal - */ - @TmfSignalHandler - public void updateSelection(LamiSelectionUpdateSignal signal) { - LamiResultTable table = fResultTable; - Object source = signal.getSource(); - - /* - * Don't forward signals from other tab pages, especially those - * from other views/tab page. - */ - if (this != signal.getSignalKey() || - this == source || - source instanceof LamiReportViewTabPage) { - /* The signal is not for us */ - return; - } - - Set entryIndex = signal.getEntryIndex(); - - /* - * Since most of the external viewer deal only with continuous timerange and do not allow multi time range - * selection simply signal only when only one selection is present. - */ - - if (entryIndex.isEmpty()) { - /* - * In an ideal world we would send a null signal to reset all view - * and simply show no selection. But since this is Tracecompass - * there is no notion of "unselected state" in most of the viewers so - * we do not update/clear the last timerange and show false information to the user. - */ - ChartSelectionUpdateSignal customSignal = new ChartSelectionUpdateSignal(LamiReportViewTabPage.this, fResultTable, Collections.EMPTY_SET); - TmfSignalManager.dispatchSignal(customSignal); - return; - } - - if (entryIndex.size() == 1) { - int index = Iterables.getOnlyElement(entryIndex).intValue(); - LamiTimeRange timeRange = table.getEntries().get(index).getCorrespondingTimeRange(); - if (timeRange != null) { - /* Send Range update to other views */ - // TODO: Consider low and high limits of timestamps here. - Number tsBeginValueNumber = timeRange.getBegin().getValue(); - Number tsEndValueNumber = timeRange.getEnd().getValue(); - - if (tsBeginValueNumber != null && tsEndValueNumber != null) { - ITmfTimestamp start = TmfTimestamp.fromNanos(tsBeginValueNumber.longValue()); - ITmfTimestamp end = TmfTimestamp.fromNanos(tsEndValueNumber.longValue()); - TmfSignalManager.dispatchSignal(new TmfSelectionRangeUpdatedSignal(LamiReportViewTabPage.this, start, end)); - } - } - } - - fSelectionIndexes = entryIndex; - - // Create the signal for the custom chart - List entries = fResultTable.getEntries(); - Set selectionSet = new HashSet<>(); - for (Integer selectionIndex : entryIndex) { - selectionSet.add(entries.get(selectionIndex)); - } - fSelection = selectionSet; - ChartSelectionUpdateSignal customSignal = new ChartSelectionUpdateSignal(LamiReportViewTabPage.this, fResultTable, selectionSet); - TmfSignalManager.dispatchSignal(customSignal); - -// /* Update all LamiViewer */ -// LamiSelectionUpdateSignal signal1 = new LamiSelectionUpdateSignal(LamiReportViewTabPage.this, selections, this); -// TmfSignalManager.dispatchSignal(signal1); - } - - private static Set getIndexOfEntriesIntersectingTimerange(LamiResultTable table, TmfTimeRange range) { - Set selections = new HashSet<>(); - for (LamiTableEntry entry : table.getEntries()) { - LamiTimeRange timerange = entry.getCorrespondingTimeRange(); - if (timerange == null) { - /* Return since the table have no timerange */ - return selections; - } - - // TODO: Consider low and high limits of timestamps here. - Number tsBeginValueNumber = timerange.getBegin().getValue(); - Number tsEndValueNumber = timerange.getEnd().getValue(); - - if (tsBeginValueNumber != null && tsEndValueNumber != null) { - ITmfTimestamp start = TmfTimestamp.fromNanos(tsBeginValueNumber.longValue()); - ITmfTimestamp end = TmfTimestamp.fromNanos(tsEndValueNumber.longValue()); - - TmfTimeRange tempTimeRange = new TmfTimeRange(start, end); - if (tempTimeRange.getIntersection(range) != null) { - selections.add(table.getEntries().indexOf(entry)); - } - } - } - return selections; - } - // Custom chart signals /** * Signal handler for a chart selection update. It will try to propagate a @@ -495,10 +199,6 @@ public final class LamiReportViewTabPage extends TmfComponent { */ @TmfSignalHandler public void updateSelection(ChartSelectionUpdateSignal signal) { - IChartViewer chart = fChart; - if (chart == null) { - return; - } /* Make sure we are not sending a signal to ourself */ if (signal.getSource() == this) { @@ -513,40 +213,9 @@ public final class LamiReportViewTabPage extends TmfComponent { /* Find which index row has been selected */ Set entries = signal.getSelectedObject(); - /* - * Since most of the external viewer deal only with continuous timerange - * and do not allow multi time range selection simply signal only when - * only one selection is present. - */ - if (entries.isEmpty()) { - /* - * In an ideal world we would send a null signal to reset all view - * and simply show no selection. But since this is Tracecompass - * there is no notion of "unselected state" in most of the viewers - * so we do not update/clear the last timerange and show false - * information to the user. - */ - /* Signal all Lami viewers & views of the selection */ - LamiSelectionUpdateSignal lamiSignal = new LamiSelectionUpdateSignal(LamiReportViewTabPage.this, Collections.EMPTY_SET, this); - TmfSignalManager.dispatchSignal(lamiSignal); - return; - } - /* Update the selection */ fSelection = entries; - // Create the signal for the LAMI selection - Set selectionIndexes = new HashSet<>(); - for (Object entry : entries ) { - selectionIndexes.add(fResultTable.getEntries().indexOf(entry)); - } - - fSelectionIndexes = selectionIndexes; - - /* Signal all Lami viewers & views of the selection */ - LamiSelectionUpdateSignal lamiSignal = new LamiSelectionUpdateSignal(LamiReportViewTabPage.this, selectionIndexes, this); - TmfSignalManager.dispatchSignal(lamiSignal); - /* Only propagate to all TraceCompass if there is a single selection */ if (entries.size() == 1) { LamiTableEntry entry = (LamiTableEntry) Iterables.getOnlyElement(entries); @@ -591,13 +260,6 @@ public final class LamiReportViewTabPage extends TmfComponent { TmfTimeRange range = new TmfTimeRange(signal.getBeginTime(), signal.getEndTime()); - // Lami signal - Set selections = getIndexOfEntriesIntersectingTimerange(fResultTable, range); - - /* Update all LamiViewer */ - LamiSelectionUpdateSignal signal1 = new LamiSelectionUpdateSignal(LamiReportViewTabPage.this, selections, this); - TmfSignalManager.dispatchSignal(signal1); - // Custom chart signal /* Find which lami table entry intersects the signal */ Set selection = getEntriesIntersectingTimerange(fResultTable, range); diff --git a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/views/LamiSeriesDialog.java b/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/views/LamiSeriesDialog.java deleted file mode 100644 index c5271ae5ce..0000000000 --- a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/views/LamiSeriesDialog.java +++ /dev/null @@ -1,510 +0,0 @@ -/******************************************************************************* - * 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.provisional.analysis.lami.ui.views; - -import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.function.Function; -import java.util.function.Predicate; - -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.jface.dialogs.Dialog; -import org.eclipse.jface.dialogs.IDialogConstants; -import org.eclipse.jface.layout.TableColumnLayout; -import org.eclipse.jface.viewers.ArrayContentProvider; -import org.eclipse.jface.viewers.CheckboxTableViewer; -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.jface.viewers.ColumnWeightData; -import org.eclipse.jface.viewers.ILabelProvider; -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.jface.viewers.TableViewerColumn; -import org.eclipse.swt.SWT; -import org.eclipse.swt.custom.SashForm; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -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.TableColumn; -import org.eclipse.swt.widgets.TableItem; -import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.aspect.LamiTableEntryAspect; -import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiChartModel.LamiChartType; -import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiXYSeriesDescription; -import org.eclipse.ui.dialogs.SelectionDialog; - -/** - * Series creation dialog - * - * @author Jonathan Rajotte-Julien - */ -public class LamiSeriesDialog extends SelectionDialog { - - private static final int MINIMUM_COLUMN_WIDTH = 30; - private static final int MININAL_SERIES_TABLE_HEIGHT = 150; - - /* The root element to populate the viewer with */ - private final Object fXInputElement; - private final Object fYInputElement; - private final List series; - - /* Providers for populating dialog */ - private final ILabelProvider fXLabelProvider; - private final IStructuredContentProvider fXContentProvider; - private final ILabelProvider fYLabelProvider; - private final IStructuredContentProvider fYContentProvider; - private final IStructuredContentProvider fSeriesContentProvider; - - private final boolean fRestrictXSeriesNumbers; - - private final List fXCheckBoxOptions; - private final List fYCheckBoxOptions; - - // the visual selection widget group - private TableViewer fXTableViewer; - private CheckboxTableViewer fYCheckBoxViewer; - private TableViewer fSeriesListViewer; - - private Label fWarning; - - /** - * @param parentShell - * The parent shell of the dialog - * @param chartType - * The chart type for which the dialog construct series - * @param xInput - * The possible X axis set of values - * @param yInput - * The possible Y axis set of values - * @param xContentProvider - * A content provider for the X axis set - * @param xLabelProvider - * The label provider for the X axis set - * @param yContentProvider - * The content provider for the Y axis set - * @param yLabelProvider - * The label provider for the Y axis set - */ - public LamiSeriesDialog(Shell parentShell, LamiChartType chartType, Object xInput, - Object yInput, - IStructuredContentProvider xContentProvider, - ILabelProvider xLabelProvider, - IStructuredContentProvider yContentProvider, - ILabelProvider yLabelProvider) { - super(parentShell); - fXInputElement = xInput; - fYInputElement = yInput; - fXContentProvider = xContentProvider; - fXLabelProvider = xLabelProvider; - fYContentProvider = yContentProvider; - fYLabelProvider = yLabelProvider; - series = new ArrayList<>(); - fSeriesContentProvider = checkNotNull(ArrayContentProvider.getInstance()); - - fXCheckBoxOptions = new ArrayList<>(); - fYCheckBoxOptions = new ArrayList<>(); - fSeriesListViewer = new TableViewer(parentShell); - fXTableViewer = new TableViewer(parentShell); - fYCheckBoxViewer = checkNotNull(CheckboxTableViewer.newCheckList(parentShell, SWT.NONE)); - - /* Dynamic restriction per chart type */ - switch (chartType) { - case XY_SCATTER: - fRestrictXSeriesNumbers = false; - break; - case BAR_CHART: - case PIE_CHART: - default: - fRestrictXSeriesNumbers = true; - break; - } - - this.fWarning = new Label(parentShell, SWT.NONE); - } - - @Override - protected Control createDialogArea(@Nullable Composite parent) { - - Composite composite = (Composite) super.createDialogArea(parent); - initializeDialogUnits(composite); - - /* Base 3 column grid layout */ - GridLayout gridLayout = new GridLayout(3, false); - composite.setLayout(gridLayout); - - GridData gridData = new GridData(GridData.FILL_BOTH); - gridData.horizontalSpan = 3; - Group seriesGroup = new Group(composite, SWT.NONE); - seriesGroup.setLayoutData(gridData); - seriesGroup.setLayout(new GridLayout(3, false)); - seriesGroup.setText(Messages.LamiSeriesDialog_series); - - /* - * New sub group for the series table. - */ - gridData = new GridData(GridData.FILL_BOTH); - gridData.horizontalSpan = 2; - gridData.heightHint = MININAL_SERIES_TABLE_HEIGHT; - Group seriesTableGroup = new Group(seriesGroup, SWT.NONE); - seriesTableGroup.setLayoutData(gridData); - TableColumnLayout layout = new TableColumnLayout(); - seriesTableGroup.setLayout(layout); - - /* Current series */ - fSeriesListViewer = new TableViewer(seriesTableGroup, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); - fSeriesListViewer.setContentProvider(fSeriesContentProvider); - fSeriesListViewer.setInput(series); - fSeriesListViewer.getTable().setHeaderVisible(true); - fSeriesListViewer.getTable().setLinesVisible(true); - TableViewerColumn column1 = createTableViewerColumn(fSeriesListViewer, Messages.LamiSeriesDialog_x_values, element -> element.getXAspect().getLabel()); - TableViewerColumn column2 = createTableViewerColumn(fSeriesListViewer, Messages.LamiSeriesDialog_y_values, element -> element.getYAspect().getLabel()); - layout.setColumnData(column1.getColumn(), new ColumnWeightData(1, MINIMUM_COLUMN_WIDTH, true)); - layout.setColumnData(column2.getColumn(), new ColumnWeightData(1, MINIMUM_COLUMN_WIDTH, true)); - - /* Delete series button */ - gridData = new GridData(GridData.CENTER); - gridData.horizontalSpan = 1; - Button deleteSeries = new Button(seriesGroup, SWT.PUSH); - deleteSeries.setText(Messages.LamiSeriesDialog_delete); - deleteSeries.setLayoutData(gridData); - deleteSeries.addSelectionListener(new SelectionListener() { - @Override - public void widgetSelected(@Nullable SelectionEvent e) { - /* Remove the selectecd series */ - IStructuredSelection selections = (IStructuredSelection) fSeriesListViewer.getSelection(); - for (Object selection : selections.toList()) { - series.remove(selection); - } - /* When table is empty reset to initial state */ - if (series.isEmpty()) { - /* Make sure the OK button is disabled */ - getButton(IDialogConstants.OK_ID).setEnabled(false); - /* Hide the selection warning */ - fWarning.setVisible(false); - - /* - * Reset the initial selection of the X axis selection table - */ - fXTableViewer.refresh(); - /* Reset check boxes options */ - fXCheckBoxOptions.forEach(checkBox -> { - checkBox.setButtonEnabled(true); - }); - fYCheckBoxOptions.forEach(checkBox -> { - checkBox.setButtonEnabled(true); - }); - } - /* Refresh the series table to show the added series */ - fSeriesListViewer.refresh(); - } - - @Override - public void widgetDefaultSelected(@Nullable SelectionEvent e) { - } - }); - - /* - * Series creator subgroup - */ - gridData = new GridData(GridData.FILL_BOTH); - gridData.horizontalSpan = 3; - Group seriesCreatorGroup = new Group(composite, getShellStyle()); - seriesCreatorGroup.setLayoutData(gridData); - seriesCreatorGroup.setLayout(new GridLayout(3, false)); - seriesCreatorGroup.setText(Messages.LamiSeriesDialog_serie_creator); - - /* X axis sash label */ - gridData = new GridData(GridData.FILL_BOTH | GridData.VERTICAL_ALIGN_END); - gridData.horizontalSpan = 1; - Label xSeriesCreatorLabel = new Label(seriesCreatorGroup, SWT.CENTER); - xSeriesCreatorLabel.setLayoutData(gridData); - xSeriesCreatorLabel.setText(Messages.LamiSeriesDialog_x_axis); - - gridData = new GridData(GridData.FILL_BOTH | GridData.VERTICAL_ALIGN_END); - gridData.horizontalSpan = 1; - Label ySeriesCreatorLabel = new Label(seriesCreatorGroup, SWT.CENTER); - ySeriesCreatorLabel.setLayoutData(gridData); - ySeriesCreatorLabel.setText(Messages.LamiSeriesDialog_y_axis); - - /* Empty label for grid layout */ - gridData = new GridData(GridData.FILL_BOTH); - gridData.horizontalSpan = 1; - Label emptyLabel = new Label(seriesCreatorGroup, SWT.CENTER); - emptyLabel.setLayoutData(gridData); - - SashForm sash1 = new SashForm(seriesCreatorGroup, SWT.BORDER | SWT.HORIZONTAL); - gridData = new GridData(GridData.FILL_BOTH); - gridData.horizontalSpan = 2; - sash1.setLayoutData(gridData); - sash1.setVisible(true); - - fXTableViewer = new TableViewer(sash1, getTableStyle()); - fXTableViewer.setContentProvider(fXContentProvider); - fXTableViewer.setLabelProvider(fXLabelProvider); - fXTableViewer.setInput(fXInputElement); - - fYCheckBoxViewer = checkNotNull(CheckboxTableViewer.newCheckList(sash1, SWT.BORDER)); - fYCheckBoxViewer.setLabelProvider(fYLabelProvider); - fYCheckBoxViewer.setContentProvider(fYContentProvider); - fYCheckBoxViewer.setInput(fYInputElement); - - gridData = new GridData(SWT.FILL, SWT.NONE, true, true); - gridData.horizontalSpan = 1; - Button button1 = new Button(seriesCreatorGroup, SWT.PUSH); - button1.setText(Messages.LamiSeriesDialog_add); - button1.setLayoutData(gridData); - button1.addSelectionListener(new SelectionListener() { - - @Override - public void widgetSelected(@Nullable SelectionEvent e) { - Object[] ySelections = fYCheckBoxViewer.getCheckedElements(); - IStructuredSelection xSelections = (IStructuredSelection) fXTableViewer.getSelection(); - @Nullable Object x = xSelections.getFirstElement(); - if (!(x instanceof LamiTableEntryAspect) || ySelections.length == 0) { - return; - } - - /* Add selection to series if it doesn not already exist in the list */ - for (Object y : ySelections) { - if(!(y instanceof LamiTableEntryAspect)) { - continue; - } - LamiXYSeriesDescription serie = new LamiXYSeriesDescription((LamiTableEntryAspect) x, ((LamiTableEntryAspect) y)); - if (!series.contains(serie)) { - series.add(serie); - fSeriesListViewer.refresh(); - } - } - - /* Set label warning visible and enable OK button */ - fWarning.setVisible(true); - getButton(IDialogConstants.OK_ID).setEnabled(true); - - /* Update possible X selection based on current series */ - TableItem[] items = fXTableViewer.getTable().getItems(); - Arrays.stream(items).forEach(item -> { - LamiTableEntryAspect aspect = (LamiTableEntryAspect) item.getData(); - if (!aspect.arePropertiesEqual(series.get(0).getXAspect())) { - fXTableViewer.remove(aspect); - } - if (fRestrictXSeriesNumbers && aspect != (series.get(0).getXAspect())) { - fXTableViewer.remove(aspect); - } - }); - - /* - * Disable all checkBox that do not apply to aspects series. - * Simply take the first one since all series should comply to - * the same restriction - */ - fXCheckBoxOptions.forEach(checkBox -> { - checkBox.setButtonEnabled(checkBox.getPredicate().test(series.get(0).getXAspect())); - }); - fYCheckBoxOptions.forEach(checkBox -> { - checkBox.setButtonEnabled(checkBox.getPredicate().test(series.get(0).getYAspect())); - }); - } - - @Override - public void widgetDefaultSelected(@Nullable SelectionEvent e) { - } - }); - - - gridData = new GridData(GridData.FILL_BOTH | GridData.VERTICAL_ALIGN_END); - gridData.horizontalSpan = 3; - fWarning = new Label(seriesCreatorGroup, SWT.LEFT); - fWarning.setLayoutData(gridData); - fWarning.setText(Messages.LamiSeriesDialog_selectionRestrictionWarning); - fWarning.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_RED)); - fWarning.setVisible(false); - - gridData = new GridData(GridData.FILL_BOTH); - gridData.horizontalSpan = 3; - Group optionGroups = new Group(composite, getShellStyle()); - optionGroups.setLayoutData(gridData); - optionGroups.setLayout(new GridLayout(3, false)); - optionGroups.setText(Messages.LamiSeriesDialog_chart_options); - - for (LamiAxisCheckBoxOption checkBox : fXCheckBoxOptions) { - Button button = new Button(optionGroups, SWT.CHECK); - button.setSelection(checkBox.getDefaultValue()); - button.setText(checkBox.getName()); - checkBox.setButton(button); - } - - for (LamiAxisCheckBoxOption checkBox : fYCheckBoxOptions) { - Button button = new Button(optionGroups, SWT.CHECK); - button.setSelection(checkBox.getDefaultValue()); - button.setText(checkBox.getName()); - checkBox.setButton(button); - } - - fYCheckBoxViewer.getTable().addSelectionListener(new SelectionListener() { - - @Override - public void widgetSelected(@Nullable SelectionEvent e) { - /* On check */ - if (e != null && e.detail == SWT.CHECK) { - /* Change possible selection */ - IStructuredSelection selections = (IStructuredSelection) fYCheckBoxViewer.getSelection(); - if (selections.getFirstElement() != null) { - - boolean checked = fYCheckBoxViewer.getChecked(selections.getFirstElement()); - /* - * If just selected look for stuff to disable. If not no - * need to look for stuff to disable since it was - * already done before. - */ - if (checked) { - TableItem[] items = fYCheckBoxViewer.getTable().getItems(); - Arrays.stream(items).forEach(item -> { - LamiTableEntryAspect aspect = (LamiTableEntryAspect) item.getData(); - if (!aspect.arePropertiesEqual((LamiTableEntryAspect) checkNotNull(selections.getFirstElement()))) { - fYCheckBoxViewer.remove(aspect); - } - }); - } else if (!checked && fYCheckBoxViewer.getCheckedElements().length == 0 && fSeriesListViewer.getTable().getItemCount() == 0) { - fYCheckBoxViewer.refresh(); - } - } - } - } - - @Override - public void widgetDefaultSelected(@Nullable SelectionEvent e) { - } - }); - - Dialog.applyDialogFont(composite); - return composite; - } - - /* - * Disable OK button on dialog creation. - */ - @Override - protected void createButtonsForButtonBar(@Nullable Composite parent) { - super.createButtonsForButtonBar(parent); - getButton(IDialogConstants.OK_ID).setEnabled(false); - } - - /** - * Return the style flags for the table viewer. - * - * @return int - */ - protected int getTableStyle() { - return SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER; - } - - /** - * Add check box option for X series. - * - * @param name - * The name of the option. The actual text shown to the user. - * @param defaultValue - * The default state of the check box option. - * @param predicate - * The predicate to check if the option applies to the given - * aspect - * @return The index of the option value in the result table. - */ - public int addXCheckBoxOption(String name, boolean defaultValue, Predicate predicate) { - LamiAxisCheckBoxOption checkBox = new LamiAxisCheckBoxOption(name, defaultValue, predicate); - fXCheckBoxOptions.add(checkBox); - return fXCheckBoxOptions.size() - 1; - } - - /** - * Add check box option for Y series. - * - * @param name - * The name of the option. The actual text shown to the user. - * @param defaultValue - * The default state of the check box option. - * @param predicate - * The predicate to check if the option applies to the given - * aspect - * @return The index of the option value in the result table. - */ - public int addYCheckBoxOption(String name, boolean defaultValue, Predicate predicate) { - LamiAxisCheckBoxOption checkbox = new LamiAxisCheckBoxOption(name, defaultValue, predicate); - fYCheckBoxOptions.add(checkbox); - return fYCheckBoxOptions.size() - 1; - } - - /** - * @return The final values of X series check boxes. - */ - public boolean[] getXCheckBoxOptionValues() { - boolean[] selections = new boolean[fXCheckBoxOptions.size()]; - for (int i = 0; i < selections.length; i++) { - selections[i] = fXCheckBoxOptions.get(i).getValue(); - } - return selections; - } - - /** - * @return The final values of Y series check boxes. - */ - public boolean[] getYCheckBoxOptionValues() { - boolean[] selections = new boolean[fYCheckBoxOptions.size()]; - for (int i = 0; i < selections.length; i++) { - selections[i] = fYCheckBoxOptions.get(i).getValue(); - } - return selections; - } - - @Override - protected void okPressed() { - for (LamiAxisCheckBoxOption checkBox : fXCheckBoxOptions) { - checkBox.updateValue(); - } - for (LamiAxisCheckBoxOption checkBox : fYCheckBoxOptions) { - checkBox.updateValue(); - } - super.okPressed(); - } - - @Override - public Object[] getResult() { - return series.toArray(); - } - - private static > TableViewerColumn createTableViewerColumn(TableViewer viewer, String name, - Function propertyFunction) { - TableViewerColumn viewerColumn = new TableViewerColumn(viewer, SWT.CENTER); - viewerColumn.setLabelProvider(new ColumnLabelProvider() { - @Override - public @Nullable String getText(@Nullable Object element) { - if (element != null) { - return propertyFunction.apply((LamiXYSeriesDescription) element).toString(); - } - return null; - } - }); - - TableColumn column = viewerColumn.getColumn(); - column.setText(name); - return viewerColumn; - } - -} diff --git a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/views/LamiViewerControl.java b/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/views/LamiViewerControl.java index 188f6fcb6f..4f9d7de231 100644 --- a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/views/LamiViewerControl.java +++ b/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/views/LamiViewerControl.java @@ -14,8 +14,12 @@ import org.eclipse.jface.action.Action; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.widgets.Composite; import org.eclipse.tracecompass.internal.analysis.lami.ui.Activator; -import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiChartModel; -import org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.viewers.ILamiViewer; +import org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.viewers.LamiTableViewer; +import org.eclipse.tracecompass.internal.provisional.tmf.chart.core.chart.ChartData; +import org.eclipse.tracecompass.internal.provisional.tmf.chart.core.chart.ChartModel; +import org.eclipse.tracecompass.internal.provisional.tmf.chart.core.chart.ChartType; +import org.eclipse.tracecompass.internal.provisional.tmf.chart.ui.chart.IChartViewer; +import org.eclipse.tracecompass.tmf.ui.viewers.TmfViewer; /** * Control for Lami viewers. @@ -29,7 +33,7 @@ public final class LamiViewerControl { private final Action fToggleAction; - private @Nullable ILamiViewer fViewer; + private @Nullable TmfViewer fViewer; /** * Build a new control for a Lami table viewer. @@ -43,9 +47,9 @@ public final class LamiViewerControl { fToggleAction = new Action() { @Override public void run() { - ILamiViewer viewer = fViewer; + TmfViewer viewer = fViewer; if (viewer == null) { - fViewer = ILamiViewer.createLamiTable(parent, page); + fViewer = LamiTableViewer.createLamiTable(parent, page); } else { viewer.dispose(); fViewer = null; @@ -63,18 +67,18 @@ public final class LamiViewerControl { * * @param parent * The parent composite - * @param page + * @param data * The {@link LamiReportViewTabPage} parent page - * @param graphModel + * @param model * The graph model */ - public LamiViewerControl(Composite parent, LamiReportViewTabPage page, LamiChartModel graphModel) { + public LamiViewerControl(Composite parent, ChartData data, ChartModel model) { fToggleAction = new Action() { @Override public void run() { - ILamiViewer viewer = fViewer; + TmfViewer viewer = fViewer; if (viewer == null) { - fViewer = ILamiViewer.createLamiChart(parent, page, graphModel); + fViewer = (TmfViewer) IChartViewer.createChart(parent, data, model); } else { viewer.dispose(); fViewer = null; @@ -82,9 +86,9 @@ public final class LamiViewerControl { parent.layout(); } }; - fToggleAction.setText(Messages.LamiReportView_ToggleAction_ButtonNamePrefix + ' ' + graphModel.getName()); + fToggleAction.setText(Messages.LamiReportView_ToggleAction_ButtonNamePrefix + ' ' + model.getTitle()); fToggleAction.setToolTipText(Messages.LamiReportView_ToggleAction_ButtonTooltip); - fToggleAction.setImageDescriptor(getIconForGraphType(graphModel.getChartType())); + fToggleAction.setImageDescriptor(getIconForGraphType(model.getChartType())); } /** @@ -93,7 +97,7 @@ public final class LamiViewerControl { * * @return The viewer */ - public @Nullable ILamiViewer getViewer() { + public @Nullable TmfViewer getViewer() { return fViewer; } @@ -115,12 +119,12 @@ public final class LamiViewerControl { } } - private static @Nullable ImageDescriptor getIconForGraphType(LamiChartModel.LamiChartType graphType) { - switch (graphType) { + private static @Nullable ImageDescriptor getIconForGraphType(ChartType chartType) { + switch (chartType) { case BAR_CHART: return Activator.getDefault().getImageDescripterFromPath("icons/histogram.gif"); //$NON-NLS-1$ case PIE_CHART: - case XY_SCATTER: + case SCATTER_CHART: default: // FIXME Use other icons return Activator.getDefault().getImageDescripterFromPath("icons/histogram.gif"); //$NON-NLS-1$ diff --git a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/views/Messages.java b/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/views/Messages.java index a80648990e..33df1a9b51 100644 --- a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/views/Messages.java +++ b/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/views/Messages.java @@ -30,26 +30,7 @@ public class Messages extends NLS { public static String LamiReportView_ToggleAction_ButtonTooltip; public static String LamiReportView_NewCustomChart; - public static String LamiReportView_NewCustomBarChart; - public static String LamiReportView_NewCustomScatterChart; public static String LamiReportView_ClearAllCustomViews; - public static String LamiReportView_LogScale; - public static String LamiReportView_SelectColumnForX; - public static String LamiReportView_SelectColumnsForCategories; - public static String LamiReportView_SelectColumnsForSeries; - public static String LamiReportView_Custom; - - public static String LamiSeriesDialog_creation; - public static String LamiSeriesDialog_add; - public static String LamiSeriesDialog_chart_options; - public static String LamiSeriesDialog_delete; - public static String LamiSeriesDialog_selectionRestrictionWarning; - public static String LamiSeriesDialog_serie_creator; - public static String LamiSeriesDialog_series; - public static String LamiSeriesDialog_x_axis; - public static String LamiSeriesDialog_x_values; - public static String LamiSeriesDialog_y_axis; - public static String LamiSeriesDialog_y_values; static { NLS.initializeMessages(BUNDLE_NAME, Messages.class); diff --git a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/views/messages.properties b/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/views/messages.properties index 6493098e03..b04433bdce 100644 --- a/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/views/messages.properties +++ b/analysis/org.eclipse.tracecompass.analysis.lami.ui/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/ui/views/messages.properties @@ -14,23 +14,4 @@ LamiReportView_ToggleAction_ButtonNamePrefix = Toggle LamiReportView_ToggleAction_ButtonTooltip = Toggle showing this graph in the view LamiReportView_NewCustomChart = New custom chart -LamiReportView_NewCustomBarChart = New custom bar chart -LamiReportView_NewCustomScatterChart = New custom scatter chart LamiReportView_ClearAllCustomViews = Clear all custom views -LamiReportView_LogScale = Log scale -LamiReportView_SelectColumnForX = Select the column used for the X axis -LamiReportView_SelectColumnsForCategories = Select the columns used for the categories -LamiReportView_SelectColumnsForSeries = Select the columns used for the series -LamiReportView_Custom = Custom - -LamiSeriesDialog_creation = chart series creation -LamiSeriesDialog_add = Add -LamiSeriesDialog_chart_options = Chart options -LamiSeriesDialog_delete = Delete -LamiSeriesDialog_selectionRestrictionWarning = Note: Selection might be restricted based on type checking of previously selected series -LamiSeriesDialog_serie_creator = Series creator -LamiSeriesDialog_series = Series -LamiSeriesDialog_x_axis = X axis -LamiSeriesDialog_x_values = X-Values -LamiSeriesDialog_y_axis = Y axis -LamiSeriesDialog_y_values = Y-Values -- 2.34.1