Commit | Line | Data |
---|---|---|
73005152 | 1 | /********************************************************************** |
df0b8ff4 BH |
2 | * Copyright (c) 2005, 2008 IBM Corporation and others. |
3 | * Copyright (c) 2011, 2012 Ericsson. | |
4 | * | |
73005152 BH |
5 | * All rights reserved. This program and the accompanying materials |
6 | * are made available under the terms of the Eclipse Public License v1.0 | |
7 | * which accompanies this distribution, and is available at | |
8 | * http://www.eclipse.org/legal/epl-v10.html | |
73005152 BH |
9 | * |
10 | * Contributors: | |
11 | * IBM - Initial API and implementation | |
12 | * Bernd Hufmann - Updated for TMF | |
13 | **********************************************************************/ | |
14 | package org.eclipse.linuxtools.tmf.ui.views.uml2sd.core; | |
15 | ||
16 | import java.util.ArrayList; | |
17 | import java.util.Arrays; | |
18 | import java.util.Comparator; | |
19 | import java.util.HashMap; | |
20 | import java.util.Iterator; | |
21 | import java.util.List; | |
eb63f5ff | 22 | import java.util.Map; |
73005152 | 23 | |
d34665f9 | 24 | import org.eclipse.linuxtools.internal.tmf.ui.TmfUiTracer; |
73005152 | 25 | import org.eclipse.linuxtools.tmf.ui.views.uml2sd.drawings.IGC; |
df0b8ff4 | 26 | import org.eclipse.linuxtools.tmf.ui.views.uml2sd.preferences.ISDPreferences; |
3145ec83 | 27 | import org.eclipse.linuxtools.tmf.ui.views.uml2sd.preferences.SDViewPref; |
73005152 BH |
28 | |
29 | /** | |
30 | * The base class used for all UML2 graph nodes displayed in the Sequence Diagram SDWidget. | |
31 | * | |
32 | * @author sveyrier | |
33 | * @version 1.0 | |
34 | */ | |
73005152 BH |
35 | public abstract class GraphNode { |
36 | ||
df0b8ff4 BH |
37 | // ------------------------------------------------------------------------ |
38 | // Attributes | |
39 | // ------------------------------------------------------------------------ | |
40 | /** | |
41 | * The start event occurrence. | |
42 | */ | |
eb63f5ff | 43 | protected int fStartEventOccurrence = 0; |
df0b8ff4 BH |
44 | /** |
45 | * The event event occurrence. | |
46 | */ | |
eb63f5ff | 47 | protected int fEndEventOccurrence = 0; |
73005152 BH |
48 | /** |
49 | * Preference ColorId to use to draw font | |
50 | */ | |
eb63f5ff | 51 | public String fPrefId = ISDPreferences.PREF_SYNC_MESS; |
73005152 BH |
52 | /** |
53 | * The selection state of the graph node. | |
54 | */ | |
eb63f5ff | 55 | protected boolean fSelected = false; |
73005152 BH |
56 | /** |
57 | * The focus state of the graph node. | |
58 | */ | |
eb63f5ff | 59 | protected boolean fFocused = false; |
df0b8ff4 BH |
60 | /** |
61 | * Flag to indicate whether node has children or not. | |
62 | */ | |
eb63f5ff | 63 | protected boolean fHasChilden = false; |
73005152 BH |
64 | /** |
65 | * The graph node name used to label the graph node in the View. | |
66 | */ | |
eb63f5ff | 67 | protected String fName = ""; //$NON-NLS-1$ |
df0b8ff4 BH |
68 | /** |
69 | * A map from node name to graph node. | |
70 | */ | |
eb63f5ff | 71 | protected Map<String, List<GraphNode>> fNodes; |
df0b8ff4 BH |
72 | /** |
73 | * A map from node name to graph node for forward sorting | |
74 | */ | |
eb63f5ff | 75 | protected Map<String, List<GraphNode>> fForwardNodes; |
df0b8ff4 BH |
76 | /** |
77 | * A map from node name to graph node for backwards sorting. | |
78 | */ | |
eb63f5ff | 79 | protected Map<String, List<GraphNode>> fBackwardNodes; |
df0b8ff4 BH |
80 | /** |
81 | * A map from node name to index. | |
82 | */ | |
eb63f5ff | 83 | protected Map<String, Integer> fIndexes; |
df0b8ff4 BH |
84 | /** |
85 | * A map from node name to index for forwards sorting. | |
86 | */ | |
eb63f5ff | 87 | protected Map<String, Boolean> fForwardSort; |
df0b8ff4 | 88 | /** |
eb63f5ff | 89 | * A map from node name to index for forwards sorting. |
df0b8ff4 | 90 | */ |
eb63f5ff | 91 | protected Map<String, Boolean> fBackwardSort; |
73005152 | 92 | |
df0b8ff4 BH |
93 | // ------------------------------------------------------------------------ |
94 | // Methods | |
95 | // ------------------------------------------------------------------------ | |
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 | |
114 | * | |
115 | * @param nodeToAdd the node to add | |
116 | */ | |
117 | public void addNode(GraphNode nodeToAdd) { | |
eb63f5ff BH |
118 | if (!fHasChilden) { |
119 | fNodes = new HashMap<String, List<GraphNode>>(2); | |
120 | fForwardNodes = new HashMap<String, List<GraphNode>>(2); | |
121 | fBackwardNodes = new HashMap<String, List<GraphNode>>(2); | |
122 | fIndexes = new HashMap<String, Integer>(2); | |
123 | fBackwardSort = new HashMap<String, Boolean>(2); | |
124 | fForwardSort = new HashMap<String, Boolean>(2); | |
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 | ||
eb63f5ff | 144 | List<GraphNode> fNodeList = (List<GraphNode>) fForwardNodes.get(nodeToAdd.getArrayId()); |
73005152 | 145 | List<GraphNode> bNodeList = null; |
eb63f5ff BH |
146 | if (fBackwardNodes != null) { |
147 | bNodeList = (List<GraphNode>) 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) | |
152 | GraphNode node = (GraphNode) fNodeList.get(fNodeList.size() - 1); | |
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) { | |
164 | fNodeList = new ArrayList<GraphNode>(); | |
165 | } | |
166 | ||
167 | fNodeList.add(nodeToAdd); | |
eb63f5ff BH |
168 | fNodes.put(nodeToAdd.getArrayId(), fNodeList); |
169 | fForwardNodes.put(nodeToAdd.getArrayId(), fNodeList); | |
73005152 BH |
170 | if (nodeToAdd.getBackComparator() != null) { |
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. | |
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. | |
189 | * | |
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 | |
200 | * | |
201 | * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.SDWidget#addSelection(GraphNode) | |
202 | * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.SDWidget#removeSelection(GraphNode) | |
203 | * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.SDWidget#clearSelection() | |
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 | |
214 | * | |
215 | * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.SDWidget#addSelection(GraphNode) | |
216 | * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.SDWidget#removeSelection(GraphNode) | |
217 | * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.SDWidget#clearSelection() | |
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. | |
227 | * | |
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. | |
237 | * | |
238 | * @return true if focued, false otherwise | |
73005152 BH |
239 | */ |
240 | public boolean hasFocus() { | |
eb63f5ff | 241 | return fFocused; |
73005152 BH |
242 | } |
243 | ||
244 | /** | |
245 | * Returns true if the graph node contains the point given in parameter, return false otherwise. | |
246 | * | |
247 | * @param x the x coordinate of the point to test containment <br> | |
248 | * y the y coordinate of the point to test containment | |
249 | * @return true if contained, false otherwise | |
250 | */ | |
251 | abstract public boolean contains(int x, int y); | |
252 | ||
253 | /** | |
254 | * Returns the x coordinate of the graph node | |
255 | * | |
256 | * @return the x coordinate | |
257 | */ | |
258 | abstract public int getX(); | |
259 | ||
260 | /** | |
261 | * Returns the y coordinate of the graph node | |
262 | * | |
263 | * @return the y coordinate | |
264 | */ | |
265 | abstract public int getY(); | |
266 | ||
267 | /** | |
268 | * Returns the graph node height | |
269 | * | |
270 | * @return the graph node height | |
271 | */ | |
272 | abstract public int getHeight(); | |
273 | ||
274 | /** | |
275 | * Returns the graph node width | |
276 | * | |
277 | * @return the graph node width | |
278 | */ | |
279 | abstract public int getWidth(); | |
280 | ||
281 | /** | |
282 | * Draws the graph node in the given context | |
283 | * | |
284 | * @param context the graphical context to draw in | |
285 | */ | |
286 | abstract protected void draw(IGC context); | |
287 | ||
288 | /** | |
289 | * Returns the GraphNode visibility for the given visible area. Wrong visibility calculation, may strongly impact | |
290 | * drawing performance | |
291 | * | |
0d9a6d76 FC |
292 | * @param x |
293 | * @param y | |
294 | * @param width | |
295 | * @param height | |
73005152 BH |
296 | * @return true if visible false otherwise |
297 | */ | |
298 | public boolean isVisible(int x, int y, int width, int height) { | |
299 | return true; | |
300 | } | |
301 | ||
302 | /** | |
303 | * Return a comparator to sort the GraphNode of the same type This comparator is used to order the GraphNode array | |
304 | * of the given node type. (see getArrayId). | |
305 | * | |
306 | * @return the comparator | |
307 | */ | |
308 | public Comparator<GraphNode> getComparator() { | |
309 | return null; | |
310 | } | |
311 | ||
312 | /** | |
313 | * If needed, return a different comparator to backward scan the GraphNode array | |
314 | * | |
315 | * @return the backward comparator or null if not needed | |
316 | */ | |
317 | public Comparator<GraphNode> getBackComparator() { | |
318 | return null; | |
319 | } | |
320 | ||
321 | /** | |
322 | * Compare two graphNodes | |
323 | * | |
324 | * @param node the node to compare to | |
325 | * @return true if equal false otherwise | |
326 | */ | |
327 | public boolean isSameAs(GraphNode node) { | |
328 | return false; | |
329 | } | |
330 | ||
331 | /** | |
332 | * Return the node type for all class instances. This id is used to store the same nodes kind in the same ordered | |
333 | * array. | |
334 | * | |
335 | * @return the node type identifier | |
336 | */ | |
337 | abstract public String getArrayId(); | |
338 | ||
339 | /** | |
340 | * Return true if the distance from the GraphNode to the given point is positive | |
341 | * | |
342 | * @param x the point x coordinate | |
343 | * @param y the point y coordinate | |
344 | * @return true if positive false otherwise | |
345 | */ | |
346 | public boolean positiveDistanceToPoint(int x, int y) { | |
347 | return false; | |
348 | } | |
349 | ||
350 | /** | |
351 | * Returns the graph node which contains the point given in parameter WARNING: Only graph nodes in the current | |
352 | * visible area can be returned | |
353 | * | |
354 | * @param x the x coordinate of the point to test | |
355 | * @param y the y coordinate of the point to test | |
356 | * @return the graph node containing the point given in parameter, null otherwise | |
357 | */ | |
358 | public GraphNode getNodeAt(int x, int y) { | |
359 | GraphNode toReturn = null; | |
360 | ||
eb63f5ff | 361 | if (!fHasChilden) { |
73005152 | 362 | return null; |
df0b8ff4 | 363 | } |
73005152 | 364 | |
eb63f5ff | 365 | Iterator<String> it = fNodes.keySet().iterator(); |
73005152 BH |
366 | GraphNode node = null; |
367 | while (it.hasNext()) { | |
368 | Object nodeType = it.next(); | |
eb63f5ff BH |
369 | List<GraphNode> list = (List<GraphNode>) fNodes.get(nodeType); |
370 | int index = ((Integer) fIndexes.get(nodeType)).intValue(); | |
73005152 | 371 | node = getNodeFromListAt(x, y, list, index); |
df0b8ff4 | 372 | if (toReturn == null) { |
73005152 | 373 | toReturn = node; |
df0b8ff4 | 374 | } |
73005152 BH |
375 | if (node != null) { |
376 | GraphNode internalNode = node.getNodeAt(x, y); | |
df0b8ff4 | 377 | if (internalNode != null) { |
73005152 | 378 | return internalNode; |
df0b8ff4 | 379 | } else if (Math.abs(node.getWidth()) < Math.abs(toReturn.getWidth()) || Math.abs(node.getHeight()) < Math.abs(toReturn.getHeight())) { |
73005152 | 380 | toReturn = node; |
df0b8ff4 | 381 | } |
73005152 BH |
382 | } |
383 | } | |
384 | return toReturn; | |
385 | } | |
386 | ||
df0b8ff4 BH |
387 | /** |
388 | * Gets node list from node A to node B | |
389 | ||
390 | * @param from A from node | |
391 | * @param to A to node | |
392 | * @return the list of nodes | |
393 | */ | |
eb63f5ff BH |
394 | public List<GraphNode> getNodeList(GraphNode from, GraphNode to) { |
395 | List<GraphNode> result = new ArrayList<GraphNode>(); | |
73005152 BH |
396 | |
397 | if (from != null) { | |
398 | result.add(from); | |
399 | } else if (to != null) { | |
400 | result.add(to); | |
401 | } | |
402 | ||
eb63f5ff | 403 | if ((from == null) || (to == null)) { |
73005152 | 404 | return result; |
df0b8ff4 | 405 | } |
73005152 | 406 | |
df0b8ff4 | 407 | if (from == to) { |
73005152 | 408 | return result; |
df0b8ff4 | 409 | } |
73005152 BH |
410 | |
411 | int startX = Math.min(from.getX(), Math.min(to.getX(), Math.min(from.getX() + from.getWidth(), to.getX() + to.getWidth()))); | |
412 | int endX = Math.max(from.getX(), Math.max(to.getX(), Math.max(from.getX() + from.getWidth(), to.getX() + to.getWidth()))); | |
413 | int startY = Math.min(from.getY(), Math.min(to.getY(), Math.min(from.getY() + from.getHeight(), to.getY() + to.getHeight()))); | |
414 | int endY = Math.max(from.getY(), Math.max(to.getY(), Math.max(from.getY() + from.getHeight(), to.getY() + to.getHeight()))); | |
415 | ||
eb63f5ff | 416 | if (!fHasChilden) { |
73005152 | 417 | return result; |
df0b8ff4 | 418 | } |
73005152 | 419 | |
eb63f5ff | 420 | Iterator<String> it = fNodes.keySet().iterator(); |
73005152 BH |
421 | while (it.hasNext()) { |
422 | Object nodeType = it.next(); | |
eb63f5ff | 423 | List<GraphNode> nodesList = (List<GraphNode>) fNodes.get(nodeType); |
df0b8ff4 | 424 | if (nodesList == null || nodesList.isEmpty()) { |
73005152 | 425 | return null; |
df0b8ff4 | 426 | } |
73005152 BH |
427 | for (int i = 0; i < nodesList.size(); i++) { |
428 | GraphNode node = (GraphNode) nodesList.get(i); | |
429 | int nw = node.getWidth(); | |
430 | int nh = node.getHeight(); | |
431 | int nx = node.getX(); | |
432 | int ny = node.getY(); | |
df0b8ff4 | 433 | 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 | 434 | result.add(node); |
df0b8ff4 | 435 | } |
73005152 BH |
436 | result.addAll(node.getNodeList(from, to)); |
437 | } | |
438 | } | |
eb63f5ff BH |
439 | |
440 | if (!result.contains(to)) { | |
73005152 | 441 | result.add(to); |
df0b8ff4 | 442 | } |
73005152 BH |
443 | return result; |
444 | } | |
445 | ||
446 | /** | |
447 | * Returns the graph node which contains the point given in parameter for the given graph node list and starting the | |
448 | * iteration at the given index<br> | |
449 | * WARNING: Only graph nodes with smaller coordinates than the current visible area can be returned.<br> | |
450 | * | |
451 | * @param x the x coordinate of the point to test | |
452 | * @param y the y coordinate of the point to test | |
453 | * @param list the list to search in | |
454 | * @param fromIndex list browsing starting point | |
455 | * @return the graph node containing the point given in parameter, null otherwise | |
456 | */ | |
457 | protected GraphNode getNodeFromListAt(int x, int y, List<GraphNode> list, int fromIndex) { | |
df0b8ff4 | 458 | if (list == null) { |
73005152 | 459 | return null; |
df0b8ff4 | 460 | } |
73005152 BH |
461 | for (int i = fromIndex; i < list.size(); i++) { |
462 | GraphNode node = (GraphNode) list.get(i); | |
df0b8ff4 | 463 | if (node.contains(x, y)) { |
73005152 | 464 | return node; |
df0b8ff4 | 465 | } |
73005152 BH |
466 | } |
467 | return null; | |
468 | } | |
469 | ||
470 | /** | |
471 | * Returns the start event occurrence attached to this graphNode. | |
472 | * | |
473 | * @return the start event occurrence attached to the graphNode | |
474 | */ | |
475 | public int getStartOccurrence() { | |
eb63f5ff | 476 | return fStartEventOccurrence; |
73005152 BH |
477 | } |
478 | ||
479 | /** | |
480 | * Returns the end event occurrence attached to this graphNode | |
481 | * | |
482 | * @return the start event occurrence attached to the graphNode | |
483 | */ | |
484 | public int getEndOccurrence() { | |
eb63f5ff | 485 | return fEndEventOccurrence; |
73005152 BH |
486 | } |
487 | ||
488 | /** | |
489 | * Computes the index of the first visible GraphNode for each ordered graph node lists depending on the visible area | |
490 | * given in parameter | |
491 | * | |
492 | * @param x visible area top left corner x coordinate | |
493 | * @param y visible area top left corner y coordinate | |
494 | * @param width visible area width | |
495 | * @param height visible area height | |
496 | */ | |
497 | public void updateIndex(int x, int y, int width, int height) { | |
eb63f5ff | 498 | if (!fHasChilden) { |
73005152 | 499 | return; |
df0b8ff4 | 500 | } |
73005152 BH |
501 | if(TmfUiTracer.isIndexTraced()) { |
502 | TmfUiTracer.traceIndex("*****************************\n"); //$NON-NLS-1$ | |
503 | TmfUiTracer.traceIndex("Visible area position in virtual screen (x,y)= " + x + " " + y + "\n\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ | |
504 | } | |
505 | ||
eb63f5ff | 506 | Iterator<String> it = fNodes.keySet().iterator(); |
73005152 BH |
507 | while (it.hasNext()) { |
508 | String nodeType = it.next(); | |
509 | int direction = 1; | |
eb63f5ff | 510 | int drawIndex = ((Integer) fIndexes.get(nodeType)).intValue(); |
73005152 BH |
511 | /* |
512 | * if (x==0) { drawIndex = 0; indexes.put(nodeType,new Integer(drawIndex)); } | |
513 | */ | |
eb63f5ff BH |
514 | if ((fNodes.get(nodeType) != null) && (((List<GraphNode>) fNodes.get(nodeType)).size() > 1)) { |
515 | if (((GraphNode) ((List<GraphNode>) fNodes.get(nodeType)).get(drawIndex)).positiveDistanceToPoint(x, y)) { | |
73005152 | 516 | direction = -1; |
df0b8ff4 | 517 | } |
73005152 | 518 | |
df0b8ff4 | 519 | if (drawIndex == 0) { |
73005152 | 520 | direction = 1; |
df0b8ff4 | 521 | } |
73005152 | 522 | |
eb63f5ff BH |
523 | if ((direction == -1) && (fBackwardNodes.get(nodeType) != null)) { |
524 | GraphNode currentNode = (GraphNode) ((List<GraphNode>) fNodes.get(nodeType)).get(drawIndex); | |
3145ec83 BH |
525 | drawIndex = Arrays.binarySearch(((List<GraphNode>) fBackwardNodes.get(nodeType)).toArray(new GraphNode[((List<GraphNode>) fBackwardNodes.get(nodeType)).size()]), |
526 | ((List<GraphNode>) fNodes.get(nodeType)).get(drawIndex), currentNode.getBackComparator()); | |
eb63f5ff | 527 | fNodes.put(nodeType, (List<GraphNode>) fBackwardNodes.get(nodeType)); |
73005152 BH |
528 | if (drawIndex < 0) { |
529 | drawIndex = 0; | |
530 | direction = 1; | |
df0b8ff4 | 531 | } else { |
eb63f5ff | 532 | fNodes.put(nodeType, (List<GraphNode>) fBackwardNodes.get(nodeType)); |
df0b8ff4 | 533 | } |
73005152 BH |
534 | } |
535 | GraphNode prev = null; | |
536 | ||
eb63f5ff | 537 | for (int i = drawIndex; i < ((List<GraphNode>) fNodes.get(nodeType)).size() && i >= 0; i = i + direction) { |
73005152 | 538 | drawIndex = i; |
eb63f5ff | 539 | fIndexes.put(nodeType, Integer.valueOf(i)); |
73005152 | 540 | |
eb63f5ff | 541 | GraphNode currentNode = (GraphNode) ((List<GraphNode>) fNodes.get(nodeType)).get(i); |
73005152 | 542 | |
df0b8ff4 | 543 | if (prev == null) { |
73005152 | 544 | prev = currentNode; |
df0b8ff4 | 545 | } |
73005152 BH |
546 | |
547 | Comparator<GraphNode> comp = currentNode.getComparator(); | |
eb63f5ff | 548 | Map<String, Boolean> sort = fForwardSort; |
73005152 | 549 | |
eb63f5ff BH |
550 | if ((direction == -1) && (currentNode.getBackComparator() != null)) { |
551 | comp = currentNode.getBackComparator(); | |
552 | sort = fBackwardSort; | |
73005152 BH |
553 | } |
554 | ||
eb63f5ff BH |
555 | if (i < ((List<GraphNode>) fNodes.get(nodeType)).size() - 1) { |
556 | GraphNode next = (GraphNode) ((List<GraphNode>) fNodes.get(nodeType)).get(i + 1); | |
73005152 | 557 | |
df0b8ff4 | 558 | if ((comp != null) && (comp.compare(currentNode, next) > 0)) { |
3145ec83 | 559 | sort.put(nodeType, Boolean.TRUE); |
df0b8ff4 | 560 | } |
73005152 BH |
561 | } |
562 | if (direction == 1) { | |
eb63f5ff | 563 | if (((GraphNode) ((List<GraphNode>) fNodes.get(nodeType)).get(i)).positiveDistanceToPoint(x, y)) { |
73005152 | 564 | break; |
df0b8ff4 | 565 | } |
73005152 BH |
566 | } else { |
567 | if (currentNode.getBackComparator() == null) { | |
568 | if // (currentNode.isVisible(x,y,width,height) | |
df0b8ff4 | 569 | (!currentNode.positiveDistanceToPoint(x, y)) { |
73005152 | 570 | break; |
df0b8ff4 | 571 | } |
73005152 BH |
572 | } else { |
573 | if (currentNode.isVisible(x, y, width, height) && !currentNode.positiveDistanceToPoint(x, y)) { | |
df0b8ff4 | 574 | if ((comp != null) && (comp.compare(currentNode, prev) <= 0)) { |
73005152 | 575 | break; |
df0b8ff4 BH |
576 | } |
577 | } else if ((comp != null) && (comp.compare(currentNode, prev) <= 0)) { | |
73005152 | 578 | prev = currentNode; |
df0b8ff4 | 579 | } |
73005152 BH |
580 | } |
581 | } | |
582 | } | |
583 | ||
eb63f5ff BH |
584 | fNodes.put(nodeType, fForwardNodes.get(nodeType)); |
585 | if ((fBackwardNodes.get(nodeType) != null) && (direction == -1)) { | |
73005152 | 586 | // nodes.put(nodeType,fnodes.get(nodeType)); |
eb63f5ff BH |
587 | int index = ((Integer) fIndexes.get(nodeType)).intValue(); |
588 | List<GraphNode> list = (List<GraphNode>) fNodes.get(nodeType); | |
589 | List<GraphNode> backList = (List<GraphNode>) fBackwardNodes.get(nodeType); | |
73005152 BH |
590 | GraphNode currentNode = (GraphNode) (backList.get(index)); |
591 | if (index > 0) { | |
eb63f5ff | 592 | index = Arrays.binarySearch(list.toArray(new GraphNode[list.size()]), backList.get(index), currentNode.getComparator()); |
df0b8ff4 | 593 | if (index < 0) { |
73005152 | 594 | index = 0; |
df0b8ff4 | 595 | } |
eb63f5ff | 596 | fIndexes.put(nodeType, Integer.valueOf(index)); |
73005152 BH |
597 | } |
598 | } | |
599 | ||
eb63f5ff BH |
600 | for (int i = drawIndex; i < ((List<GraphNode>) fNodes.get(nodeType)).size() && i >= 0; i++) { |
601 | GraphNode toDraw = (GraphNode) ((List<GraphNode>) fNodes.get(nodeType)).get(i); | |
73005152 | 602 | toDraw.updateIndex(x, y, width, height); |
df0b8ff4 | 603 | if (!toDraw.isVisible(x, y, width, height)) { |
73005152 | 604 | break; |
df0b8ff4 | 605 | } |
73005152 BH |
606 | } |
607 | } | |
608 | if (TmfUiTracer.isIndexTraced()) { | |
609 | TmfUiTracer.traceIndex("First drawn " + nodeType + " index = " + drawIndex + "\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ | |
610 | TmfUiTracer.traceIndex(nodeType + " found in " + 0 + " iterations\n"); //$NON-NLS-1$ //$NON-NLS-2$ | |
611 | } | |
612 | } | |
613 | ||
614 | if (TmfUiTracer.isIndexTraced()) { | |
615 | TmfUiTracer.traceIndex("*****************************\n"); //$NON-NLS-1$ | |
616 | } | |
617 | } | |
618 | ||
619 | /** | |
620 | * Draws the children nodes on the given context.<br> | |
621 | * This method start width GraphNodes ordering if needed.<br> | |
622 | * After, depending on the visible area, only visible GraphNodes are drawn.<br> | |
623 | * | |
624 | * @param context the context to draw to | |
73005152 BH |
625 | * @see org.eclipse.linuxtools.tmf.ui.views.uml2sd.core.GraphNode#draw(IGC) |
626 | */ | |
627 | protected void drawChildenNodes(IGC context) { | |
628 | ||
eb63f5ff | 629 | if (!fHasChilden) { |
73005152 | 630 | return; |
df0b8ff4 | 631 | } |
73005152 | 632 | // If the nodes have not been added ordered, the array is ordered |
eb63f5ff | 633 | Iterator<String> it = fForwardSort.keySet().iterator(); |
73005152 BH |
634 | while (it.hasNext()) { |
635 | String nodeType = it.next(); | |
eb63f5ff | 636 | boolean sort = ((Boolean) fForwardSort.get(nodeType)).booleanValue(); |
73005152 | 637 | if (sort) { |
eb63f5ff BH |
638 | GraphNode[] temp = ((List<GraphNode>) fForwardNodes.get(nodeType)).toArray(new GraphNode[((List<GraphNode>)fForwardNodes.get(nodeType)).size()]); |
639 | GraphNode node = (GraphNode) ((List<GraphNode>) fNodes.get(nodeType)).get(0); | |
73005152 | 640 | Arrays.sort(temp, node.getComparator()); |
3145ec83 | 641 | fForwardSort.put(nodeType, Boolean.FALSE); |
eb63f5ff BH |
642 | fNodes.put(nodeType, Arrays.asList(temp)); |
643 | fForwardNodes.put(nodeType, Arrays.asList(temp)); | |
df0b8ff4 | 644 | if (TmfUiTracer.isSortingTraced()) { |
73005152 | 645 | TmfUiTracer.traceSorting(nodeType + " array sorted\n"); //$NON-NLS-1$ |
df0b8ff4 | 646 | } |
73005152 BH |
647 | } |
648 | } | |
649 | ||
eb63f5ff | 650 | Iterator<String> it2 = fBackwardSort.keySet().iterator(); |
73005152 BH |
651 | while (it2.hasNext()) { |
652 | String nodeType = it2.next(); | |
eb63f5ff | 653 | boolean sort = ((Boolean) fBackwardSort.get(nodeType)).booleanValue(); |
73005152 | 654 | if (sort) { |
eb63f5ff BH |
655 | GraphNode[] temp = ((List<GraphNode>) fBackwardNodes.get(nodeType)).toArray(new GraphNode[((List<GraphNode>) fBackwardNodes.get(nodeType)).size()]); |
656 | GraphNode node = (GraphNode) ((List<GraphNode>) fNodes.get(nodeType)).get(0); | |
73005152 | 657 | Arrays.sort(temp, node.getBackComparator()); |
3145ec83 | 658 | fBackwardSort.put(nodeType, Boolean.FALSE); |
eb63f5ff | 659 | fBackwardNodes.put(nodeType, Arrays.asList(temp)); |
df0b8ff4 | 660 | if (TmfUiTracer.isSortingTraced()) { |
73005152 | 661 | TmfUiTracer.traceSorting(nodeType + " back array sorted\n"); //$NON-NLS-1$ |
df0b8ff4 | 662 | } |
73005152 BH |
663 | } |
664 | } | |
665 | ||
666 | if (TmfUiTracer.isDisplayTraced()) { | |
667 | TmfUiTracer.traceDisplay("*****************************\n"); //$NON-NLS-1$ | |
668 | } | |
669 | ||
670 | int arrayStep = 1; | |
df0b8ff4 | 671 | if ((Metrics.getMessageFontHeigth() + Metrics.MESSAGES_NAME_SPACING * 2) * context.getZoom() < Metrics.MESSAGE_SIGNIFICANT_VSPACING) { |
73005152 | 672 | arrayStep = Math.round(Metrics.MESSAGE_SIGNIFICANT_VSPACING / ((Metrics.getMessageFontHeigth() + Metrics.MESSAGES_NAME_SPACING * 2) * context.getZoom())); |
df0b8ff4 | 673 | } |
73005152 BH |
674 | |
675 | int count = 0; | |
eb63f5ff | 676 | Iterator<String> it3 = fForwardSort.keySet().iterator(); |
73005152 BH |
677 | while (it3.hasNext()) { |
678 | count = 0; | |
679 | Object nodeType = it3.next(); | |
eb63f5ff | 680 | GraphNode node = (GraphNode) ((List<GraphNode>) fNodes.get(nodeType)).get(0); |
3145ec83 | 681 | context.setFont(SDViewPref.getInstance().getFont(node.fPrefId)); |
eb63f5ff BH |
682 | int index = ((Integer) fIndexes.get(nodeType)).intValue(); |
683 | count = drawNodes(context, (List<GraphNode>) fNodes.get(nodeType), index, arrayStep); | |
df0b8ff4 | 684 | if (TmfUiTracer.isDisplayTraced()) { |
73005152 | 685 | TmfUiTracer.traceDisplay(count + " " + nodeType + " drawn, starting from index " + index + "\r\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
df0b8ff4 | 686 | } |
73005152 BH |
687 | } |
688 | if (TmfUiTracer.isDisplayTraced()) { | |
689 | TmfUiTracer.traceDisplay("*****************************\n"); //$NON-NLS-1$ | |
690 | } | |
691 | ||
692 | } | |
693 | ||
694 | /** | |
695 | * Draw the GraphNode stored in the given list, starting at index startIndex with the given step | |
696 | * | |
697 | * @param context the context to draw to | |
698 | * @param list the GraphNodes list | |
699 | * @param startIndex the start index | |
700 | * @param step the step to browse the list | |
701 | * @return the number of GraphNodes drawn | |
702 | */ | |
703 | protected int drawNodes(IGC context, List<GraphNode> list, int startIndex, int step) { | |
eb63f5ff | 704 | if (!fHasChilden) { |
73005152 | 705 | return 0; |
df0b8ff4 | 706 | } |
73005152 BH |
707 | |
708 | GraphNode last = null; | |
709 | int nodesCount = 0; | |
df0b8ff4 | 710 | if (list.size() < 0) { |
73005152 | 711 | return 0; |
df0b8ff4 | 712 | } |
73005152 BH |
713 | |
714 | GraphNode node = (GraphNode) list.get(0); | |
3145ec83 | 715 | context.setFont(SDViewPref.getInstance().getFont(node.fPrefId)); |
73005152 BH |
716 | Comparator<GraphNode> comparator = node.getComparator(); |
717 | for (int i = startIndex; i < list.size(); i = i + step) { | |
718 | GraphNode toDraw = (GraphNode) list.get(i); | |
719 | if (i < list.size() - 1) { | |
720 | GraphNode next = (GraphNode) list.get(i + 1); | |
f9a8715c | 721 | if ((comparator != null) && (comparator.compare(toDraw, next) > 0)) { |
3145ec83 | 722 | fForwardSort.put(next.getArrayId(), Boolean.TRUE); |
73005152 BH |
723 | } |
724 | } | |
725 | int cx = context.getContentsX(); | |
726 | int cy = context.getContentsY(); | |
727 | int cw = context.getVisibleWidth(); | |
728 | int ch = context.getVisibleHeight(); | |
729 | // The arrays should be ordered, no needs to continue for this one | |
df0b8ff4 | 730 | if (!toDraw.isVisible(cx, cy, cw, ch) && toDraw.positiveDistanceToPoint(cx + cw, cy + ch)) { |
73005152 | 731 | break; |
df0b8ff4 | 732 | } |
73005152 BH |
733 | // ***Common*** nodes visibility |
734 | if ((!toDraw.isSameAs(last) || toDraw.isSelected()) && (toDraw.isVisible(context.getContentsX(), context.getContentsY(), context.getVisibleWidth(), context.getVisibleHeight()))) { | |
735 | nodesCount++; | |
736 | ||
737 | toDraw.draw(context); | |
df0b8ff4 | 738 | if (hasFocus()) { |
73005152 | 739 | toDraw.drawFocus(context); |
df0b8ff4 | 740 | } |
73005152 BH |
741 | } |
742 | last = toDraw; | |
743 | } | |
744 | return nodesCount; | |
745 | } | |
746 | ||
df0b8ff4 BH |
747 | /** |
748 | * Draws the focus within the graphical context. | |
749 | * @param context | |
750 | */ | |
73005152 BH |
751 | public void drawFocus(IGC context) { |
752 | context.drawFocus(getX(), getY(), getWidth(), getHeight()); | |
753 | } | |
754 | ||
755 | /** | |
756 | * Determine if the given point (px,py) is contained in the rectangle (x,y,width,height) | |
757 | * | |
758 | * @param x the rectangle x coordinate | |
759 | * @param y the rectangle y coordinate | |
760 | * @param width the rectangle width | |
761 | * @param height the rectangle height | |
762 | * @param px the x coordinate of the point to test | |
763 | * @param py the y coordinate of the point to test | |
764 | * @return true if contained false otherwise | |
765 | */ | |
766 | public static boolean contains(int x, int y, int width, int height, int px, int py) { | |
767 | int locX = x; | |
768 | int locY = y; | |
769 | int locWidth = width; | |
770 | int locHeight = height; | |
771 | ||
772 | if (width < 0) { | |
773 | locX = locX + width; | |
774 | locWidth = -locWidth; | |
775 | } | |
776 | ||
777 | if (height < 0) { | |
778 | locY = locY + height; | |
779 | locHeight = -locHeight; | |
780 | } | |
781 | return (px >= locX) && (py >= locY) && ((px - locX) <= locWidth) && ((py - locY) <= locHeight); | |
782 | } | |
783 | } |