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