xml: bug 493954: Allow string states to be displayed in time graph views
authorGeneviève Bastien <gbastien+lttng@versatic.net>
Wed, 4 May 2016 03:31:33 +0000 (23:31 -0400)
committerGenevieve Bastien <gbastien+lttng@versatic.net>
Thu, 2 Jun 2016 20:09:22 +0000 (16:09 -0400)
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 <gbastien+lttng@versatic.net>
Reviewed-on: https://git.eclipse.org/r/71970
Reviewed-by: Hudson CI
Reviewed-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
tmf/org.eclipse.tracecompass.tmf.analysis.xml.ui/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/ui/views/timegraph/XmlPresentationProvider.java
tmf/org.eclipse.tracecompass.tmf.analysis.xml.ui/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/ui/views/timegraph/XmlTimeGraphView.java

index ac8eb753c96eb383a75accfb543634d5435d60b0..d83a8b300a47242fdc09cfb2b30737ac5a64c99f 100644 (file)
@@ -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<StateItem> 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<Element> 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);
     }
 
index 331d81bf6159aa7dd005fbbd84e5f159c9ba659d..41b3c9a50d20b7432f38fa92ddd35fd8a0e9f61a 100644 (file)
@@ -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<String, Integer> 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<String> analysisIds = fViewInfo.getViewAnalysisIds(viewElement);
 
         List<Element> 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<ILinkEvent> getLinkList(long startTime, long endTime, long resolution, IProgressMonitor monitor) {
         /* TODO: not implemented yet, need XML to go along */
This page took 0.028 seconds and 5 git commands to generate.