source: trunk/src/org/expeditee/items/ItemUtils.java@ 78

Last change on this file since 78 was 78, checked in by ra33, 16 years ago

Added @b and @v...
Also changed @f... so that images can be displayed with transparent backgrounds.
Did a bunch of refactoring in the process to remove duplicated code and simplify managing @i, @f and @b.

File size: 22.7 KB
Line 
1package org.expeditee.items;
2
3import java.awt.Font;
4import java.awt.FontMetrics;
5import java.awt.Image;
6import java.awt.image.ImageObserver;
7import java.io.File;
8import java.io.UnsupportedEncodingException;
9import java.net.URL;
10import java.net.URLDecoder;
11import java.util.ArrayList;
12import java.util.Collection;
13import java.util.HashMap;
14import java.util.LinkedHashSet;
15import java.util.LinkedList;
16import java.util.List;
17import java.util.Map;
18
19import javax.swing.JFrame;
20
21import org.expeditee.gui.DisplayIO;
22import org.expeditee.gui.Frame;
23
24//Static methods that provide functions for the objects\
25//mostly to transform values (string -> color etc).
26
27/**
28 * Static methods that provide functions for use in Items.
29 */
30public class ItemUtils {
31 private static JFrame _jf = new JFrame();
32
33 // Tag constants
34 public static final int TAG_SORT = 0;
35
36 public static final int TAG_JOIN = 1;
37
38 public static final int TAG_INDENT = 2;
39
40 public static final int TAG_OVERLAY = 3;
41
42 public static final int TAG_ACTIVE_OVERLAY = 4;
43
44 public static final int TAG_IMAGE = 5;
45
46 public static final int TAG_ITEM_TEMPLATE = 6;
47
48 public static final int TAG_ANNOTATION_TEMPLATE = 7;
49
50 public static final int TAG_CODE_COMMENT_TEMPLATE = 8;
51
52 public static final int TAG_MENU = 9;
53
54 public static final int TAG_MENU_NEXT = 10;
55
56 public static final int TAG_PARENT = 11;
57
58 public static final int TAG_LITERAL = 12;
59
60 public static final int TAG_FRAME_IMAGE = 13;
61
62 public static final int TAG_BACKUP = 14;
63
64 public static final int TAG_POINTTYPE = 15;
65
66 // Brook: Im claiming this number!
67 public static final int TAG_IWIDGET = 16;
68
69 public static final int TAG_LINE_TEMPLATE = 17;
70
71 public static final int TAG_STAT_TEMPLATE = 18;
72
73 public static final int TAG_VECTOR = 19;
74
75 public static final int TAG_BITMAP_IMAGE = 20;
76
77 public static final int TAG_MIN = 0;
78
79 public static final int TAG_MAX = 20;
80
81 /**
82 * Determines if the given List of Items contains an Item that is one of the
83 * pre-defined tags.
84 *
85 * @param items
86 * The list of Items to search through
87 * @param tag
88 * The Tag to search for, this should correspond to one of the
89 * predefined constants in this class
90 * @return True if an Item was found that is the given Tag, False otherwise.
91 */
92 public static boolean ContainsTag(List<Item> items, int tag) {
93 return ContainsTag(items, GetTag(tag));
94 }
95
96 public static boolean ContainsTag(List<Item> items, String tag) {
97 return (FindTag(items, tag) != null);
98 }
99
100 public static boolean ContainsExactTag(List<Item> items, int tag) {
101 return ContainsExactTag(items, GetTag(tag));
102 }
103
104 public static boolean ContainsExactTag(List<Item> items, String tag) {
105 return (FindExactTag(items, tag) != null);
106 }
107
108 /**
109 * Searches the given List of Items for an Item that is one of the
110 * pre-defined tags.
111 *
112 * @param items
113 * The list of Items to search through
114 * @param tag
115 * The Tag to search for, this should correspond to one of the
116 * predefined constants in this class
117 * @return The Item that is the given tag if one is found, or False if none
118 * is found
119 */
120 public static Item FindTag(List<Item> items, int tag) {
121 return FindTag(items, GetTag(tag));
122 }
123
124 /**
125 * Searches the given List of Items for an Item that is the given tag
126 *
127 * @param items
128 * The list of Items to search through
129 * @param toFind
130 * The Tag to search for, this should include the at (@) symbol
131 * @return The Item that is the given tag if one is found, or False if none
132 * is found
133 */
134 public static Text FindTag(List<Item> items, String toFind) {
135 for (Item i : items) {
136 if (i instanceof Text && i.isAnnotation())
137 if (((Text) i).startsWith(toFind))
138 return (Text) i;
139 }
140
141 return null;
142 }
143
144 public static Item FindExactTag(List<Item> items, String toFind) {
145 for (Item i : items) {
146 if (i instanceof Text && i.isAnnotation())
147 if (((Text) i).getTextNoList().trim().equalsIgnoreCase(toFind))
148 return (Item) i;
149 }
150
151 return null;
152 }
153
154 public static Item FindExactTag(List<Item> items, int tag) {
155 return FindExactTag(items, GetTag(tag));
156 }
157
158 /**
159 * Determines if the given Item is one of the pre-defined tags in this class
160 *
161 * @param toCheck
162 * The Item to check
163 * @param tag
164 * The tag to check the Item against, this should correspond to
165 * one of the constants defined in this class
166 * @return True if the Item matches the given tag, false otherwise
167 */
168 public static boolean isTag(Item toCheck, int tag) {
169 return isTag(toCheck, GetTag(tag));
170 }
171
172 public static boolean isTag(Item toCheck, int tag, boolean hasValue) {
173 return isTag(toCheck, GetTag(tag), hasValue);
174 }
175
176 /**
177 * Checks if the given Item contains the desired tag (case insensitive)
178 *
179 * @param toCheck
180 * The Item to check for the given tag
181 * @param tag
182 * The tag to check for in the given Item
183 * @param tagOnly
184 * True if the tag does not have a value
185 * @return True if the tag is found in the given Item, False otherwise.
186 */
187 public static boolean isTag(Item toCheck, String tag, boolean hasValue) {
188 if (!(toCheck instanceof Text) || !toCheck.isAnnotation())
189 return false;
190
191 Text txt = (Text) toCheck;
192 // tags are ase-insensitive
193 return String.CASE_INSENSITIVE_ORDER.compare(txt.getFirstLine().trim(),
194 tag) == 0
195 || (hasValue && txt.startsWith(tag + " ", true));
196 }
197
198 public static boolean isTag(Item toCheck, String tag) {
199 return isTag(toCheck, tag, true);
200 }
201
202 /**
203 * Strips off the given tag from the given String, and returns wathever is
204 * left
205 *
206 * @param toStrip
207 * The String to strip the Tag from
208 * @param tag
209 * The tag to remove from the String
210 * @return The String that results from removing the given Tag from the
211 * given String, or null if the given String is not the given Tag
212 */
213 public static String StripTag(String toStrip, String tag) {
214 if (toStrip.toLowerCase().startsWith(tag.toLowerCase())) {
215 toStrip = toStrip.substring(tag.length()).trim();
216 return toStrip;
217 }
218
219 /**
220 * TODO: Change this to use REGEX
221 */
222
223 return null;
224 }
225
226 /**
227 * The same as StripTag(String, String), but this method iterates through
228 * the list of pre-defined tags until one is found.
229 *
230 * @param toStrip
231 * The String to strip the tag from
232 * @return The String that results from stripping off the Tag, or null if
233 * the given String was not a tag
234 */
235 public static String StripTag(String toStrip) {
236 // there must be something left after stripping
237 if (toStrip == null)// || toStrip.trim().indexOf(" ") < 0)
238 return toStrip;
239
240 for (int i = TAG_MIN; i <= TAG_MAX; i++) {
241 String res = StripTag(toStrip, GetTag(i));
242 if (res != null)
243 return res;
244 }
245
246 return null;
247 }
248
249 /**
250 * Strips the first character from a string if it is the @ symbol
251 * @param toStrip
252 * the string to be stripped
253 * @return the stripped version of the string
254 */
255 public static String StripTagSymbol(String toStrip) {
256 // there must be something left after stripping
257 if (toStrip != null) {
258 if (toStrip.length() > 0) {
259 if (toStrip.charAt(0) == '@') {
260 return toStrip.substring(1);
261 }
262 }
263 }
264
265 return toStrip;
266 }
267
268 /**
269 * Converts the given int to the String tag. The int should correspond to
270 * one of the constants in this class, if it does not this method will
271 * return null.
272 *
273 * @param tag
274 * The int corresponding to the constants in this class of which
275 * tag to return
276 * @return The String representation of the given Tag, or null if the given
277 * value does not have a tag associated
278 */
279 public static String GetTag(int tag) {
280 // TODO refactor so that this uses a map for INT to tags
281 switch (tag) {
282 case TAG_SORT:
283 return "@sort";
284 case TAG_JOIN:
285 return "@join";
286 case TAG_INDENT:
287 return "@indent";
288 case TAG_OVERLAY:
289 return "@o";
290 case TAG_VECTOR:
291 return "@v";
292 case TAG_ACTIVE_OVERLAY:
293 return "@ao";
294 case TAG_IMAGE:
295 return "@i:";
296 case TAG_ITEM_TEMPLATE:
297 return "@itemtemplate";
298 case TAG_ANNOTATION_TEMPLATE:
299 return "@annotationtemplate";
300 case TAG_STAT_TEMPLATE:
301 return "@stattemplate";
302 case TAG_CODE_COMMENT_TEMPLATE:
303 return "@commenttemplate";
304 case TAG_MENU:
305 return "@menu";
306 case TAG_MENU_NEXT:
307 return "@nextmenu";
308 case TAG_PARENT:
309 return "@parent";
310 case TAG_LITERAL:
311 return "@lit";
312 case TAG_FRAME_IMAGE:
313 return "@f";
314 case TAG_BITMAP_IMAGE:
315 return "@b";
316 case TAG_BACKUP:
317 return "@old";
318 case TAG_POINTTYPE:
319 return "@pointtype:";
320 case TAG_IWIDGET:
321 return "@iw";
322 case TAG_LINE_TEMPLATE:
323 return "@linetemplate";
324 default:
325 return null;
326 }
327 }
328
329 /**
330 * Returns a FontMetrics object that corresponds to the given Font.
331 *
332 * @param font
333 * The Font to derive the FontMetrics from
334 * @return FontMetrics that correspond to the given Font
335 */
336 public static FontMetrics getFontMetrics(Font font) {
337 return _jf.getFontMetrics(font);
338 }
339
340 public static Image CreateImage(int x, int y) {
341 return _jf.createImage(x, y);
342 }
343
344 /**
345 * Creates a picture object from the information stored in the given Text
346 * object. <br>
347 * The paths searched are in the following order:<br>
348 * /images/<br>
349 * the source text as a relative path (from program root folder). <br>
350 * the source text as an absolute path <br>
351 * <br>
352 * If the Image file cannot be found on disk null is returned.
353 *
354 * @param source
355 * The Text file containing the Picture infomation
356 * @return The Picture object representing the file, or Null if the file is
357 * not found.
358 */
359 public static Picture CreatePicture(Text source, ImageObserver observer) {
360 String text = source.getTextNoList();
361 String path = "";
362 String size = "";
363
364 try {
365 // remove @i tag
366 text = text.replaceFirst("@i:", "");
367 text = text.replaceAll("\n", "");
368 text = text.trim();
369
370 if (text.indexOf(".") >= text.lastIndexOf(" "))
371 path = text;
372 else
373 path = text.substring(0, text.lastIndexOf(" "));
374
375 size = text.substring(path.length()).trim();
376
377 // try images subdirectory
378 File file = null;
379
380 for (String dir : org.expeditee.gui.UserSettings.ImageDirs) {
381 file = new File(dir + path);
382 if (file.exists() && !file.isDirectory())
383 break;
384 }
385
386 if (file == null || !file.exists() || file.isDirectory())
387 file = new File(path);
388
389 // try relative path
390 if (!file.exists() || file.isDirectory()) {
391 URL picture = new Object().getClass().getResource(path);
392
393 // decode to remove %20 in windows folder names
394 if (picture != null) {
395 try {
396 path = URLDecoder.decode(picture.getFile(), "UTF-8");
397 } catch (UnsupportedEncodingException e) {
398 // TODO Auto-generated catch block
399 e.printStackTrace();
400 }
401 }
402
403 } else
404 path = file.getPath();
405
406 // if the image isn't found by now, give up.
407 file = new File(path);
408 if (!file.exists() || file.isDirectory()) {
409 return null;
410 }
411
412 } catch (Exception e) {
413 return null;
414 }
415
416 try {
417 Picture pic = new Picture(source, path, size, observer);
418
419 return pic;
420 } catch (Exception e) {
421 e.printStackTrace();
422 return null;
423 }
424
425 }
426
427 public static Picture CreateFrameImage(Text source, ImageObserver observer) {
428 String size = source.getFirstLine();
429
430 // remove @f tag
431 size = size.replaceFirst("@f", "");
432 size = size.trim();
433
434 try {
435 Picture pic = new FrameImage(source, size, observer);
436 return pic;
437 } catch (Exception e) {
438 // e.printStackTrace();
439 return null;
440 }
441 }
442
443 public static Picture CreateFrameBitmap(Text source, ImageObserver observer) {
444 String size = source.getFirstLine();
445
446 // remove @b tag
447 size = size.replaceFirst("@b", "");
448 size = size.trim();
449
450 try {
451 Picture pic = new FrameBitmap(source, size, observer);
452 return pic;
453 } catch (Exception e) {
454 // e.printStackTrace();
455 return null;
456 }
457 }
458
459 /**
460 * Creates a deep copy of the given List of Items.
461 *
462 * @param toCopy
463 * The list of Items to copy
464 * @return A list containing a copy of all Items in the given List
465 */
466 public static List<Item> CopyItems(Collection<Item> toCopy) {
467 return CopyItems(toCopy, false);
468 }
469
470 public static List<Item> CopyItems(Collection<Item> toCopy, boolean extrude) {
471 // The copies to return
472 List<Item> copies = new ArrayList<Item>();
473
474 // list of dots at the end of lines
475 Collection<Item> lineEnds = new LinkedHashSet<Item>();
476 Collection<Line> lines = new LinkedHashSet<Line>();
477 Collection<Constraint> constraints = new LinkedHashSet<Constraint>();
478
479 Collection<Item> singles = new LinkedHashSet<Item>();
480
481 Map<Item, Item> lineEndMap = new HashMap<Item, Item>();
482
483 // Widgets are super special
484 List<InteractiveWidget> widgets = new ArrayList<InteractiveWidget>();
485
486 for (Item i : toCopy) {
487
488 // BROOK
489 if (i instanceof WidgetCorner) { // dont add these
490
491 if (!widgets.contains(((WidgetCorner) i).getWidgetSource()))
492 widgets.add(((WidgetCorner) i).getWidgetSource());
493
494 // BROOK
495 } else if (i instanceof WidgetEdge) { // dont add these
496
497 // lines are recreated later
498 } else if (i instanceof Line) {
499 lines.add((Line) i);
500 } else {
501 if (i.isLineEnd()) {
502 lineEnds.add(i);
503 constraints.addAll(i.getConstraints());
504 } else {
505 singles.add(i);
506 }
507 }
508 }
509
510 // copy all single items
511 for (Item i : singles) {
512 Item copy = i.copy();
513
514 if (i.getParent() != null) {
515 // if this is the frame name, make sure the frame is saved (in
516 // case it is a TDFC frame)
517 if (i == i.getParent().getFrameNameItem())
518 i.getParent().setChanged(true);
519
520 // if this is the title of the frame, link it to the frame
521 if (i.getLink() == null && i == i.getParent().getTitle()
522 && toCopy.size() == 1) {
523 // save the frame after copying
524 i.getParent().setChanged(true);
525 copy.setLink(i.getParent().getFrameName());
526 }
527 }
528 copies.add(copy);
529 }
530
531 // replace line ends with their copies
532 // this is done here so that copied lines can still share end points
533 for (Item i : lineEnds) {
534 // create a copy of the line end
535 Item copy = i.copy();
536 copy.removeAllLines();
537 copy.removeAllConstraints();
538
539 if (extrude) {
540 Frame frame = i.getParentOrCurrentFrame();
541 Line newLine = new Line(i, copy, frame.getNextItemID());
542 // make sure overlay items are put back on the overlay
543 newLine.setParent(frame);
544 frame.addItem(newLine);
545 copies.add(newLine);
546 }
547 copies.add(copy);
548 lineEndMap.put(i, copy);
549 }
550
551 // recreate lines
552 for (Line line : lines) {
553 Line lineCopy = line.copy();
554 //get the lineEnd we copied above if it is in the MAPPING
555 Item originalLineEnd = line.getEndItem();
556 Item actualLineEnd = lineEndMap.get(originalLineEnd);
557 if (actualLineEnd == null)
558 lineCopy.setEndItem(originalLineEnd);
559 else
560 lineCopy.setEndItem(actualLineEnd);
561
562 Item originalLineStart = line.getStartItem();
563 Item actualLineStart = lineEndMap.get(originalLineStart);
564 if (actualLineStart == null)
565 lineCopy.setStartItem(originalLineStart);
566 else
567 lineCopy.setStartItem(actualLineStart);
568
569 copies.add(lineCopy);
570 }
571
572 // recreate constraints
573 for (Constraint c : constraints) {
574 Item start = lineEndMap.get(c.getStart());
575 Item end = lineEndMap.get(c.getEnd());
576 int id = DisplayIO.getCurrentFrame().getNextItemID();
577 if (start != null && end != null) {
578 new Constraint(start, end, id, c.getType());
579 }
580 }
581
582 // BROOK
583 for (InteractiveWidget iw : widgets) {
584 try {
585
586 InteractiveWidget icopy = iw.copy();
587 copies.addAll(icopy.getItems());
588
589 } catch (InteractiveWidgetNotAvailableException e) {
590 e.printStackTrace();
591 }
592 }
593
594 return copies;
595 }
596
597 private static void ReplaceAll(List<Item> list, Item replace, Item with) {
598 // replace all other instances with the copy
599 for (int pos = 0; pos < list.size(); pos++)
600 if (list.get(pos) == replace) {
601 list.set(pos, with);
602 }
603 }
604
605 /**
606 * Attempts to create a new line that starts from the given Item
607 * ('unreeling'). The Item must already have at least one line, and not be a
608 * line itself to be unreeled from.
609 *
610 * @param toUnreelFrom
611 * The Item that will be one end point of the new line
612 * @return A List containing the newly created Item and Line that unreel
613 * from the given Item, or null if this Item cannot be unreeled
614 * from.
615 */
616 public static List<Item> UnreelLine(Item toUnreelFrom) {
617 // the Item must already have one line to be unreeled from
618 if (toUnreelFrom == null || toUnreelFrom.getLines().size() < 1)
619 return null;
620
621 List<Item> unreel = new ArrayList<Item>(2);
622 unreel.add(toUnreelFrom);
623 unreel.addAll(toUnreelFrom.getLines());
624 return UnreelLine(unreel);
625 }
626
627 /**
628 * Attempts to create a new line that starts from the given list of Items
629 * ('unreeling'). The List must contain only one non-line Item. The non-line
630 * Item must already have at least one line to be unreeled from.
631 *
632 * @param toUnreel
633 * The List containing the Item that will be one end point of the
634 * new line
635 * @return A List of the newly created Item and Line that unreel from the
636 * Item in the given List, or null if this List cannot be unreeled
637 * from.
638 */
639 public static List<Item> UnreelLine(List<Item> toUnreel) {
640 Item origEnd = null;
641 // find the end being unreeled from
642 for (Item item : toUnreel) {
643 // we dont want to unreel anything other than lines
644 if (!(item.isLineEnd() || item instanceof Line)) {
645 return null;
646 }
647 // find the dot to unreel from
648 if (item.isLineEnd()) {
649 // if there are multiple ends in the list, return
650 if (origEnd != null)
651 return null;
652
653 origEnd = item;
654 }
655 }
656
657 // copy the original endpoint
658 Item copy = origEnd.copy();
659 copy.removeAllLines();
660 copy.removeAllConstraints();
661
662 // create a new line
663 Line line = new Line(origEnd, copy, DisplayIO.getCurrentFrame()
664 .getNextItemID());
665 // copy.setFloating(true);
666 origEnd.setArrowheadLength(0);
667 // copy.setArrowheadLength(0);
668
669 List<Item> toReturn = new LinkedList<Item>();
670 toReturn.add(copy);
671 toReturn.add(line);
672 return toReturn;
673 }
674
675 public static void New() {
676 EnclosedCheck(DisplayIO.getCurrentFrame().getItems());
677 }
678
679 public static void Old() {
680 OldEnclosedCheck(DisplayIO.getCurrentFrame().getItems());
681 }
682
683 /**
684 * Updates the connectedToAnnotation flags for all items
685 */
686 public static void UpdateConnectedToAnnotations(Collection<Item> items) {
687 // get all lineEnds on the Frame
688 Collection<Item> lineEnds = new LinkedHashSet<Item>();
689 for (Item i : items) {
690 i.setConnectedToAnnotation(false);
691 if (i.isLineEnd()) {
692 lineEnds.add(i);
693 }
694 }
695
696 // if there are no line endpoints on the Frame, then there can't be an
697 // enclosure
698 if (lineEnds.size() == 0)
699 return;
700
701 // Now find go through line ends and see if any are annotation items
702 while (lineEnds.size() > 0) {
703 Item item = lineEnds.iterator().next();
704 // If its an annotation item then set the flag for all its connected
705 // items
706 if (item.isAnnotation()) {
707 Collection<Item> connected = item.getAllConnected();
708 for (Item i : connected)
709 i.setConnectedToAnnotation(true);
710 lineEnds.removeAll(connected);
711 }
712 lineEnds.remove(item);
713 }
714 }
715
716 /**
717 * Checks through all Lines and Dots on the current Frame to detect if any
718 * form an enclosure, which can then be used to manipulate items within the
719 * polygon. If an enclosure is found, then the dots will have their
720 * enclosure value set to true, and a List is created that contains all the
721 * Dots in the order they were processed. Actual calculation of the Polygon
722 * is done dynamically (to account for Dots being moved).
723 */
724 public static void EnclosedCheck(Collection<Item> items) {
725 // get all lineEnds on the Frame
726 List<Item> lineEnds = new LinkedList<Item>();
727 for (Item i : items) {
728 if (i.isLineEnd()) {
729 i.setEnclosedList(null);
730 // Add line ends joined to 2 other lines
731 if (i.getLines().size() == 2)
732 lineEnds.add(i);
733 }
734 }
735
736 // if there are no line endpoints on the Frame, then there can't be an
737 // enclosure
738 if (lineEnds.size() == 0)
739 return;
740
741 // New approach
742 while (lineEnds.size() > 0) {
743 Item item = lineEnds.get(0);
744 // Get the lineEnds connected to this item
745 Collection<Item> connected = item.getAllConnected();
746 Collection<Item> connectedLineEnds = new LinkedHashSet<Item>();
747 for (Item itemToCheck : connected) {
748 if (itemToCheck.isLineEnd())
749 connectedLineEnds.add(itemToCheck);
750 }
751 // Check that all the line ends are in our lineEnds list
752 int oldSize = lineEnds.size();
753 // Remove all the items from our line ends list
754 lineEnds.removeAll(connectedLineEnds);
755 int newSize = lineEnds.size();
756 int connectedSize = connectedLineEnds.size();
757 // Check if all the connectedItems were in the lineEnds collection
758 if (oldSize == newSize + connectedSize) {
759 // Set them to be the enclosed list for each of the items
760 for (Item enclosedLineEnd : connectedLineEnds) {
761 enclosedLineEnd.setEnclosedList(connectedLineEnds);
762 }
763 }
764
765 }
766 }
767
768 /**
769 * Checks through all Lines and Dots on the current Frame to detect if any
770 * form an enclosure, which can then be used to manipulate items within the
771 * polygon. If an enclosure is found, then the dots will have their
772 * enclosure value set to true, and a List is created that contains all the
773 * Dots in the order they were processed. Actual calculation of the Polygon
774 * is done dynamically (to account for Dots being moved).
775 */
776 public static void OldEnclosedCheck(Collection<Item> items) {
777 _seen.clear();
778
779 // get all lineEnds on the Frame
780 List<Item> lineEnds = new ArrayList<Item>(0);
781 for (Item i : items) {
782 if (i.isLineEnd()) {
783 i.setEnclosedList(null);
784
785 if (i.getLines().size() == 2)
786 lineEnds.add(i);
787 }
788 }
789
790 // if there are no line endpoints on the Frame, then there can't be an
791 // enclosure
792 if (lineEnds.size() == 0)
793 return;
794
795 // TODO optimise this code!!
796 // iterate through all the lineEnds
797 for (Item searchFor : lineEnds) {
798 _seen.clear();
799
800 for (Line l : searchFor.getLines()) {
801 _seen.add(l);
802 if (traverse(searchFor, l.getOppositeEnd(searchFor))) {
803 _path.add(l.getOppositeEnd(searchFor));
804
805 for (Item i : _path)
806 i.setEnclosedList(_path);
807
808 _path = new ArrayList<Item>(0);
809
810 break;
811 }
812 }
813 }
814
815 }
816
817 private static List<Line> _seen = new ArrayList<Line>();
818
819 private static List<Item> _path = new ArrayList<Item>();
820
821 private static boolean traverse(Item toFind, Item searchFrom) {
822 if (toFind == null || searchFrom == null || !searchFrom.isLineEnd())
823 return false;
824
825 if (searchFrom.getLines().size() != 2)
826 return false;
827
828 if (toFind == searchFrom)
829 return true;
830
831 for (Line l : searchFrom.getLines()) {
832 if (!(_seen.contains(l))) {
833 _seen.add(l);
834 if (traverse(toFind, l.getOppositeEnd(searchFrom))) {
835 _path.add(l.getOppositeEnd(searchFrom));
836 return true;
837 }
838 }
839
840 }
841
842 return false;
843 }
844}
Note: See TracBrowser for help on using the repository browser.