xml: bug 493954: Allow string states to be displayed in time graph views
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.analysis.xml.ui / src / org / eclipse / tracecompass / internal / tmf / analysis / xml / ui / views / timegraph / XmlPresentationProvider.java
1 /*******************************************************************************
2 * Copyright (c) 2014 École Polytechnique de Montréal
3 *
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors:
10 * Florian Wininger - Initial API and implementation
11 * Geneviève Bastien - Review of the initial implementation
12 *******************************************************************************/
13
14 package org.eclipse.tracecompass.internal.tmf.analysis.xml.ui.views.timegraph;
15
16 import java.util.ArrayList;
17 import java.util.Collections;
18 import java.util.HashMap;
19 import java.util.List;
20 import java.util.Map;
21
22 import org.eclipse.jdt.annotation.NonNull;
23 import org.eclipse.swt.graphics.GC;
24 import org.eclipse.swt.graphics.RGB;
25 import org.eclipse.swt.graphics.Rectangle;
26 import org.eclipse.swt.widgets.Display;
27 import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.XmlUtils;
28 import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.stateprovider.TmfXmlStrings;
29 import org.eclipse.tracecompass.internal.tmf.analysis.xml.ui.TmfXmlUiStrings;
30 import org.eclipse.tracecompass.internal.tmf.analysis.xml.ui.views.timegraph.XmlEntry.EntryDisplayType;
31 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.StateItem;
32 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphPresentationProvider;
33 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
34 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
35 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeEvent;
36 import org.w3c.dom.Element;
37
38 /**
39 * Presentation provider for the XML view, based on the generic TMF presentation
40 * provider.
41 *
42 * TODO: This should support colors/states defined for each entry element in the
43 * XML element.
44 *
45 * @author Florian Wininger
46 */
47 public class XmlPresentationProvider extends TimeGraphPresentationProvider {
48
49 private static final long[] COLOR_SEED = { 0x0000ff, 0xff0000, 0x00ff00,
50 0xff00ff, 0x00ffff, 0xffff00, 0x000000, 0xf07300
51 };
52
53 private static final int COLOR_MASK = 0xffffff;
54
55 private List<StateItem> stateValues = new ArrayList<>();
56 /*
57 * Maps the value of an event with the corresponding index in the
58 * stateValues list
59 */
60 private Map<Integer, Integer> stateIndex = new HashMap<>();
61
62 @Override
63 public int getStateTableIndex(ITimeEvent event) {
64 if (event instanceof TimeEvent && ((TimeEvent) event).hasValue()) {
65 TimeEvent tcEvent = (TimeEvent) event;
66
67 XmlEntry entry = (XmlEntry) event.getEntry();
68 int value = tcEvent.getValue();
69
70 if (entry.getType() == EntryDisplayType.DISPLAY) {
71 // Draw state only if state is already known
72 Integer index = stateIndex.get(value);
73 if (index != null) {
74 return index;
75 }
76 }
77 }
78 return INVISIBLE;
79 }
80
81 @Override
82 public StateItem[] getStateTable() {
83 return stateValues.toArray(new StateItem[stateValues.size()]);
84 }
85
86 @Override
87 public String getEventName(ITimeEvent event) {
88 if (event instanceof TimeEvent && ((TimeEvent) event).hasValue()) {
89 TimeEvent tcEvent = (TimeEvent) event;
90
91 XmlEntry entry = (XmlEntry) event.getEntry();
92 int value = tcEvent.getValue();
93
94 if (entry.getType() == EntryDisplayType.DISPLAY) {
95 Integer index = stateIndex.get(value);
96 if (index != null) {
97 String rgb = stateValues.get(index.intValue()).getStateString();
98 return rgb;
99 }
100 }
101 return null;
102 }
103 return Messages.XmlPresentationProvider_MultipleStates;
104 }
105
106 @Override
107 public Map<String, String> getEventHoverToolTipInfo(ITimeEvent event, long hoverTime) {
108 /*
109 * TODO: Add the XML elements to support adding extra information in the
110 * tooltips and implement this
111 */
112 return Collections.EMPTY_MAP;
113 }
114
115 @Override
116 public void postDrawEvent(ITimeEvent event, Rectangle bounds, GC gc) {
117 /*
118 * TODO Add the XML elements to support texts in intervals and implement
119 * this
120 */
121 }
122
123 @Override
124 public void postDrawEntry(ITimeGraphEntry entry, Rectangle bounds, GC gc) {
125 }
126
127 /**
128 * Loads the states from a {@link TmfXmlUiStrings#TIME_GRAPH_VIEW} XML
129 * element
130 *
131 * @param viewElement
132 * The XML view element
133 */
134 public synchronized void loadNewStates(@NonNull Element viewElement) {
135 stateValues.clear();
136 stateIndex.clear();
137 List<Element> states = XmlUtils.getChildElements(viewElement, TmfXmlStrings.DEFINED_VALUE);
138
139 for (Element state : states) {
140 int value = Integer.parseInt(state.getAttribute(TmfXmlStrings.VALUE));
141 String name = state.getAttribute(TmfXmlStrings.NAME);
142 String color = state.getAttribute(TmfXmlStrings.COLOR);
143
144 addOrUpdateState(value, name, color);
145 }
146 Display.getDefault().asyncExec(new Runnable() {
147 @Override
148 public void run() {
149 fireColorSettingsChanged();
150 }
151 });
152 }
153
154 /**
155 * Add a new state in the time graph view. This allow to define at runtime
156 * new states that cannot be known at the conception of this analysis.
157 *
158 * @param name
159 * The string associated with the state
160 * @return the value for this state
161 */
162 public synchronized int addState(String name) {
163 // Find a value for this name, start at 10000
164 int value = 10000;
165 while (stateIndex.get(value) != null) {
166 value++;
167 }
168 addOrUpdateState(value, name, ""); //$NON-NLS-1$
169 Display.getDefault().asyncExec(new Runnable() {
170 @Override
171 public void run() {
172 fireColorSettingsChanged();
173 }
174 });
175 return value;
176 }
177
178 private synchronized void addOrUpdateState(int value, String name, String color) {
179 // FIXME Allow this case
180 if (value < 0) {
181 return;
182 }
183
184 final RGB colorRGB = (color.startsWith(TmfXmlStrings.COLOR_PREFIX)) ? parseColor(color) : calcColor(name);
185
186 StateItem item = new StateItem(colorRGB, name);
187
188 Integer index = stateIndex.get(value);
189 if (index == null) {
190 /* Add the new state value */
191 stateIndex.put(value, stateValues.size());
192 stateValues.add(item);
193 } else {
194 /* Override a previous state value */
195 stateValues.set(index, item);
196 }
197 }
198
199 private static RGB parseColor(String color) {
200 RGB colorRGB;
201 Integer hex = Integer.parseInt(color.substring(1), 16);
202 int hex1 = hex.intValue() % 256;
203 int hex2 = (hex.intValue() / 256) % 256;
204 int hex3 = (hex.intValue() / (256 * 256)) % 256;
205 colorRGB = new RGB(hex3, hex2, hex1);
206 return colorRGB;
207 }
208
209 /*
210 * This method will always return the same color for a same name, no matter
211 * the value, so that different traces with the same XML analysis will
212 * display identically states with the same name.
213 */
214 private static RGB calcColor(String name) {
215 int hash = name.hashCode();
216 long base = COLOR_SEED[Math.abs(hash) % COLOR_SEED.length];
217 int x = (int) ((hash & COLOR_MASK) ^ base);
218 final int r = (x >> 16) & 0xff;
219 final int g = (x >> 8) & 0xff;
220 final int b = x & 0xff;
221 return new RGB(r, g, b);
222 }
223
224 }
This page took 0.036439 seconds and 5 git commands to generate.