Commit | Line | Data |
---|---|---|
4999a196 | 1 | /******************************************************************************* |
50d36521 | 2 | * Copyright (c) 2012, 2015 Ericsson, École Polytechnique de Montréal |
4999a196 GB |
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 | * Patrick Tasse - Initial API and implementation | |
11 | * Geneviève Bastien - Move code to provide base classes for time graph view | |
12 | *******************************************************************************/ | |
13 | ||
2bdf0193 | 14 | package org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model; |
4999a196 GB |
15 | |
16 | import java.util.ArrayList; | |
9ba941e9 PT |
17 | import java.util.Arrays; |
18 | import java.util.Comparator; | |
4999a196 GB |
19 | import java.util.Iterator; |
20 | import java.util.List; | |
1cf25311 | 21 | import java.util.concurrent.CopyOnWriteArrayList; |
36299425 | 22 | import java.util.regex.Pattern; |
4999a196 | 23 | |
0b02f22a | 24 | import org.eclipse.jdt.annotation.NonNull; |
50d36521 PT |
25 | import org.eclipse.swt.SWT; |
26 | ||
4999a196 GB |
27 | /** |
28 | * An entry for use in the time graph views | |
4999a196 GB |
29 | */ |
30 | public class TimeGraphEntry implements ITimeGraphEntry { | |
31 | ||
4999a196 | 32 | /** Entry's parent */ |
a3188982 | 33 | private ITimeGraphEntry fParent = null; |
4999a196 GB |
34 | |
35 | /** List of child entries */ | |
df2597e0 | 36 | private final List<@NonNull ITimeGraphEntry> fChildren = new CopyOnWriteArrayList<>(); |
4999a196 GB |
37 | |
38 | /** Name of this entry (text to show) */ | |
39 | private String fName; | |
50d36521 PT |
40 | private long fStartTime = SWT.DEFAULT; |
41 | private long fEndTime = SWT.DEFAULT; | |
0b02f22a PT |
42 | private @NonNull List<ITimeEvent> fEventList = new ArrayList<>(); |
43 | private @NonNull List<ITimeEvent> fZoomedEventList = new ArrayList<>(); | |
9ba941e9 | 44 | private Comparator<ITimeGraphEntry> fComparator; |
4999a196 GB |
45 | |
46 | /** | |
47 | * Constructor | |
48 | * | |
4999a196 | 49 | * @param name |
1d46dc38 | 50 | * The name of this entry |
4999a196 | 51 | * @param startTime |
1d46dc38 | 52 | * The start time of this entry |
4999a196 | 53 | * @param endTime |
1d46dc38 | 54 | * The end time of this entry |
4999a196 | 55 | */ |
1d46dc38 | 56 | public TimeGraphEntry(String name, long startTime, long endTime) { |
4999a196 GB |
57 | fName = name; |
58 | fStartTime = startTime; | |
59 | fEndTime = endTime; | |
60 | } | |
61 | ||
62 | // --------------------------------------------- | |
63 | // Getters and setters | |
64 | // --------------------------------------------- | |
65 | ||
66 | @Override | |
67 | public ITimeGraphEntry getParent() { | |
68 | return fParent; | |
69 | } | |
70 | ||
71 | /** | |
72 | * Sets the entry's parent | |
73 | * | |
74 | * @param entry The new parent entry | |
75 | */ | |
a3188982 PT |
76 | /* |
77 | * TODO: This method can be removed in the next major API version. | |
78 | */ | |
4999a196 GB |
79 | protected void setParent(TimeGraphEntry entry) { |
80 | fParent = entry; | |
81 | } | |
82 | ||
a3188982 PT |
83 | /** |
84 | * Sets the entry's parent | |
85 | * | |
86 | * @param entry The new parent entry | |
a3188982 PT |
87 | */ |
88 | /* | |
89 | * TODO: This method should be added to the interface in the next major API version. | |
90 | */ | |
91 | protected void setParent(ITimeGraphEntry entry) { | |
92 | fParent = entry; | |
93 | } | |
94 | ||
4999a196 | 95 | @Override |
9ba941e9 | 96 | public synchronized boolean hasChildren() { |
4999a196 GB |
97 | return fChildren.size() > 0; |
98 | } | |
99 | ||
100 | @Override | |
df2597e0 | 101 | public synchronized List<@NonNull ? extends ITimeGraphEntry> getChildren() { |
4999a196 GB |
102 | return fChildren; |
103 | } | |
104 | ||
105 | @Override | |
106 | public String getName() { | |
107 | return fName; | |
108 | } | |
109 | ||
110 | /** | |
111 | * Update the entry name | |
112 | * | |
113 | * @param name | |
114 | * the updated entry name | |
115 | */ | |
116 | public void setName(String name) { | |
117 | fName = name; | |
118 | } | |
119 | ||
120 | @Override | |
121 | public long getStartTime() { | |
122 | return fStartTime; | |
123 | } | |
124 | ||
125 | @Override | |
126 | public long getEndTime() { | |
127 | return fEndTime; | |
128 | } | |
129 | ||
1cf25311 PT |
130 | /** |
131 | * Updates the end time | |
132 | * | |
133 | * @param endTime | |
134 | * the end time | |
1cf25311 PT |
135 | */ |
136 | public void updateEndTime(long endTime) { | |
137 | fEndTime = Math.max(endTime, fEndTime); | |
138 | } | |
139 | ||
4999a196 GB |
140 | @Override |
141 | public boolean hasTimeEvents() { | |
142 | return true; | |
143 | } | |
144 | ||
145 | @Override | |
df2597e0 | 146 | public Iterator<@NonNull ITimeEvent> getTimeEventsIterator() { |
4999a196 GB |
147 | if (hasTimeEvents()) { |
148 | return new EventIterator(fEventList, fZoomedEventList); | |
149 | } | |
150 | return null; | |
151 | } | |
152 | ||
153 | @Override | |
df2597e0 | 154 | public Iterator<@NonNull ITimeEvent> getTimeEventsIterator(long startTime, long stopTime, long visibleDuration) { |
4999a196 GB |
155 | if (!hasTimeEvents()) { |
156 | return null; | |
157 | } | |
158 | return new EventIterator(fEventList, fZoomedEventList, startTime, stopTime); | |
159 | } | |
160 | ||
161 | /** | |
1d46dc38 | 162 | * Add an event to this entry's event list. If necessary, update the start |
1cf25311 PT |
163 | * and end time of the entry. If the event list's last event starts at the |
164 | * same time as the event to add, it is replaced by the new event. | |
4999a196 GB |
165 | * |
166 | * @param event | |
1cf25311 | 167 | * The time event to add |
4999a196 GB |
168 | */ |
169 | public void addEvent(ITimeEvent event) { | |
170 | long start = event.getTime(); | |
171 | long end = start + event.getDuration(); | |
0b02f22a PT |
172 | int lastIndex = fEventList.size() - 1; |
173 | if (lastIndex >= 0 && fEventList.get(lastIndex).getTime() == event.getTime()) { | |
174 | fEventList.set(lastIndex, event); | |
175 | } else { | |
176 | fEventList.add(event); | |
177 | } | |
cb982e03 PT |
178 | if (event instanceof NullTimeEvent) { |
179 | /* A NullTimeEvent should not affect the entry bounds */ | |
180 | return; | |
181 | } | |
0b02f22a PT |
182 | if (fStartTime == SWT.DEFAULT || start < fStartTime) { |
183 | fStartTime = start; | |
184 | } | |
185 | if (fEndTime == SWT.DEFAULT || end > fEndTime) { | |
186 | fEndTime = end; | |
4999a196 GB |
187 | } |
188 | } | |
189 | ||
190 | /** | |
0b02f22a PT |
191 | * Set the general event list of this entry. The list should be modifiable |
192 | * but will only increase in size over time. | |
4999a196 | 193 | * |
4999a196 | 194 | * @param eventList |
0b02f22a | 195 | * The modifiable list of time events, or null to clear the list |
4999a196 GB |
196 | */ |
197 | public void setEventList(List<ITimeEvent> eventList) { | |
3ce8c834 | 198 | if (eventList != null) { |
0b02f22a | 199 | fEventList = eventList; |
3ce8c834 | 200 | } else { |
507b1336 | 201 | fEventList = new ArrayList<>(); |
3ce8c834 | 202 | } |
4999a196 GB |
203 | } |
204 | ||
205 | /** | |
0b02f22a PT |
206 | * Set the zoomed event list of this entry. The list should be modifiable |
207 | * but will only increase in size over time. | |
4999a196 | 208 | * |
4999a196 | 209 | * @param eventList |
0b02f22a | 210 | * The modifiable list of time events, or null to clear the list |
4999a196 GB |
211 | */ |
212 | public void setZoomedEventList(List<ITimeEvent> eventList) { | |
3ce8c834 | 213 | if (eventList != null) { |
0b02f22a | 214 | fZoomedEventList = eventList; |
3ce8c834 | 215 | } else { |
507b1336 | 216 | fZoomedEventList = new ArrayList<>(); |
3ce8c834 | 217 | } |
4999a196 GB |
218 | } |
219 | ||
0b02f22a PT |
220 | /** |
221 | * Add an event to this entry's zoomed event list. If necessary, update the | |
222 | * start and end time of the entry. If the zoomed event list's last event | |
223 | * starts at the same time as the event to add, it is replaced by the new | |
224 | * event. If the new event starts before the zoomed event list's last event, | |
225 | * the new event is ignored and is assumed to be already part of the list. | |
226 | * | |
227 | * @param event | |
228 | * The time event to add | |
0336f981 | 229 | * @since 1.1 |
0b02f22a PT |
230 | */ |
231 | public void addZoomedEvent(ITimeEvent event) { | |
232 | long start = event.getTime(); | |
233 | long end = start + event.getDuration(); | |
234 | int lastIndex = fZoomedEventList.size() - 1; | |
235 | long lastStart = lastIndex >= 0 ? fZoomedEventList.get(lastIndex).getTime() : Long.MIN_VALUE; | |
236 | if (start > lastStart) { | |
237 | fZoomedEventList.add(event); | |
238 | } else if (start == lastStart) { | |
239 | fZoomedEventList.set(lastIndex, event); | |
240 | } | |
cb982e03 PT |
241 | if (event instanceof NullTimeEvent) { |
242 | /* A NullTimeEvent should not affect the entry bounds */ | |
243 | return; | |
244 | } | |
0b02f22a PT |
245 | if (fStartTime == SWT.DEFAULT || start < fStartTime) { |
246 | fStartTime = start; | |
247 | } | |
248 | if (fEndTime == SWT.DEFAULT || end > fEndTime) { | |
249 | fEndTime = end; | |
250 | } | |
251 | } | |
252 | ||
4999a196 | 253 | /** |
1d46dc38 | 254 | * Add a child entry to this one |
4999a196 GB |
255 | * |
256 | * @param child | |
257 | * The child entry | |
258 | */ | |
a3188982 PT |
259 | /* |
260 | * TODO: This method can be removed in the next major API version. | |
261 | */ | |
df2597e0 | 262 | public synchronized void addChild(@NonNull TimeGraphEntry child) { |
9ba941e9 | 263 | addChild((ITimeGraphEntry) child); |
4999a196 GB |
264 | } |
265 | ||
a3188982 | 266 | /** |
9ba941e9 PT |
267 | * Add a child entry to this one. If a comparator was previously set with |
268 | * {@link #sortChildren(Comparator)}, the entry will be inserted in its | |
269 | * sort-order position. Otherwise it will be added to the end of the list. | |
a3188982 PT |
270 | * |
271 | * @param child | |
272 | * The child entry | |
a3188982 | 273 | */ |
df2597e0 | 274 | public synchronized void addChild(@NonNull ITimeGraphEntry child) { |
9ba941e9 PT |
275 | /* |
276 | * TODO: Use setParent() once it is added to the interface. | |
277 | */ | |
a3188982 PT |
278 | if (child instanceof TimeGraphEntry) { |
279 | ((TimeGraphEntry) child).fParent = this; | |
280 | } | |
9ba941e9 PT |
281 | if (fComparator == null) { |
282 | fChildren.add(child); | |
283 | } else { | |
284 | int i; | |
285 | for (i = 0; i < fChildren.size(); i++) { | |
286 | ITimeGraphEntry entry = fChildren.get(i); | |
287 | if (fComparator.compare(child, entry) < 0) { | |
288 | break; | |
289 | } | |
290 | } | |
291 | fChildren.add(i, child); | |
292 | } | |
a3188982 PT |
293 | } |
294 | ||
295 | /** | |
296 | * Add a child entry to this one at the specified position | |
297 | * | |
298 | * @param index | |
299 | * Index at which the specified entry is to be inserted | |
300 | * @param child | |
301 | * The child entry | |
a3188982 | 302 | */ |
df2597e0 | 303 | public synchronized void addChild(int index, @NonNull ITimeGraphEntry child) { |
9ba941e9 PT |
304 | /* |
305 | * TODO: Use setParent() once it is added to the interface. | |
306 | */ | |
a3188982 PT |
307 | if (child instanceof TimeGraphEntry) { |
308 | ((TimeGraphEntry) child).fParent = this; | |
309 | } | |
310 | fChildren.add(index, child); | |
311 | } | |
312 | ||
9ba941e9 PT |
313 | /** |
314 | * Sort the children of this entry using the provided comparator. Subsequent | |
315 | * calls to {@link #addChild(ITimeGraphEntry)} will use this comparator to | |
316 | * maintain the sort order. | |
317 | * | |
318 | * @param comparator | |
319 | * The entry comparator | |
9ba941e9 PT |
320 | */ |
321 | public synchronized void sortChildren(Comparator<ITimeGraphEntry> comparator) { | |
322 | fComparator = comparator; | |
323 | if (comparator == null) { | |
324 | return; | |
325 | } | |
df2597e0 | 326 | @NonNull ITimeGraphEntry[] array = fChildren.toArray(new @NonNull ITimeGraphEntry[0]); |
9ba941e9 PT |
327 | Arrays.sort(array, comparator); |
328 | fChildren.clear(); | |
329 | fChildren.addAll(Arrays.asList(array)); | |
330 | } | |
331 | ||
b1b156f3 PT |
332 | @Override |
333 | public String toString() { | |
334 | return getClass().getSimpleName() + '(' + fName + ')'; | |
335 | } | |
336 | ||
36299425 JCK |
337 | /** |
338 | * @since 2.0 | |
339 | */ | |
340 | @Override | |
341 | public boolean matches(@NonNull Pattern pattern) { | |
342 | // Default implementation | |
343 | return pattern.matcher(fName).find(); | |
344 | } | |
345 | ||
4999a196 | 346 | } |