From: Geneviève Bastien Date: Wed, 4 May 2016 03:31:33 +0000 (-0400) Subject: xml: bug 493954: Allow string states to be displayed in time graph views X-Git-Url: http://git.efficios.com/?p=deliverable%2Ftracecompass.git;a=commitdiff_plain;h=6d8889e1ca56c2442446eeb1ee24a5bd108d7e90 xml: bug 493954: Allow string states to be displayed in time graph views If a string state value is to be displayed in the time graph, it will add a new state to the presentation provider with color. This state will be re-used when the same string is displayed again. This is ideal for time graphs of state system where there is a fixed number of strings as value, yet impossible to define with definedValues because specific to a trace. Change-Id: I2d1fa041e578e0a7dbccc3138153db3fd4684c62 Signed-off-by: Geneviève Bastien Reviewed-on: https://git.eclipse.org/r/71970 Reviewed-by: Hudson CI Reviewed-by: Matthew Khouzam --- diff --git a/tmf/org.eclipse.tracecompass.tmf.analysis.xml.ui/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/ui/views/timegraph/XmlPresentationProvider.java b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.ui/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/ui/views/timegraph/XmlPresentationProvider.java index ac8eb753c9..d83a8b300a 100644 --- a/tmf/org.eclipse.tracecompass.tmf.analysis.xml.ui/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/ui/views/timegraph/XmlPresentationProvider.java +++ b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.ui/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/ui/views/timegraph/XmlPresentationProvider.java @@ -40,13 +40,18 @@ import org.w3c.dom.Element; * provider. * * TODO: This should support colors/states defined for each entry element in the - * XML element. Also, event values may not be integers only (for instance, this - * wouldn't support yet the callstack view) + * XML element. * * @author Florian Wininger */ public class XmlPresentationProvider extends TimeGraphPresentationProvider { + private static final long[] COLOR_SEED = { 0x0000ff, 0xff0000, 0x00ff00, + 0xff00ff, 0x00ffff, 0xffff00, 0x000000, 0xf07300 + }; + + private static final int COLOR_MASK = 0xffffff; + private List stateValues = new ArrayList<>(); /* * Maps the value of an event with the corresponding index in the @@ -126,7 +131,7 @@ public class XmlPresentationProvider extends TimeGraphPresentationProvider { * @param viewElement * The XML view element */ - public void loadNewStates(@NonNull Element viewElement) { + public synchronized void loadNewStates(@NonNull Element viewElement) { stateValues.clear(); stateIndex.clear(); List states = XmlUtils.getChildElements(viewElement, TmfXmlStrings.DEFINED_VALUE); @@ -136,31 +141,59 @@ public class XmlPresentationProvider extends TimeGraphPresentationProvider { String name = state.getAttribute(TmfXmlStrings.NAME); String color = state.getAttribute(TmfXmlStrings.COLOR); - // FIXME Allow this case - if (value < 0) { - return; + addOrUpdateState(value, name, color); + } + Display.getDefault().asyncExec(new Runnable() { + @Override + public void run() { + fireColorSettingsChanged(); } + }); + } - final RGB colorRGB = (color.startsWith(TmfXmlStrings.COLOR_PREFIX)) ? parseColor(color) : calcColor(value); - - StateItem item = new StateItem(colorRGB, name); - - Integer index = stateIndex.get(value); - if (index == null) { - /* Add the new state value */ - stateIndex.put(value, stateValues.size()); - stateValues.add(item); - } else { - /* Override a previous state value */ - stateValues.set(index, item); - } + /** + * Add a new state in the time graph view. This allow to define at runtime + * new states that cannot be known at the conception of this analysis. + * + * @param name + * The string associated with the state + * @return the value for this state + */ + public synchronized int addState(String name) { + // Find a value for this name, start at 10000 + int value = 10000; + while (stateIndex.get(value) != null) { + value++; } + addOrUpdateState(value, name, ""); //$NON-NLS-1$ Display.getDefault().asyncExec(new Runnable() { @Override public void run() { fireColorSettingsChanged(); } }); + return value; + } + + private synchronized void addOrUpdateState(int value, String name, String color) { + // FIXME Allow this case + if (value < 0) { + return; + } + + final RGB colorRGB = (color.startsWith(TmfXmlStrings.COLOR_PREFIX)) ? parseColor(color) : calcColor(name); + + StateItem item = new StateItem(colorRGB, name); + + Integer index = stateIndex.get(value); + if (index == null) { + /* Add the new state value */ + stateIndex.put(value, stateValues.size()); + stateValues.add(item); + } else { + /* Override a previous state value */ + stateValues.set(index, item); + } } private static RGB parseColor(String color) { @@ -173,39 +206,18 @@ public class XmlPresentationProvider extends TimeGraphPresentationProvider { return colorRGB; } - private static RGB calcColor(int value) { - int x = (value * 97) % 1530; - int r = 0, g = 0, b = 0; - if (x >= 0 && x < 255) { - r = 255; - g = x; - b = 0; - } - if (x >= 255 && x < 510) { - r = 510 - x; - g = 255; - b = 0; - } - if (x >= 510 && x < 765) { - r = 0; - g = 255; - b = x - 510; - } - if (x >= 765 && x < 1020) { - r = 0; - g = 1020 - x; - b = 255; - } - if (x >= 1020 && x < 1275) { - r = x - 1020; - g = 0; - b = 255; - } - if (x >= 1275 && x <= 1530) { - r = 255; - g = 0; - b = 1530 - x; - } + /* + * This method will always return the same color for a same name, no matter + * the value, so that different traces with the same XML analysis will + * display identically states with the same name. + */ + private static RGB calcColor(String name) { + int hash = name.hashCode(); + long base = COLOR_SEED[Math.abs(hash) % COLOR_SEED.length]; + int x = (int) ((hash & COLOR_MASK) ^ base); + final int r = (x >> 16) & 0xff; + final int g = (x >> 8) & 0xff; + final int b = x & 0xff; return new RGB(r, g, b); } diff --git a/tmf/org.eclipse.tracecompass.tmf.analysis.xml.ui/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/ui/views/timegraph/XmlTimeGraphView.java b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.ui/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/ui/views/timegraph/XmlTimeGraphView.java index 331d81bf61..41b3c9a50d 100644 --- a/tmf/org.eclipse.tracecompass.tmf.analysis.xml.ui/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/ui/views/timegraph/XmlTimeGraphView.java +++ b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.ui/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/ui/views/timegraph/XmlTimeGraphView.java @@ -49,6 +49,7 @@ import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedE import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException; import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException; import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval; +import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue; import org.eclipse.tracecompass.tmf.core.statesystem.ITmfAnalysisModuleWithStateSystems; import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils; @@ -97,6 +98,7 @@ public class XmlTimeGraphView extends AbstractTimeGraphView { private final @NonNull XmlViewInfo fViewInfo = new XmlViewInfo(ID); private final ITmfXmlModelFactory fFactory; + private final Map fStringValueMap = new HashMap<>(); // ------------------------------------------------------------------------ // Constructors @@ -243,6 +245,10 @@ public class XmlTimeGraphView extends AbstractTimeGraphView { title = Messages.XmlTimeGraphView_DefaultTitle; } setViewTitle(title); + + // Empty the additional state values + fStringValueMap.clear(); + Set analysisIds = fViewInfo.getViewAnalysisIds(viewElement); List entries = XmlUtils.getChildElements(viewElement, TmfXmlUiStrings.ENTRY_ELEMENT); @@ -491,7 +497,7 @@ public class XmlTimeGraphView extends AbstractTimeGraphView { if (monitor.isCanceled()) { return null; } - int status = statusInterval.getStateValue().unboxInt(); + int status = getStatusFromInterval(statusInterval); long time = statusInterval.getStartTime(); long duration = statusInterval.getEndTime() - time + 1; if (!statusInterval.getStateValue().isNull()) { @@ -512,6 +518,42 @@ public class XmlTimeGraphView extends AbstractTimeGraphView { return eventList; } + private int getStatusFromInterval(ITmfStateInterval statusInterval) { + ITmfStateValue stateValue = statusInterval.getStateValue(); + int status = -1; + switch (stateValue.getType()) { + case INTEGER: + case NULL: + status = stateValue.unboxInt(); + break; + case LONG: + status = (int) stateValue.unboxLong(); + break; + case STRING: + String statusStr = stateValue.unboxStr(); + Integer statusInt = fStringValueMap.get(statusStr); + if (statusInt != null) { + status = statusInt; + break; + } + ITimeGraphPresentationProvider2 pres = this.getPresentationProvider(); + if (pres instanceof XmlPresentationProvider) { + // Add this new state to the presentation provider + status = ((XmlPresentationProvider) pres).addState(statusStr); + fStringValueMap.put(statusStr, status); + } + break; + case DOUBLE: + status = (int) stateValue.unboxDouble(); + break; + case CUSTOM: + default: + break; + } + + return status; + } + @Override protected List getLinkList(long startTime, long endTime, long resolution, IProgressMonitor monitor) { /* TODO: not implemented yet, need XML to go along */