Commit | Line | Data |
---|---|---|
73005152 | 1 | /********************************************************************** |
ed902a2b | 2 | * Copyright (c) 2005, 2014 IBM Corporation, Ericsson |
73005152 BH |
3 | * All rights reserved. This program and the accompanying materials |
4 | * are made available under the terms of the Eclipse Public License v1.0 | |
5 | * which accompanies this distribution, and is available at | |
6 | * http://www.eclipse.org/legal/epl-v10.html | |
a55887ca AM |
7 | * |
8 | * Contributors: | |
c8422608 AM |
9 | * IBM - Initial API and implementation |
10 | * Bernd Hufmann - Updated for TMF | |
73005152 | 11 | **********************************************************************/ |
c8422608 | 12 | |
2bdf0193 | 13 | package org.eclipse.tracecompass.tmf.ui.views.uml2sd.core; |
73005152 BH |
14 | |
15 | import java.util.ArrayList; | |
16 | import java.util.Arrays; | |
17 | import java.util.Comparator; | |
18 | import java.util.HashMap; | |
19 | import java.util.Iterator; | |
20 | import java.util.List; | |
eb63f5ff | 21 | import java.util.Map; |
73005152 | 22 | |
2bdf0193 AM |
23 | import org.eclipse.tracecompass.internal.tmf.ui.TmfUiTracer; |
24 | import org.eclipse.tracecompass.tmf.ui.views.uml2sd.drawings.IGC; | |
25 | import org.eclipse.tracecompass.tmf.ui.views.uml2sd.preferences.ISDPreferences; | |
26 | import org.eclipse.tracecompass.tmf.ui.views.uml2sd.preferences.SDViewPref; | |
73005152 BH |
27 | |
28 | /** | |
29 | * The base class used for all UML2 graph nodes displayed in the Sequence Diagram SDWidget. | |
a55887ca | 30 | * |
73005152 BH |
31 | * @author sveyrier |
32 | * @version 1.0 | |
33 | */ | |
73005152 BH |
34 | public abstract class GraphNode { |
35 | ||
42618bb1 | 36 | private static final String UI_DELIMITER = "*****************************\n"; //$NON-NLS-1$ |
df0b8ff4 BH |
37 | // ------------------------------------------------------------------------ |
38 | // Attributes | |
39 | // ------------------------------------------------------------------------ | |
40 | /** | |
41 | * The start event occurrence. | |
42 | */ | |
cab6c8ff | 43 | private int fStartEventOccurrence = 0; |
df0b8ff4 BH |
44 | /** |
45 | * The event event occurrence. | |
46 | */ | |
cab6c8ff | 47 | private int fEndEventOccurrence = 0; |
73005152 BH |
48 | /** |
49 | * Preference ColorId to use to draw font | |
50 | */ | |
cab6c8ff | 51 | private String fPrefId = ISDPreferences.PREF_SYNC_MESS; |
73005152 BH |
52 | /** |
53 | * The selection state of the graph node. | |
54 | */ | |
cab6c8ff | 55 | private boolean fSelected = false; |
73005152 BH |
56 | /** |
57 | * The focus state of the graph node. | |
58 | */ | |
cab6c8ff | 59 | private boolean fFocused = false; |
df0b8ff4 | 60 | /** |
a55887ca | 61 | * Flag to indicate whether node has children or not. |
df0b8ff4 | 62 | */ |
cab6c8ff | 63 | private boolean fHasChilden = false; |
73005152 BH |
64 | /** |
65 | * The graph node name used to label the graph node in the View. | |
66 | */ | |
cab6c8ff | 67 | private String fName = ""; //$NON-NLS-1$ |
df0b8ff4 BH |
68 | /** |
69 | * A map from node name to graph node. | |
70 | */ | |
cab6c8ff | 71 | private Map<String, List<GraphNode>> fNodes; |
df0b8ff4 BH |
72 | /** |
73 | * A map from node name to graph node for forward sorting | |
74 | */ | |
cab6c8ff | 75 | private Map<String, List<GraphNode>> fForwardNodes; |
df0b8ff4 BH |
76 | /** |
77 | * A map from node name to graph node for backwards sorting. | |
78 | */ | |
cab6c8ff | 79 | private Map<String, List<GraphNode>> fBackwardNodes; |
df0b8ff4 BH |
80 | /** |
81 | * A map from node name to index. | |
82 | */ | |
cab6c8ff | 83 | private Map<String, Integer> fIndexes; |
df0b8ff4 | 84 | /** |
cab6c8ff | 85 | * A map from node name to flag for forwards sorting. |
df0b8ff4 | 86 | */ |
cab6c8ff | 87 | private Map<String, Boolean> fForwardSort; |
df0b8ff4 | 88 | /** |
cab6c8ff | 89 | * A map from node name to flag for backwards sorting. |
df0b8ff4 | 90 | */ |
cab6c8ff | 91 | private Map<String, Boolean> fBackwardSort; |
73005152 | 92 | |
df0b8ff4 BH |
93 | // ------------------------------------------------------------------------ |
94 | // Methods | |
95 | // ------------------------------------------------------------------------ | |
a55887ca | 96 | |
73005152 BH |
97 | /** |
98 | * Reset the internal index of the first visible GraphNode for each ordered GraphNode lists | |
73005152 BH |
99 | */ |
100 | public void resetIndex() { | |
eb63f5ff | 101 | if (!fHasChilden) { |
73005152 | 102 | return; |
df0b8ff4 BH |
103 | } |
104 | ||
eb63f5ff | 105 | Iterator<String> it = fIndexes.keySet().iterator(); |
73005152 BH |
106 | while (it.hasNext()) { |
107 | String nodeType = it.next(); | |
eb63f5ff | 108 | fIndexes.put(nodeType, Integer.valueOf(0)); |
73005152 BH |
109 | } |
110 | } | |
111 | ||
112 | /** | |
113 | * Add a GraphNode into the receiver | |
a55887ca | 114 | * |
73005152 BH |
115 | * @param nodeToAdd the node to add |
116 | */ | |
117 | public void addNode(GraphNode nodeToAdd) { | |
eb63f5ff | 118 | if (!fHasChilden) { |
507b1336 AM |
119 | fNodes = new HashMap<>(2); |
120 | fForwardNodes = new HashMap<>(2); | |
121 | fBackwardNodes = new HashMap<>(2); | |
122 | fIndexes = new HashMap<>(2); | |
123 | fBackwardSort = new HashMap<>(2); | |
124 | fForwardSort = new HashMap<>(2); | |
eb63f5ff | 125 | fHasChilden = true; |
73005152 BH |
126 | } |
127 | ||
128 | // Nothing to add | |
df0b8ff4 | 129 | if (nodeToAdd == null) { |
73005152 | 130 | return; |
df0b8ff4 | 131 | } |
73005152 | 132 | |
eb63f5ff BH |
133 | if (fNodes.get(nodeToAdd.getArrayId()) == null) { |
134 | fNodes.put(nodeToAdd.getArrayId(), new ArrayList<GraphNode>(1)); | |
135 | fIndexes.put(nodeToAdd.getArrayId(), Integer.valueOf(0)); | |
136 | fForwardNodes.put(nodeToAdd.getArrayId(), new ArrayList<GraphNode>(1)); | |
3145ec83 | 137 | fForwardSort.put(nodeToAdd.getArrayId(), Boolean.FALSE); |
73005152 | 138 | if (nodeToAdd.getBackComparator() != null) { |
eb63f5ff | 139 | fBackwardNodes.put(nodeToAdd.getArrayId(), new ArrayList<GraphNode>(1)); |
3145ec83 | 140 | fBackwardSort.put(nodeToAdd.getArrayId(), Boolean.FALSE); |
73005152 BH |
141 | } |
142 | } | |
143 | ||
abbdd66a | 144 | List<GraphNode> fNodeList = fForwardNodes.get(nodeToAdd.getArrayId()); |
73005152 | 145 | List<GraphNode> bNodeList = null; |
eb63f5ff | 146 | if (fBackwardNodes != null) { |
abbdd66a | 147 | bNodeList = fBackwardNodes.get(nodeToAdd.getArrayId()); |
df0b8ff4 | 148 | } |
73005152 BH |
149 | if (fNodeList != null && fNodeList.size() > 0) { |
150 | // check if the nodes are added y ordered | |
151 | // if not, tag the list to sort it later (during draw) | |
abbdd66a | 152 | GraphNode node = fNodeList.get(fNodeList.size() - 1); |
73005152 BH |
153 | Comparator<GraphNode> fcomp = nodeToAdd.getComparator(); |
154 | Comparator<GraphNode> bcomp = nodeToAdd.getBackComparator(); | |
f9a8715c | 155 | if ((fcomp != null) && (fcomp.compare(node, nodeToAdd) > 0)) { |
3145ec83 | 156 | fForwardSort.put(nodeToAdd.getArrayId(), Boolean.TRUE); |
73005152 | 157 | } |
f9a8715c | 158 | if ((bcomp != null) && (bcomp.compare(node, nodeToAdd) > 0)) { |
3145ec83 | 159 | fBackwardSort.put(nodeToAdd.getArrayId(), Boolean.TRUE); |
73005152 BH |
160 | } |
161 | } | |
162 | ||
163 | if (fNodeList == null) { | |
507b1336 | 164 | fNodeList = new ArrayList<>(); |
73005152 BH |
165 | } |
166 | ||
167 | fNodeList.add(nodeToAdd); | |
eb63f5ff BH |
168 | fNodes.put(nodeToAdd.getArrayId(), fNodeList); |
169 | fForwardNodes.put(nodeToAdd.getArrayId(), fNodeList); | |
64636df8 | 170 | if ((bNodeList != null) && (nodeToAdd.getBackComparator() != null)) { |
73005152 | 171 | bNodeList.add(nodeToAdd); |
eb63f5ff | 172 | fBackwardNodes.put(nodeToAdd.getArrayId(), bNodeList); |
73005152 BH |
173 | } |
174 | } | |
175 | ||
176 | /** | |
177 | * Set the graph node name.<br> | |
178 | * It is the name display in the view to label the graph node. | |
a55887ca | 179 | * |
0d9a6d76 | 180 | * @param nodeName the name to set |
73005152 BH |
181 | */ |
182 | public void setName(String nodeName) { | |
eb63f5ff | 183 | fName = nodeName; |
73005152 BH |
184 | } |
185 | ||
186 | /** | |
187 | * Returns the graph node name.<br> | |
188 | * It is the name display in the view to label the graph node. | |
a55887ca | 189 | * |
73005152 BH |
190 | * @return the graph node name |
191 | */ | |
192 | public String getName() { | |
eb63f5ff | 193 | return fName; |
73005152 BH |
194 | } |
195 | ||
196 | /** | |
197 | * Tags the the graph node has selected.<br> | |
198 | * WARNING: This method is only used to draw the graph node using the system selection colors. <br> | |
199 | * To use the complete SDViewer selection mechanism (selection management, notification, etc..) see SDWidget class | |
a55887ca | 200 | * |
2bdf0193 AM |
201 | * @see org.eclipse.tracecompass.tmf.ui.views.uml2sd.SDWidget#addSelection(GraphNode) |
202 | * @see org.eclipse.tracecompass.tmf.ui.views.uml2sd.SDWidget#removeSelection(GraphNode) | |
203 | * @see org.eclipse.tracecompass.tmf.ui.views.uml2sd.SDWidget#clearSelection() | |
73005152 BH |
204 | * @param selection - true to set selected, false to set unselected |
205 | */ | |
206 | public void setSelected(boolean selection) { | |
eb63f5ff | 207 | fSelected = selection; |
73005152 BH |
208 | } |
209 | ||
210 | /** | |
211 | * Tags the the graph node as focused.<br> | |
212 | * WARNING: This method is only used to draw the graph node using the system focus style. <br> | |
213 | * To use the complete SDViewer focus mechanism see SDWidget class | |
a55887ca | 214 | * |
2bdf0193 AM |
215 | * @see org.eclipse.tracecompass.tmf.ui.views.uml2sd.SDWidget#addSelection(GraphNode) |
216 | * @see org.eclipse.tracecompass.tmf.ui.views.uml2sd.SDWidget#removeSelection(GraphNode) | |
217 | * @see org.eclipse.tracecompass.tmf.ui.views.uml2sd.SDWidget#clearSelection() | |
73005152 BH |
218 | * @param focus - true to set focued, false otherwise |
219 | */ | |
220 | public void setFocused(boolean focus) { | |
eb63f5ff | 221 | fFocused = focus; |
73005152 BH |
222 | } |
223 | ||
224 | /** | |
225 | * Returns true if the graph node is selected, false otherwise.<br> | |
226 | * The returned value is used to highlight the graph node in the View. | |
a55887ca | 227 | * |
73005152 | 228 | * @return true if selected, false otherwise |
73005152 BH |
229 | */ |
230 | public boolean isSelected() { | |
eb63f5ff | 231 | return fSelected; |
73005152 BH |
232 | } |
233 | ||
234 | /** | |
235 | * Returns true if the graph node is focused, false otherwise.<br> | |
236 | * The returned value is used to highlight the graph node in the View. | |
a55887ca AM |
237 | * |
238 | * @return true if focused, false otherwise | |
73005152 BH |
239 | */ |
240 | public boolean hasFocus() { | |
eb63f5ff | 241 | return fFocused; |
73005152 BH |
242 | } |
243 | ||
244 | /** | |
a55887ca AM |
245 | * Returns true if the graph node contains the point given in parameter, |
246 | * return false otherwise. | |
247 | * | |
248 | * @param x | |
249 | * the x coordinate of the point to test containment | |
250 | * @param y | |
251 | * the y coordinate of the point to test containment | |
73005152 BH |
252 | * @return true if contained, false otherwise |
253 | */ | |
574f43ad | 254 | public abstract boolean contains(int x, int y); |
73005152 BH |
255 | |
256 | /** | |
257 | * Returns the x coordinate of the graph node | |
a55887ca | 258 | * |
73005152 BH |
259 | * @return the x coordinate |
260 | */ | |
574f43ad | 261 | public abstract int getX(); |
73005152 BH |
262 | |
263 | /** | |
264 | * Returns the y coordinate of the graph node | |
a55887ca | 265 | * |
73005152 BH |
266 | * @return the y coordinate |
267 | */ | |
574f43ad | 268 | public abstract int getY(); |
73005152 BH |
269 | |
270 | /** | |
271 | * Returns the graph node height | |
a55887ca | 272 | * |
73005152 BH |
273 | * @return the graph node height |
274 | */ | |
574f43ad | 275 | public abstract int getHeight(); |
73005152 BH |
276 | |
277 | /** | |
278 | * Returns the graph node width | |
a55887ca | 279 | * |
73005152 BH |
280 | * @return the graph node width |
281 | */ | |
574f43ad | 282 | public abstract int getWidth(); |
73005152 BH |
283 | |
284 | /** | |
285 | * Draws the graph node in the given context | |
a55887ca | 286 | * |
73005152 BH |
287 | * @param context the graphical context to draw in |
288 | */ | |
574f43ad | 289 | protected abstract void draw(IGC context); |
73005152 BH |
290 | |
291 | /** | |
a55887ca AM |
292 | * Returns the GraphNode visibility for the given visible area. Wrong |
293 | * visibility calculation, may strongly impact drawing performance | |
294 | * | |
0d9a6d76 | 295 | * @param x |
a55887ca | 296 | * The X coordinate |
0d9a6d76 | 297 | * @param y |
a55887ca | 298 | * The Y coordinate |
0d9a6d76 | 299 | * @param width |
a55887ca | 300 | * The width of the area |
0d9a6d76 | 301 | * @param height |
a55887ca AM |
302 | * The height of the area |
303 | * @return true if visible, false otherwise | |
73005152 BH |
304 | */ |
305 | public boolean isVisible(int x, int y, int width, int height) { | |
306 | return true; | |
307 | } | |
308 | ||
309 | /** | |
a55887ca AM |
310 | * Return a comparator to sort the GraphNode of the same type This |
311 | * comparator is used to order the GraphNode array of the given node type. | |
312 | * (see getArrayId). | |
313 | * | |
73005152 BH |
314 | * @return the comparator |
315 | */ | |
316 | public Comparator<GraphNode> getComparator() { | |
317 | return null; | |
318 | } | |
319 | ||
320 | /** | |
a55887ca AM |
321 | * If needed, return a different comparator to backward scan the GraphNode |
322 | * array | |
323 | * | |
73005152 BH |
324 | * @return the backward comparator or null if not needed |
325 | */ | |
326 | public Comparator<GraphNode> getBackComparator() { | |
327 | return null; | |
328 | } | |
329 | ||
330 | /** | |
331 | * Compare two graphNodes | |
a55887ca AM |
332 | * |
333 | * @param node | |
334 | * the node to compare to | |
73005152 BH |
335 | * @return true if equal false otherwise |
336 | */ | |
337 | public boolean isSameAs(GraphNode node) { | |
338 | return false; | |
339 | } | |
340 | ||
341 | /** | |
342 | * Return the node type for all class instances. This id is used to store the same nodes kind in the same ordered | |
343 | * array. | |
a55887ca | 344 | * |
73005152 BH |
345 | * @return the node type identifier |
346 | */ | |
574f43ad | 347 | public abstract String getArrayId(); |
73005152 BH |
348 | |
349 | /** | |
350 | * Return true if the distance from the GraphNode to the given point is positive | |
a55887ca | 351 | * |
73005152 BH |
352 | * @param x the point x coordinate |
353 | * @param y the point y coordinate | |
354 | * @return true if positive false otherwise | |
355 | */ | |
356 | public boolean positiveDistanceToPoint(int x, int y) { | |
357 | return false; | |
358 | } | |
359 | ||
360 | /** | |
361 | * Returns the graph node which contains the point given in parameter WARNING: Only graph nodes in the current | |
362 | * visible area can be returned | |
a55887ca | 363 | * |
73005152 BH |
364 | * @param x the x coordinate of the point to test |
365 | * @param y the y coordinate of the point to test | |
366 | * @return the graph node containing the point given in parameter, null otherwise | |
367 | */ | |
368 | public GraphNode getNodeAt(int x, int y) { | |
369 | GraphNode toReturn = null; | |
370 | ||
eb63f5ff | 371 | if (!fHasChilden) { |
73005152 | 372 | return null; |
df0b8ff4 | 373 | } |
73005152 | 374 | |
73005152 | 375 | GraphNode node = null; |
22740f50 JCK |
376 | for (Map.Entry<String, List<GraphNode>> entry : fNodes.entrySet()) { |
377 | List<GraphNode> list = entry.getValue(); | |
378 | int index = fIndexes.get(entry.getKey()).intValue(); | |
73005152 | 379 | node = getNodeFromListAt(x, y, list, index); |
df0b8ff4 | 380 | if (toReturn == null) { |
73005152 | 381 | toReturn = node; |
df0b8ff4 | 382 | } |
73005152 BH |
383 | if (node != null) { |
384 | GraphNode internalNode = node.getNodeAt(x, y); | |
df0b8ff4 | 385 | if (internalNode != null) { |
73005152 | 386 | return internalNode; |
df0b8ff4 | 387 | } else if (Math.abs(node.getWidth()) < Math.abs(toReturn.getWidth()) || Math.abs(node.getHeight()) < Math.abs(toReturn.getHeight())) { |
73005152 | 388 | toReturn = node; |
df0b8ff4 | 389 | } |
73005152 BH |
390 | } |
391 | } | |
392 | return toReturn; | |
393 | } | |
394 | ||
df0b8ff4 BH |
395 | /** |
396 | * Gets node list from node A to node B | |
397 | ||
398 | * @param from A from node | |
399 | * @param to A to node | |
400 | * @return the list of nodes | |
401 | */ | |
eb63f5ff | 402 | public List<GraphNode> getNodeList(GraphNode from, GraphNode to) { |
507b1336 | 403 | List<GraphNode> result = new ArrayList<>(); |
73005152 BH |
404 | |
405 | if (from != null) { | |
406 | result.add(from); | |
407 | } else if (to != null) { | |
408 | result.add(to); | |
409 | } | |
410 | ||
eb63f5ff | 411 | if ((from == null) || (to == null)) { |
73005152 | 412 | return result; |
df0b8ff4 | 413 | } |
73005152 | 414 | |
df0b8ff4 | 415 | if (from == to) { |
73005152 | 416 | return result; |
df0b8ff4 | 417 | } |
73005152 BH |
418 | |
419 | int startX = Math.min(from.getX(), Math.min(to.getX(), Math.min(from.getX() + from.getWidth(), to.getX() + to.getWidth()))); | |
420 | int endX = Math.max(from.getX(), Math.max(to.getX(), Math.max(from.getX() + from.getWidth(), to.getX() + to.getWidth()))); | |
421 | int startY = Math.min(from.getY(), Math.min(to.getY(), Math.min(from.getY() + from.getHeight(), to.getY() + to.getHeight()))); | |
422 | int endY = Math.max(from.getY(), Math.max(to.getY(), Math.max(from.getY() + from.getHeight(), to.getY() + to.getHeight()))); | |
423 | ||
eb63f5ff | 424 | if (!fHasChilden) { |
73005152 | 425 | return result; |
df0b8ff4 | 426 | } |
73005152 | 427 | |
22740f50 JCK |
428 | for (Map.Entry<String, List<GraphNode>> entry : fNodes.entrySet()) { |
429 | List<GraphNode> nodesList = entry.getValue(); | |
df0b8ff4 | 430 | if (nodesList == null || nodesList.isEmpty()) { |
73005152 | 431 | return null; |
df0b8ff4 | 432 | } |
73005152 | 433 | for (int i = 0; i < nodesList.size(); i++) { |
abbdd66a | 434 | GraphNode node = nodesList.get(i); |
73005152 BH |
435 | int nw = node.getWidth(); |
436 | int nh = node.getHeight(); | |
437 | int nx = node.getX(); | |
438 | int ny = node.getY(); | |
df0b8ff4 | 439 | if (contains(startX, startY, endX - startX, endY - startY, nx + 1, ny + 1) && contains(startX, startY, endX - startX, endY - startY, nx + nw - 2, ny + nh - 2)) { |
73005152 | 440 | result.add(node); |
df0b8ff4 | 441 | } |
73005152 BH |
442 | result.addAll(node.getNodeList(from, to)); |
443 | } | |
444 | } | |
eb63f5ff BH |
445 | |
446 | if (!result.contains(to)) { | |
73005152 | 447 | result.add(to); |
df0b8ff4 | 448 | } |
73005152 BH |
449 | return result; |
450 | } | |
451 | ||
452 | /** | |
453 | * Returns the graph node which contains the point given in parameter for the given graph node list and starting the | |
454 | * iteration at the given index<br> | |
455 | * WARNING: Only graph nodes with smaller coordinates than the current visible area can be returned.<br> | |
a55887ca | 456 | * |
73005152 BH |
457 | * @param x the x coordinate of the point to test |
458 | * @param y the y coordinate of the point to test | |
459 | * @param list the list to search in | |
460 | * @param fromIndex list browsing starting point | |
461 | * @return the graph node containing the point given in parameter, null otherwise | |
462 | */ | |
463 | protected GraphNode getNodeFromListAt(int x, int y, List<GraphNode> list, int fromIndex) { | |
df0b8ff4 | 464 | if (list == null) { |
73005152 | 465 | return null; |
df0b8ff4 | 466 | } |
73005152 | 467 | for (int i = fromIndex; i < list.size(); i++) { |
abbdd66a | 468 | GraphNode node = list.get(i); |
df0b8ff4 | 469 | if (node.contains(x, y)) { |
73005152 | 470 | return node; |
df0b8ff4 | 471 | } |
73005152 BH |
472 | } |
473 | return null; | |
474 | } | |
475 | ||
476 | /** | |
477 | * Returns the start event occurrence attached to this graphNode. | |
a55887ca | 478 | * |
73005152 BH |
479 | * @return the start event occurrence attached to the graphNode |
480 | */ | |
481 | public int getStartOccurrence() { | |
eb63f5ff | 482 | return fStartEventOccurrence; |
73005152 BH |
483 | } |
484 | ||
485 | /** | |
486 | * Returns the end event occurrence attached to this graphNode | |
a55887ca | 487 | * |
73005152 BH |
488 | * @return the start event occurrence attached to the graphNode |
489 | */ | |
490 | public int getEndOccurrence() { | |
eb63f5ff | 491 | return fEndEventOccurrence; |
73005152 BH |
492 | } |
493 | ||
494 | /** | |
495 | * Computes the index of the first visible GraphNode for each ordered graph node lists depending on the visible area | |
496 | * given in parameter | |
a55887ca | 497 | * |
73005152 BH |
498 | * @param x visible area top left corner x coordinate |
499 | * @param y visible area top left corner y coordinate | |
500 | * @param width visible area width | |
501 | * @param height visible area height | |
502 | */ | |
503 | public void updateIndex(int x, int y, int width, int height) { | |
eb63f5ff | 504 | if (!fHasChilden) { |
73005152 | 505 | return; |
df0b8ff4 | 506 | } |
73005152 | 507 | if(TmfUiTracer.isIndexTraced()) { |
42618bb1 | 508 | TmfUiTracer.traceIndex(UI_DELIMITER); |
73005152 BH |
509 | TmfUiTracer.traceIndex("Visible area position in virtual screen (x,y)= " + x + " " + y + "\n\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
510 | } | |
511 | ||
22740f50 JCK |
512 | for (Map.Entry<String, List<GraphNode>> entry : fNodes.entrySet()) { |
513 | String nodeType = entry.getKey(); | |
73005152 | 514 | int direction = 1; |
abbdd66a | 515 | int drawIndex = fIndexes.get(nodeType).intValue(); |
73005152 BH |
516 | /* |
517 | * if (x==0) { drawIndex = 0; indexes.put(nodeType,new Integer(drawIndex)); } | |
518 | */ | |
22740f50 JCK |
519 | if ((entry.getValue() != null) && (entry.getValue().size() > 1)) { |
520 | if (entry.getValue().get(drawIndex).positiveDistanceToPoint(x, y)) { | |
73005152 | 521 | direction = -1; |
df0b8ff4 | 522 | } |
73005152 | 523 | |
df0b8ff4 | 524 | if (drawIndex == 0) { |
73005152 | 525 | direction = 1; |
df0b8ff4 | 526 | } |
73005152 | 527 | |
eb63f5ff | 528 | if ((direction == -1) && (fBackwardNodes.get(nodeType) != null)) { |
22740f50 | 529 | GraphNode currentNode = entry.getValue().get(drawIndex); |
abbdd66a | 530 | drawIndex = Arrays.binarySearch(fBackwardNodes.get(nodeType).toArray(new GraphNode[fBackwardNodes.get(nodeType).size()]), |
22740f50 JCK |
531 | entry.getValue().get(drawIndex), currentNode.getBackComparator()); |
532 | entry.setValue(fBackwardNodes.get(nodeType)); | |
73005152 BH |
533 | if (drawIndex < 0) { |
534 | drawIndex = 0; | |
535 | direction = 1; | |
df0b8ff4 | 536 | } else { |
22740f50 | 537 | entry.setValue(fBackwardNodes.get(nodeType)); |
df0b8ff4 | 538 | } |
73005152 BH |
539 | } |
540 | GraphNode prev = null; | |
541 | ||
22740f50 | 542 | for (int i = drawIndex; i < entry.getValue().size() && i >= 0; i = i + direction) { |
73005152 | 543 | drawIndex = i; |
eb63f5ff | 544 | fIndexes.put(nodeType, Integer.valueOf(i)); |
73005152 | 545 | |
22740f50 | 546 | GraphNode currentNode = entry.getValue().get(i); |
73005152 | 547 | |
df0b8ff4 | 548 | if (prev == null) { |
73005152 | 549 | prev = currentNode; |
df0b8ff4 | 550 | } |
73005152 BH |
551 | |
552 | Comparator<GraphNode> comp = currentNode.getComparator(); | |
eb63f5ff | 553 | Map<String, Boolean> sort = fForwardSort; |
73005152 | 554 | |
eb63f5ff BH |
555 | if ((direction == -1) && (currentNode.getBackComparator() != null)) { |
556 | comp = currentNode.getBackComparator(); | |
557 | sort = fBackwardSort; | |
73005152 BH |
558 | } |
559 | ||
22740f50 JCK |
560 | if (i < entry.getValue().size() - 1) { |
561 | GraphNode next = entry.getValue().get(i + 1); | |
73005152 | 562 | |
df0b8ff4 | 563 | if ((comp != null) && (comp.compare(currentNode, next) > 0)) { |
3145ec83 | 564 | sort.put(nodeType, Boolean.TRUE); |
df0b8ff4 | 565 | } |
73005152 BH |
566 | } |
567 | if (direction == 1) { | |
22740f50 | 568 | if (entry.getValue().get(i).positiveDistanceToPoint(x, y)) { |
73005152 | 569 | break; |
df0b8ff4 | 570 | } |
73005152 BH |
571 | } else { |
572 | if (currentNode.getBackComparator() == null) { | |
573 | if // (currentNode.isVisible(x,y,width,height) | |
df0b8ff4 | 574 | (!currentNode.positiveDistanceToPoint(x, y)) { |
73005152 | 575 | break; |
df0b8ff4 | 576 | } |
73005152 BH |
577 | } else { |
578 | if (currentNode.isVisible(x, y, width, height) && !currentNode.positiveDistanceToPoint(x, y)) { | |
df0b8ff4 | 579 | if ((comp != null) && (comp.compare(currentNode, prev) <= 0)) { |
73005152 | 580 | break; |
df0b8ff4 BH |
581 | } |
582 | } else if ((comp != null) && (comp.compare(currentNode, prev) <= 0)) { | |
73005152 | 583 | prev = currentNode; |
df0b8ff4 | 584 | } |
73005152 BH |
585 | } |
586 | } | |
587 | } | |
588 | ||
22740f50 | 589 | entry.setValue(fForwardNodes.get(nodeType)); |
eb63f5ff | 590 | if ((fBackwardNodes.get(nodeType) != null) && (direction == -1)) { |
73005152 | 591 | // nodes.put(nodeType,fnodes.get(nodeType)); |
abbdd66a | 592 | int index = fIndexes.get(nodeType).intValue(); |
22740f50 | 593 | List<GraphNode> list = entry.getValue(); |
abbdd66a AM |
594 | List<GraphNode> backList = fBackwardNodes.get(nodeType); |
595 | GraphNode currentNode = (backList.get(index)); | |
73005152 | 596 | if (index > 0) { |
eb63f5ff | 597 | index = Arrays.binarySearch(list.toArray(new GraphNode[list.size()]), backList.get(index), currentNode.getComparator()); |
df0b8ff4 | 598 | if (index < 0) { |
73005152 | 599 | index = 0; |
df0b8ff4 | 600 | } |
eb63f5ff | 601 | fIndexes.put(nodeType, Integer.valueOf(index)); |
73005152 BH |
602 | } |
603 | } | |
604 | ||
22740f50 JCK |
605 | for (int i = drawIndex; i < entry.getValue().size() && i >= 0; i++) { |
606 | GraphNode toDraw = entry.getValue().get(i); | |
73005152 | 607 | toDraw.updateIndex(x, y, width, height); |
df0b8ff4 | 608 | if (!toDraw.isVisible(x, y, width, height)) { |
73005152 | 609 | break; |
df0b8ff4 | 610 | } |
73005152 BH |
611 | } |
612 | } | |
613 | if (TmfUiTracer.isIndexTraced()) { | |
a55887ca | 614 | TmfUiTracer.traceIndex("First drawn " + nodeType + " index = " + drawIndex + "\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
73005152 BH |
615 | TmfUiTracer.traceIndex(nodeType + " found in " + 0 + " iterations\n"); //$NON-NLS-1$ //$NON-NLS-2$ |
616 | } | |
617 | } | |
618 | ||
619 | if (TmfUiTracer.isIndexTraced()) { | |
42618bb1 | 620 | TmfUiTracer.traceIndex(UI_DELIMITER); |
73005152 BH |
621 | } |
622 | } | |
623 | ||
624 | /** | |
625 | * Draws the children nodes on the given context.<br> | |
626 | * This method start width GraphNodes ordering if needed.<br> | |
627 | * After, depending on the visible area, only visible GraphNodes are drawn.<br> | |
a55887ca | 628 | * |
73005152 | 629 | * @param context the context to draw to |
2bdf0193 | 630 | * @see org.eclipse.tracecompass.tmf.ui.views.uml2sd.core.GraphNode#draw(IGC) |
73005152 BH |
631 | */ |
632 | protected void drawChildenNodes(IGC context) { | |
633 | ||
eb63f5ff | 634 | if (!fHasChilden) { |
73005152 | 635 | return; |
df0b8ff4 | 636 | } |
73005152 | 637 | // If the nodes have not been added ordered, the array is ordered |
22740f50 JCK |
638 | for (Map.Entry<String, Boolean> entry : fForwardSort.entrySet()) { |
639 | String nodeType = entry.getKey(); | |
640 | boolean sort = entry.getValue().booleanValue(); | |
73005152 | 641 | if (sort) { |
abbdd66a AM |
642 | GraphNode[] temp = fForwardNodes.get(nodeType).toArray(new GraphNode[fForwardNodes.get(nodeType).size()]); |
643 | GraphNode node = fNodes.get(nodeType).get(0); | |
73005152 | 644 | Arrays.sort(temp, node.getComparator()); |
22740f50 | 645 | entry.setValue(Boolean.FALSE); |
eb63f5ff BH |
646 | fNodes.put(nodeType, Arrays.asList(temp)); |
647 | fForwardNodes.put(nodeType, Arrays.asList(temp)); | |
df0b8ff4 | 648 | if (TmfUiTracer.isSortingTraced()) { |
73005152 | 649 | TmfUiTracer.traceSorting(nodeType + " array sorted\n"); //$NON-NLS-1$ |
df0b8ff4 | 650 | } |
73005152 BH |
651 | } |
652 | } | |
653 | ||
22740f50 JCK |
654 | for (Map.Entry<String, Boolean> entry : fBackwardSort.entrySet()) { |
655 | String nodeType = entry.getKey(); | |
656 | boolean sort = entry.getValue().booleanValue(); | |
73005152 | 657 | if (sort) { |
abbdd66a AM |
658 | GraphNode[] temp = fBackwardNodes.get(nodeType).toArray(new GraphNode[fBackwardNodes.get(nodeType).size()]); |
659 | GraphNode node = fNodes.get(nodeType).get(0); | |
73005152 | 660 | Arrays.sort(temp, node.getBackComparator()); |
22740f50 | 661 | entry.setValue(Boolean.FALSE); |
eb63f5ff | 662 | fBackwardNodes.put(nodeType, Arrays.asList(temp)); |
df0b8ff4 | 663 | if (TmfUiTracer.isSortingTraced()) { |
73005152 | 664 | TmfUiTracer.traceSorting(nodeType + " back array sorted\n"); //$NON-NLS-1$ |
df0b8ff4 | 665 | } |
73005152 BH |
666 | } |
667 | } | |
668 | ||
669 | if (TmfUiTracer.isDisplayTraced()) { | |
42618bb1 | 670 | TmfUiTracer.traceDisplay(UI_DELIMITER); |
73005152 BH |
671 | } |
672 | ||
673 | int arrayStep = 1; | |
df0b8ff4 | 674 | if ((Metrics.getMessageFontHeigth() + Metrics.MESSAGES_NAME_SPACING * 2) * context.getZoom() < Metrics.MESSAGE_SIGNIFICANT_VSPACING) { |
73005152 | 675 | arrayStep = Math.round(Metrics.MESSAGE_SIGNIFICANT_VSPACING / ((Metrics.getMessageFontHeigth() + Metrics.MESSAGES_NAME_SPACING * 2) * context.getZoom())); |
df0b8ff4 | 676 | } |
73005152 BH |
677 | |
678 | int count = 0; | |
eb63f5ff | 679 | Iterator<String> it3 = fForwardSort.keySet().iterator(); |
73005152 BH |
680 | while (it3.hasNext()) { |
681 | count = 0; | |
682 | Object nodeType = it3.next(); | |
abbdd66a | 683 | GraphNode node = fNodes.get(nodeType).get(0); |
3145ec83 | 684 | context.setFont(SDViewPref.getInstance().getFont(node.fPrefId)); |
abbdd66a AM |
685 | int index = fIndexes.get(nodeType).intValue(); |
686 | count = drawNodes(context, fNodes.get(nodeType), index, arrayStep); | |
df0b8ff4 | 687 | if (TmfUiTracer.isDisplayTraced()) { |
73005152 | 688 | TmfUiTracer.traceDisplay(count + " " + nodeType + " drawn, starting from index " + index + "\r\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
df0b8ff4 | 689 | } |
73005152 BH |
690 | } |
691 | if (TmfUiTracer.isDisplayTraced()) { | |
42618bb1 | 692 | TmfUiTracer.traceDisplay(UI_DELIMITER); |
73005152 BH |
693 | } |
694 | ||
695 | } | |
696 | ||
697 | /** | |
698 | * Draw the GraphNode stored in the given list, starting at index startIndex with the given step | |
a55887ca | 699 | * |
73005152 BH |
700 | * @param context the context to draw to |
701 | * @param list the GraphNodes list | |
702 | * @param startIndex the start index | |
703 | * @param step the step to browse the list | |
704 | * @return the number of GraphNodes drawn | |
705 | */ | |
706 | protected int drawNodes(IGC context, List<GraphNode> list, int startIndex, int step) { | |
eb63f5ff | 707 | if (!fHasChilden) { |
73005152 | 708 | return 0; |
df0b8ff4 | 709 | } |
73005152 BH |
710 | |
711 | GraphNode last = null; | |
712 | int nodesCount = 0; | |
54cb184d | 713 | if (list.isEmpty()) { |
73005152 | 714 | return 0; |
df0b8ff4 | 715 | } |
73005152 | 716 | |
abbdd66a | 717 | GraphNode node = list.get(0); |
3145ec83 | 718 | context.setFont(SDViewPref.getInstance().getFont(node.fPrefId)); |
73005152 BH |
719 | Comparator<GraphNode> comparator = node.getComparator(); |
720 | for (int i = startIndex; i < list.size(); i = i + step) { | |
abbdd66a | 721 | GraphNode toDraw = list.get(i); |
73005152 | 722 | if (i < list.size() - 1) { |
abbdd66a | 723 | GraphNode next = list.get(i + 1); |
f9a8715c | 724 | if ((comparator != null) && (comparator.compare(toDraw, next) > 0)) { |
3145ec83 | 725 | fForwardSort.put(next.getArrayId(), Boolean.TRUE); |
73005152 BH |
726 | } |
727 | } | |
728 | int cx = context.getContentsX(); | |
729 | int cy = context.getContentsY(); | |
730 | int cw = context.getVisibleWidth(); | |
731 | int ch = context.getVisibleHeight(); | |
732 | // The arrays should be ordered, no needs to continue for this one | |
df0b8ff4 | 733 | if (!toDraw.isVisible(cx, cy, cw, ch) && toDraw.positiveDistanceToPoint(cx + cw, cy + ch)) { |
73005152 | 734 | break; |
df0b8ff4 | 735 | } |
73005152 BH |
736 | // ***Common*** nodes visibility |
737 | if ((!toDraw.isSameAs(last) || toDraw.isSelected()) && (toDraw.isVisible(context.getContentsX(), context.getContentsY(), context.getVisibleWidth(), context.getVisibleHeight()))) { | |
738 | nodesCount++; | |
a55887ca | 739 | |
73005152 | 740 | toDraw.draw(context); |
df0b8ff4 | 741 | if (hasFocus()) { |
73005152 | 742 | toDraw.drawFocus(context); |
df0b8ff4 | 743 | } |
73005152 BH |
744 | } |
745 | last = toDraw; | |
746 | } | |
747 | return nodesCount; | |
748 | } | |
749 | ||
df0b8ff4 BH |
750 | /** |
751 | * Draws the focus within the graphical context. | |
a55887ca | 752 | * |
df0b8ff4 | 753 | * @param context |
a55887ca | 754 | * The context |
df0b8ff4 | 755 | */ |
73005152 BH |
756 | public void drawFocus(IGC context) { |
757 | context.drawFocus(getX(), getY(), getWidth(), getHeight()); | |
758 | } | |
759 | ||
760 | /** | |
761 | * Determine if the given point (px,py) is contained in the rectangle (x,y,width,height) | |
a55887ca | 762 | * |
73005152 BH |
763 | * @param x the rectangle x coordinate |
764 | * @param y the rectangle y coordinate | |
765 | * @param width the rectangle width | |
766 | * @param height the rectangle height | |
767 | * @param px the x coordinate of the point to test | |
768 | * @param py the y coordinate of the point to test | |
769 | * @return true if contained false otherwise | |
770 | */ | |
771 | public static boolean contains(int x, int y, int width, int height, int px, int py) { | |
772 | int locX = x; | |
773 | int locY = y; | |
774 | int locWidth = width; | |
775 | int locHeight = height; | |
776 | ||
777 | if (width < 0) { | |
778 | locX = locX + width; | |
779 | locWidth = -locWidth; | |
780 | } | |
781 | ||
782 | if (height < 0) { | |
783 | locY = locY + height; | |
784 | locHeight = -locHeight; | |
785 | } | |
786 | return (px >= locX) && (py >= locY) && ((px - locX) <= locWidth) && ((py - locY) <= locHeight); | |
787 | } | |
cab6c8ff BH |
788 | |
789 | /** | |
790 | * Sets the start event occurrence attached to this graphNode. | |
791 | * | |
792 | * @param occurence | |
793 | * the start event occurrence attached to the graphNode | |
cab6c8ff BH |
794 | */ |
795 | protected void setStartOccurrence(int occurence) { | |
796 | fStartEventOccurrence = occurence; | |
797 | } | |
798 | ||
799 | /** | |
800 | * Sets the end event occurrence attached to this graphNode | |
801 | * | |
802 | * @param occurence | |
803 | * the start event occurrence attached to the graphNode | |
cab6c8ff BH |
804 | */ |
805 | protected void setEndOccurrence(int occurence) { | |
806 | fEndEventOccurrence = occurence; | |
807 | } | |
808 | ||
809 | /** | |
810 | * Sets the color preference id | |
811 | * @param id | |
812 | * The color preference id | |
cab6c8ff BH |
813 | */ |
814 | protected void setColorPrefId(String id) { | |
815 | fPrefId = id; | |
816 | } | |
817 | ||
818 | /** | |
819 | * Gets the color preference id | |
820 | * @return the color preference id | |
cab6c8ff BH |
821 | */ |
822 | protected String getColorPrefId() { | |
823 | return fPrefId; | |
824 | } | |
825 | ||
826 | /** | |
827 | * @return if node has children or not | |
cab6c8ff BH |
828 | */ |
829 | protected boolean hasChildren() { | |
830 | return fHasChilden; | |
831 | } | |
832 | ||
833 | /** | |
834 | * Sets the flag indicating where the node has children or not. | |
835 | * @param hasChildren | |
836 | * if node has children or not | |
cab6c8ff BH |
837 | */ |
838 | protected void hasChildren(boolean hasChildren) { | |
839 | fHasChilden = hasChildren; | |
840 | } | |
841 | /** | |
842 | * Returns a map from node name to graph node. | |
843 | * | |
844 | * @return map with children graph bodes | |
cab6c8ff BH |
845 | */ |
846 | protected Map<String, List<GraphNode>> getNodeMap() { | |
847 | return fNodes; | |
848 | } | |
849 | /** | |
850 | * Returns a map from node name to graph node for forward sorting | |
851 | * | |
852 | * @return forward sorting map | |
cab6c8ff BH |
853 | */ |
854 | protected Map<String, List<GraphNode>> getForwardNodes() { | |
855 | return fForwardNodes; | |
856 | } | |
857 | /** | |
858 | * Returns a map from node name to graph node for backwards sorting. | |
859 | * | |
860 | * @return backwards sorting map | |
cab6c8ff BH |
861 | */ |
862 | protected Map<String, List<GraphNode>> getBackwardNodes() { | |
863 | return fBackwardNodes; | |
864 | } | |
865 | /** | |
866 | * Returns a map from node name to index. | |
867 | * | |
868 | * @return map with node name to index | |
cab6c8ff BH |
869 | */ |
870 | protected Map<String, Integer> getIndexes() { | |
871 | return fIndexes; | |
872 | } | |
873 | ||
874 | /** | |
875 | * Returns a map from node name to sort flag for forwards sorting. | |
876 | * @return a map from node name to sort flag | |
cab6c8ff BH |
877 | */ |
878 | protected Map<String, Boolean> getForwardSortMap() { | |
879 | return fForwardSort; | |
880 | } | |
881 | /** | |
882 | * Returns a map from node name to flag for backwards sorting. | |
883 | * @return map from node name to flag for backwards sorting. | |
cab6c8ff BH |
884 | */ |
885 | protected Map<String, Boolean> getBackwardSortMap() { | |
886 | return fBackwardSort; | |
887 | } | |
73005152 | 888 | } |