source: trunk/org/expeditee/gui/Frame.java@ 4

Last change on this file since 4 was 4, checked in by davidb, 16 years ago

Starting source code to Expeditee

File size: 30.6 KB
Line 
1package org.expeditee.gui;
2
3import java.awt.Color;
4import java.awt.Dimension;
5import java.awt.Image;
6import java.awt.Polygon;
7import java.awt.image.ImageObserver;
8import java.awt.image.VolatileImage;
9import java.util.ArrayList;
10import java.util.Collections;
11import java.util.LinkedList;
12import java.util.List;
13import java.util.Stack;
14
15import org.expeditee.io.Conversion;
16import org.expeditee.io.Logger;
17import org.expeditee.items.Dot;
18import org.expeditee.items.Item;
19import org.expeditee.items.ItemUtils;
20import org.expeditee.items.Line;
21import org.expeditee.items.Text;
22
23/**
24 * Represents a KMS Frame that is displayed on the screen. Also is a registered
25 * MouseListener on the Browser, and processes any MouseEvents directly.
26 *
27 * @author jdm18
28 *
29 */
30public class Frame implements ImageObserver {
31
32 public static final Color[] COLOR_WHEEL = { Color.BLACK, Color.GRAY,
33 new Color(235, 235, 235), new Color(225, 225, 255),
34 new Color(195, 255, 255), new Color(225, 255, 225),
35 new Color(255, 255, 195), new Color(255, 225, 225),
36 new Color(255, 195, 255), null };
37
38 // The various attributes of this Frame
39 /**
40 * TODO: Change these to non-string attributes (where applicable). All
41 * processing to\from Java types should be done in KMSReader and KMSWriter.
42 */
43 private String _frameset = null;
44
45 private int _number = -1;
46
47 private int _version = 1;
48
49 private int _fversion = -1;
50
51 private String _protection = null;
52
53 private String _owner = null;
54
55 private String _creationDate = null;
56
57 private String _modifiedUser = null;
58
59 private String _modifiedDate = null;
60
61 private String _frozenDate = null;
62
63 private Color _background;
64
65 private Color _foreground;
66
67 public String path;
68
69 private boolean _sorted = true;
70
71 // The items contained in this Frame
72
73 // records whether a change has been made to this Frame (for saving
74 // purposes).
75 private boolean _change = false;
76
77 private boolean _saved = false;
78
79 // list of deleted items that can be restored
80 private Stack<Item> _undo = new Stack<Item>();
81
82 // basically just a list of smaller objects?
83 // maybe a hashtable (id -> item?)
84 // Note: Needs to be able to be iterated through (for painting)
85 private List<Item> _body = new ArrayList<Item>();
86
87 public static List<Item> FreeItems = new ArrayList<Item>();
88
89 private int _lineCount = 0;
90
91 private int _itemCount = 1;
92
93 // The frameName to display on the screen
94 private Text _frameName = null;
95
96 // private Text _template = UserSettings.ItemTemplate.copy();
97
98 private List<Overlay> _overlays = new ArrayList<Overlay>();
99
100 private VolatileImage _buffer = null;
101
102 private boolean _validBuffer = true;
103
104 /**
105 * Default constructor, nothing is set.
106 */
107 public Frame() {
108 // _template.setParent(this);
109 }
110
111 public VolatileImage getBuffer() {
112 return _buffer;
113 }
114
115 public void setBuffer(VolatileImage newBuffer) {
116 _buffer = newBuffer;
117 // setBufferValid(true);
118 }
119
120 public boolean isBufferValid() {
121 if (_buffer != null && _buffer.contentsLost())
122 return false;
123
124 return _validBuffer;
125 }
126
127 public void setBufferValid(boolean newValue) {
128 _validBuffer = newValue;
129 }
130
131 public int getNextItemID() {
132 return ++_itemCount;
133 }
134
135 public void updateIDs(List<Item> items) {
136 for (Item i : items)
137 if (!(i instanceof Line))
138 i.setID(getNextItemID());
139 else
140 i.setID(++_lineCount);
141 }
142
143 /**
144 * Returns whether this Frame has been changed and required saving to disk.
145 *
146 * @return True if this Frame has been altered, false otherwise.
147 */
148 public boolean hasChanged() {
149 // virtual frames are never saved
150 if (_number == -1)
151 return false;
152
153 return _change;
154 }
155
156 /**
157 * Sets whether this Frame should be saved to disk.
158 *
159 * @param value
160 * False if this Frame should be saved to disk, False otherwise.
161 */
162 public void setChanged(boolean value) {
163 _change = value;
164
165 if (_change)
166 setBufferValid(false);
167 }
168
169 // indicates the frame has changed
170 private void change() {
171 setChanged(true);
172 }
173
174 /**
175 * Returns an ArrayList of all Items currently on the Frame (excludes Items
176 * attached to the cursor).
177 *
178 * @return The list of Item objects that are on this Frame.
179 */
180 public List<Item> getItems() {
181
182 if (!_sorted) {
183 Collections.sort(_body);
184 _sorted = true;
185 }
186
187 return _body;
188 }
189
190 /**
191 * Returns a list of all the non annotation text items on the frame which
192 * are not the title or frame name.
193 *
194 * @return the list of body text items.
195 */
196 public List<Text> getBodyTextItems() {
197 List<Text> bodyTextItems = new ArrayList<Text>();
198 Text frameTitle = getTitle();
199
200 for (Item i : getItems()) {
201 // only add up normal body text items
202 if (i instanceof Text && i != _frameName && i != frameTitle
203 && !i.isAnnotation()) {
204 bodyTextItems.add((Text) i);
205 }
206 }
207
208 return bodyTextItems;
209 }
210
211 /**
212 * Gets the last item on the frame that is a non annotation item but is also
213 * text.
214 *
215 * @return the last non annotation text item.
216 */
217 public Text getLastNonAnnotationTextItem() {
218 List<Item> items = getItems();
219
220 // find the last non-annotation text item
221 for (int i = (items.size() - 1); i >= 0; i--) {
222 Item it = items.get(i);
223
224 if (it instanceof Text && !it.isAnnotation()) {
225 return (Text) it;
226 }
227 }
228 return null;
229 }
230
231 /**
232 * Iterates through the list of items on the frame, and returns one with the
233 * given id if one exists, otherwise returns null.
234 *
235 * @param id
236 * The id to search for in the list of items
237 * @return The item on this frame with the given ID, or null if one is not
238 * found.
239 */
240 public Item getItemWithID(int id) {
241 for (Item i : _body)
242 if (i.getID() == id)
243 return i;
244
245 return null;
246 }
247
248 /**
249 * Sets this Frame's Title which is displayed in the top left corner.
250 *
251 * @param title
252 * The title to assign to this Frame
253 */
254 public void setTitle(String title) {
255 if (title == null || title == "")
256 return;
257
258 boolean oldchange = _change;
259
260 // remove any numbering this title has
261 title = title.replaceAll("^\\d*[.] *", "");
262 Text frameTitle = getTitle();
263
264 if (frameTitle == null) {
265 if (UserSettings.TitleTemplate == null) {
266 frameTitle = new Text(getNextItemID(), title);
267 frameTitle.setPosition(Item.MARGIN_LEFT
268 + org.expeditee.io.Conversion.X_ADJUST,
269 org.expeditee.io.Conversion.Y_ADJUST);
270 } else {
271 frameTitle = UserSettings.TitleTemplate.copy();
272 frameTitle.setID(this.getNextItemID());
273 frameTitle.setText(title);
274 }
275 addItem(frameTitle);
276 } else {
277 frameTitle.setText(title);
278 title = ItemUtils.StripTagSymbol(title);
279 String autoBulletText = FrameKeyboardActions.getAutoBullet(title);
280 if (autoBulletText.length() > 0)
281 frameTitle.stripFirstWord();
282 }
283
284 FrameUtils.Parse(this);
285
286 // do not save if this is the only change
287 setChanged(oldchange);
288 }
289
290 public Text getTitle() {
291 List<Item> items = getItems();
292 for (Item i : items) {
293 if (i instanceof Text /* && !i.isAnnotation() */&& i != _frameName)
294 return (Text) i;
295 }
296
297 return null;
298 }
299
300 public Text getName() {
301 return _frameName;
302 }
303
304 public Text getItemTemplate() {
305 Text t = UserSettings.ItemTemplate;
306
307 // check for an updated template...
308 for (Item i : this.getItems()) {
309 if (ItemUtils.isTag(i, ItemUtils.TAG_ITEM_TEMPLATE)) {
310 t = (Text) i;
311 break;
312 }
313 }
314
315 // If the item is linked apply any attribute pairs on the child frame
316 String link = t.getAbsoluteLink();
317 // need to get link first because copy doesnt copy the link
318 t = t.copy();
319 if (link != null) {
320 t.setLink(null);
321 Frame childFrame = FrameIO.LoadFrame(link);
322 if (childFrame != null) {
323 // read in attribute value pairs
324 for (Text attribute : childFrame.getBodyTextItems()) {
325 AttributeUtils.SetAttribute(t, attribute);
326 }
327 }
328 }
329
330 return t;
331 }
332
333 public Text getAnnotationTemplate() {
334 Text t = null;
335 // check for an updated template...
336 for (Item i : this.getItems()) {
337 if (ItemUtils.isTag(i, ItemUtils.TAG_ANNOTATION_TEMPLATE)) {
338 t = (Text) i;
339 break;
340 }
341 }
342
343 if (t == null) {
344 if (UserSettings.AnnotationTemplate != null)
345 t = UserSettings.AnnotationTemplate;
346 else
347 t = getItemTemplate();
348 }
349
350 return t.copy();
351 }
352
353 public Text getCodeCommentTemplate() {
354 Text t = null;
355
356 // check for an updated template...
357 for (Item i : this.getItems()) {
358 if (ItemUtils.isTag(i, ItemUtils.TAG_CODE_COMMENT_TEMPLATE)) {
359 t = (Text) i;
360 break;
361 }
362 }
363
364 if (t == null) {
365 if (UserSettings.CodeCommentTemplate != null)
366 t = UserSettings.CodeCommentTemplate;
367 else
368 t = getItemTemplate();
369 }
370
371 return t.copy();
372 }
373
374 /*
375 * public void setItemTemplate(Text template) { if (template != null)
376 * _template = template; else _template = UserSettings.ItemTemplate.copy(); }
377 */
378
379 /**
380 * Returns any items on this frame that are within the given Shape. Also
381 * returns any Items on overlay frames that are within the Shape.
382 *
383 * @param shape
384 * The Shape to search for Items in
385 * @return All Items on this Frame or overlayed Frames for which
386 * Item.intersects(shape) return true.
387 */
388 public List<Item> getItemsWithin(Polygon poly) {
389 ArrayList<Item> results = new ArrayList<Item>();
390
391 for (Item i : _body)
392 if (i.intersects(poly)) {// || shape.contains(i.getX(),
393 // i.getY())){
394 if (!results.contains(i))
395 results.add(i);
396 /*
397 * List<Item> connected = i.getConnected(); for(Item item :
398 * connected) if(!results.contains(item))
399 * results.add(item);//All(i.getConnected());
400 */
401 }
402
403 for (Overlay o : _overlays)
404 results.addAll(o.Frame.getItemsWithin(poly));
405
406 /*
407 * ArrayList<Dot> toInclude = new ArrayList<Line>(0); //remove lines
408 * that do not have a point anchored in the polygon for(Item i :
409 * results){ if(i instanceof Line){ Line line = (Line) i;
410 * if(!(results.contains(line.getStartDot())) &&
411 * !(results.contains(line.getEndDot()))) removeLines.add(line); } }
412 *
413 * results.removeAll(removeLines);
414 */
415
416 return results;
417 }
418
419 /**
420 * Sets the name of this Frame to the given String, to be displayed in the
421 * upper right corner.
422 *
423 * @param name
424 * The name to use for this Frame.
425 */
426 public void setFrameset(String name) {
427 _frameset = name;
428 }
429
430 /**
431 * Adjusts frameset names so that a period is appended if they end in a
432 * digit.
433 *
434 * @param name
435 * the unadjusted frame set name
436 * @return the adjusted frame set name
437 */
438 public String getFramesetNameAdjusted() {
439 return _frameset
440 + (Character.isDigit(_frameset.charAt(_frameset.length() - 1)) ? "."
441 : "");
442 }
443
444 /**
445 * Adjusts a frameset name so a period is appended if it ends in a digit.
446 * This form of the frameset name is used when referencing frames in the
447 * frame set.
448 *
449 * @param frameset
450 * @return
451 */
452 public static String GetFramesetNameAdjusted(String frameset) {
453 return frameset
454 + (Character.isDigit(frameset.charAt(frameset.length() - 1)) ? "."
455 : "");
456 }
457
458 public void setFrameName(String framename) {
459 int num = Conversion.getFrameNumber(framename);
460 String frameset = Conversion.getFrameset(framename, false);
461
462 setFrameset(frameset);
463 setFrameNumber(num);
464 }
465
466 /**
467 * Sets the frame number of this Frame to the given integer
468 *
469 * @param number
470 * The number to set as the frame number
471 */
472 public void setFrameNumber(int number) {
473 _number = number;
474 boolean oldchange = _change;
475
476 int id;
477
478 if (_frameName != null) {
479 removeItem(_frameName);
480 id = _frameName.getID();
481 } else
482 id = -1 * getNextItemID();
483
484 _frameName = new Text(id);
485 _frameName.setText(getFramesetNameAdjusted() + _number);
486 _frameName.setPosition(FrameGraphics.getMaxFrameSize().width
487 - _frameName.getBoundsWidth() - Item.MARGIN_RIGHT
488 - org.expeditee.io.Conversion.X_ADJUST,
489 org.expeditee.io.Conversion.Y_ADJUST);
490 addItem(_frameName);
491
492 setChanged(oldchange);
493 }
494
495 /**
496 * Returns the number of this Frame.
497 *
498 * @return The Frame number of this Frame or -1 if it is not set.
499 */
500 public int getFrameNumber() {
501 return _number;
502 }
503
504 /**
505 * Sets the version of this Frame to the given String.
506 *
507 * @param version
508 * The version to use for this Frame.
509 */
510 public void setVersion(int version) {
511 _version = version;
512 }
513
514 /**
515 * Sets the format version of this Frame to the given String.
516 *
517 * @param version
518 * The format version to use for this Frame.
519 */
520 public void setFormatVersion(int version) {
521 _fversion = version;
522 }
523
524 /**
525 * Sets the protection of this Frame to the given String.
526 *
527 * @param protection
528 * The protection to use for this Frame.
529 */
530 public void setProtection(String protection) {
531 _protection = protection;
532 }
533
534 /**
535 * Sets the owner of this Frame to the given String.
536 *
537 * @param owner
538 * The owner to use for this Frame.
539 */
540 public void setOwner(String owner) {
541 _owner = owner;
542 }
543
544 /**
545 * Sets the created date of this Frame to the given String.
546 *
547 * @param date
548 * The date to use for this Frame.
549 */
550 public void setDateCreated(String date) {
551 _creationDate = date;
552 _modifiedDate = date;
553 for (Item i : _body) {
554 i.setDateCreated(date);
555 }
556 }
557
558 public void resetDateCreated() {
559 setDateCreated(Logger.EasyDateFormat("ddMMMyyyy:HHmm"));
560 }
561
562 /**
563 * Sets the last modifying user of this Frame to the given String.
564 *
565 * @param user
566 * The user to set as the last modifying user.
567 */
568 public void setLastModifyUser(String user) {
569 _modifiedUser = user;
570 }
571
572 /**
573 * Sets the last modified date of this Frame to the given String.
574 *
575 * @param date
576 * The date to set as the last modified date.
577 */
578 public void setLastModifyDate(String date) {
579 _modifiedDate = date;
580 }
581
582 /**
583 * Sets the last frozen date of this Frame to the given String.
584 *
585 * @param date
586 * The date to set as the last frozen date.
587 */
588 public void setFrozenDate(String date) {
589 _frozenDate = date;
590 }
591
592 public void setResort(boolean value) {
593 _sorted = !value;
594 }
595
596 /**
597 * Adds the given Item to the body of this Frame.
598 *
599 * @param item
600 * The Item to add to this Frame.
601 */
602 public void addItem(Item item) {
603 if (item != null) {
604 if (_body.contains(item)) {
605 System.out.println("Item (" + item.getClass().getSimpleName()
606 + ") with ID " + item.getID() + " already in body.");
607 return;
608 }
609
610 if (item instanceof Line)
611 _lineCount++;
612
613 _itemCount = Math.max(_itemCount, item.getID());
614
615 _body.add(item);
616 item.setParent(this);
617
618 _sorted = false;
619
620 item.setMaxSize(FrameGraphics.getMaxFrameSize());
621 change();
622 }
623 }
624
625 public void setMaxSize(Dimension max) {
626 if (max == null)
627 return;
628
629 for (Item i : _body)
630 i.setMaxSize(max);
631
632 _frameName.setPosition(FrameGraphics.getMaxFrameSize().width
633 - _frameName.getBoundsWidth() - Item.MARGIN_RIGHT
634 - org.expeditee.io.Conversion.X_ADJUST,
635 org.expeditee.io.Conversion.Y_ADJUST);
636 }
637
638 public void addAllItems(List<Item> toAdd) {
639 for (Item i : toAdd)
640 addItem(i);
641 }
642
643 public void removeAllItems(List<Item> toRemove) {
644 for (Item i : toRemove)
645 removeItem(i);
646 }
647
648 public void removeItem(Item item) {
649 if (_body.remove(item))
650 change();
651 }
652
653 /**
654 * Adds the given list of Items to the undo stack. This is the same as
655 * calling addToUndo() for each Item in the list.
656 *
657 * @param items
658 * The List of Items to add to the undo stack.
659 */
660 public void addAllToUndo(List<Item> items) {
661 if (items.size() < 1)
662 return;
663
664 String id = "" + _undo.size();
665
666 for (Item i : items) {
667 i.setData(id);
668 _undo.push(i);
669 }
670 }
671
672 public void addToUndo(Item item) {
673 if (item == null)
674 return;
675
676 item.setData("" + _undo.size());
677 _undo.push(item);
678 }
679
680 public void undo() {
681 Item undo = null;
682
683 if (_undo.size() <= 0)
684 return;
685
686 undo = _undo.pop();
687
688 // if the change was to characteristics
689 if (_body.contains(undo)) {
690 Item old = _body.get(_body.indexOf(undo));
691 _body.set(_body.indexOf(old), undo);
692 // the item was deleted
693 } else {
694 List<Item> toRestore = new LinkedList<Item>();
695 toRestore.add(undo);
696
697 // remove any connected items at the top of the stack
698 while (_undo.size() > 0) {
699 Item next = _undo.peek();
700 // if this item was connected to one already picked up, remove
701 // it from the stack
702 if (toRestore.contains(next))
703 _undo.pop();
704 // else, if this item should be restored (deleted in an enclosed
705 // set)
706 else if (next.getData().equals(undo.getData())) {
707 _undo.pop();
708 toRestore.add(next);
709 // otherwise, we are done
710 } else
711 break;
712 }
713
714 // if these items were deleted from a frame, add them
715 addAllItems(toRestore);
716
717 for (Item i : toRestore) {
718 if (i instanceof Line) {
719 Line line = (Line) i;
720 line.getStartItem().addLine(line);
721 line.getEndItem().addLine(line);
722 }
723 }
724 }
725
726 change();
727 FrameGraphics.Repaint();
728 ItemUtils.EnclosedCheck(_body);
729 }
730
731 /**
732 * Returns the frameset of this Frame
733 *
734 * @return The name of this Frame's frameset.
735 */
736 public String getFramesetName() {
737 return _frameset;
738 }
739
740 public String getFrameName() {
741 return getFramesetNameAdjusted() + _number;
742 }
743
744 public Item getFrameNameItem() {
745 return _frameName;
746 }
747
748 /**
749 * Returns the format version of this Frame
750 *
751 * @return The version of this Frame.
752 */
753 public int getVersion() {
754 return _version;
755 }
756
757 public int getFormatVersion() {
758 return _fversion;
759 }
760
761 public String getProtection() {
762 return _protection;
763 }
764
765 public String getOwner() {
766 return _owner;
767 }
768
769 public String getDateCreated() {
770 return _creationDate;
771 }
772
773 public String getLastModifyUser() {
774 return _modifiedUser;
775 }
776
777 public String getLastModifyDate() {
778 return _modifiedDate;
779 }
780
781 public String getFrozenDate() {
782 return _frozenDate;
783 }
784
785 public void setBackgroundColor(Color back) {
786 _background = back;
787 change();
788 FrameGraphics.Repaint();
789 }
790
791 public Color getBackgroundColor() {
792 return _background;
793 }
794
795 public Color getPaintBackgroundColor() {
796 if (_background == null)
797 return DisplayIO.DEFAULT_BACKGROUND;
798
799 return _background;
800 }
801
802 public void setForegroundColor(Color front) {
803 _foreground = front;
804 change();
805 FrameGraphics.Repaint();
806 }
807
808 public Color getForegroundColor() {
809 return _foreground;
810 }
811
812 public Color getPaintForegroundColor() {
813 final int GRAY = 127;
814 final int THRESHOLD = 10;
815
816 if (_foreground == null) {
817 Color back = getPaintBackgroundColor();
818 if (Math.abs(back.getRed() - GRAY) < THRESHOLD
819 && Math.abs(back.getBlue() - GRAY) < THRESHOLD
820 && Math.abs(back.getGreen() - GRAY) < THRESHOLD)
821 return Color.WHITE;
822
823 Color fore = new Color(Math.abs(255 - back.getRed()), Math
824 .abs(255 - back.getGreen()), Math.abs(255 - back.getBlue()));
825 return fore;
826 // return Item.DEFAULT_FOREGROUND;
827 }
828
829 return _foreground;
830 }
831
832 public String toString() {
833 String s = "";
834 s += "Name: " + _frameset + _number + "\n";
835 s += "Version: " + _version + "\n";
836 s += "Format Version: " + _fversion + "\n";
837 s += "Protection: " + _protection + "\n";
838 s += "Owner: " + _owner + "\n";
839 s += "Date Created: " + _creationDate + "\n";
840 s += "Last Mod. User: " + _modifiedUser + "\n";
841 s += "Last Mod. Date: " + _modifiedDate + "\n";
842 s += "Last Froz. Date: " + _frozenDate + "\n";
843
844 s += "\n";
845 s += "\n";
846
847 s += "Items: " + _body.size() + "\n";
848
849 return s;
850 }
851
852 public Item getItemAbove(Item current) {
853 int ind = _body.indexOf(current);
854 if (ind == -1)
855 return null;
856
857 // loop through all items above this one, return the first match
858 for (int i = ind - 1; i >= 0; i--) {
859 Item check = _body.get(i);
860
861 if (FrameUtils.inSameColumn(check, current))
862 return check;
863 }
864
865 return null;
866 }
867
868 /**
869 * Updates any Images that require it from their ImageObserver (Principally
870 * Animated GIFs)
871 */
872 public boolean imageUpdate(Image img, int infoflags, int x, int y,
873 int width, int height) {
874 FrameGraphics.ForceRepaint();
875
876 if (DisplayIO.getCurrentFrame() == this)
877 return true;
878
879 return false;
880 }
881
882 /**
883 * Gets the text items that are in the same column and below a specified
884 * item. Frame title and name are excluded from the column list.
885 *
886 * @param from
887 * The Item to get the column for.
888 */
889 public List<Item> getColumn(Item from) {
890 // Check that this item is on the current frame
891 if (!_body.contains(from))
892 return null;
893
894 // Make sure the items are sorted
895 Collections.sort(_body);
896
897 if (from == null) {
898 from = getLastNonAnnotationTextItem();
899 }
900
901 if (from == null)
902 return null;
903
904 /**
905 * TODO: Check
906 */
907
908 List<Item> column = new ArrayList<Item>();
909
910 // Create a list of items consisting of the item 'from' and all the
911 // items below it which are also in the same column as it
912 for (int i = _body.indexOf(from); i < _body.size(); i++) {
913 Item item = _body.get(i);
914 if (isNormalTextItem(item)) {
915 if (FrameUtils.inSameColumn(from, item))
916 column.add(item);
917 }
918 }
919
920 return column;
921 }
922
923 /**
924 * Adds the given Frame to the list of overlays Frames being drawn with this
925 * Frame.
926 *
927 * @param overlay
928 * The Frame to add
929 */
930 public void addOverlay(Overlay overlay) {
931 if (_overlays == null || overlay == null)
932 _overlays = new ArrayList<Overlay>();
933
934 _overlays.add(overlay);
935 }
936
937 /**
938 * Removes the given Frame from the list of overlay Frames being drawn with
939 * this Frame.
940 *
941 * @param overlay
942 * The Frame to remove
943 */
944 public void removeOverlay(Frame overlay) {
945 _overlays.remove(overlay);
946 FrameGraphics.Repaint();
947 }
948
949 public List<Overlay> getOverlays() {
950 return _overlays;
951 }
952
953 public void clearOverlays() {
954 _overlays.clear();
955 }
956
957 public void addAllOverlays(List<Overlay> overlays) {
958 _overlays.addAll(overlays);
959 }
960
961 @Override
962 public boolean equals(Object o) {
963 if (o instanceof String) {
964 return (String.CASE_INSENSITIVE_ORDER.compare((String) o,
965 getFrameName()) == 0);
966 }
967
968 if (o instanceof Frame) {
969 return getFrameName().equals(((Frame) o).getFrameName());
970 }
971
972 return super.equals(o);
973 }
974
975 /**
976 * Merge one frames contents into another.
977 *
978 * @param toMergeWith
979 */
980 private void merge(Frame toMergeWith) {
981 if (toMergeWith == null)
982 return;
983
984 List<Item> copies = ItemUtils.CopyItems(toMergeWith.getItems());
985
986 for (Item i : copies) {
987 if (i.getID() >= 0) {
988 i.setID(this.getNextItemID());
989 addItem(i);
990 }
991 }
992 }
993
994 /**
995 * TODO document what this method is actually doing and why Merge text?!?!
996 *
997 * @param toMerge
998 * @return the items that cant be merged?!?!
999 */
1000 public List<Item> merge(List<Item> toMerge) {
1001 ArrayList<Item> remain = new ArrayList<Item>(0);
1002
1003 for (Item i : toMerge) {
1004 if (!(i instanceof Text))
1005 remain.add(i);
1006 else {
1007 if (!AttributeUtils.SetAttribute(this, (Text) i)) {
1008 if (i.getLink() != null)
1009 merge(FrameIO.LoadFrame(i.getAbsoluteLink()));
1010 else if (FrameIO
1011 .isValidFrameName(((Text) i).getFirstLine())) {
1012 merge(FrameIO.LoadFrame(((Text) i).getFirstLine()));
1013 }
1014 }
1015 }
1016 }
1017
1018 return remain;
1019 }
1020
1021 /**
1022 * Removes all non-title non-annotation items from this Frame. All removed
1023 * items are added to the backup-stack.
1024 */
1025 public void clear() {
1026 List<Item> newBody = new ArrayList<Item>(0);
1027
1028 for (Item i : _body)
1029 if (i.isAnnotation() || i == getName() || i == getTitle())
1030 newBody.add(i);
1031
1032 _body.removeAll(newBody);
1033 addAllToUndo(_body);
1034 _body = newBody;
1035 }
1036
1037 /**
1038 * Creates a new Text Item with no text. The newly created Item is a copy
1039 * the ItemTemplate if one is present, and inherits all the attributes of
1040 * the Template
1041 *
1042 * @return The newly created Text Item
1043 */
1044 public Text createNewText(String text) {
1045 Text t = createBlankText(text);
1046 t.setText(text);
1047
1048 return t;
1049 }
1050
1051 public Text createBlankText(String templateType) {
1052 Text t;
1053 if (templateType.length() == 0)
1054 t = getItemTemplate().copy();
1055 else
1056 t = getItemTemplate(templateType.charAt(0));
1057
1058 // reset attributes
1059 t.setID(getNextItemID());
1060 t.setMaxSize(FrameGraphics.getMaxFrameSize());
1061 t.setPosition(DisplayIO.getMouseX(), DisplayIO.getMouseY());
1062 t.setText("");
1063 return t;
1064 }
1065
1066 private Text getItemTemplate(char firstChar) {
1067 switch (firstChar) {
1068 case '@':
1069 return getAnnotationTemplate();
1070 case '/':
1071 return getCodeCommentTemplate();
1072 default:
1073 return getItemTemplate();
1074 }
1075 }
1076
1077 public Text createNewText() {
1078 return createNewText("");
1079 }
1080
1081 public Text addText(int x, int y, String text, String action) {
1082 Text t = createNewText(text);
1083 t.setPosition(x, y);
1084 t.addAction(action);
1085
1086 addItem(t);
1087 return t;
1088 }
1089
1090 public Text addText(int x, int y, String text, String action, String link) {
1091 Text t = addText(x, y, text, action);
1092 t.setLink(link);
1093 return t;
1094 }
1095
1096 public Dot addDot(int x, int y) {
1097 Dot d = new Dot(x, y, getNextItemID());
1098 addItem(d);
1099 return d;
1100 }
1101
1102 /**
1103 * Creates a JMenu from the Items present on this Frame and adds it to the
1104 * Menus on the Display
1105 */
1106 /*
1107 * public void createMenu() { for (Item i : _body) { if (ItemUtils.isTag(i,
1108 * ItemUtils.TAG_MENU) && i.getLink() != null) { Frame nextMenu =
1109 * FrameIO.LoadFrame(i.getLink()); JMenu menu = nextMenu.createSubMenu();
1110 * DisplayIO.addMenu(menu); } } }
1111 */
1112
1113 /**
1114 * Creates a new JMenu from the Items present on this Frame
1115 *
1116 * @return The newly created JMenu
1117 */
1118 /*
1119 * private JMenu createSubMenu() { Text frameTitle = getTitle();
1120 *
1121 * if (frameTitle == null) FrameUtils.Parse(this);
1122 *
1123 * if (frameTitle == null || frameTitle.getFirstLine() == null) return null;
1124 *
1125 * JMenu menu = new JMenu(frameTitle.getFirstLine());
1126 *
1127 * boolean literal = false; String litTitle = null;
1128 *
1129 * for (Item i : _body) { // if the @lit tag is active if (literal) {
1130 * literal = false; if (litTitle == null) litTitle = ((Text)
1131 * i).getFirstLine(); JMenuItem item = new JMenuItem(litTitle);
1132 * item.addActionListener(new MenuAction(i, true)); menu.add(item); //
1133 * non-annotation items with links or actions are put on the // menu } else
1134 * if (i != _frameName && i instanceof Text && !i.isAnnotation() &&
1135 * (i.getLink() != null || i.getAction() != null)) { JMenuItem item = new
1136 * JMenuItem(((Text) i).getText().get(0)); item.addActionListener(new
1137 * MenuAction(i, false)); menu.add(item); // if this is another menu frame }
1138 * else if (i.getLink() != null && ItemUtils.isTag(i, ItemUtils.TAG_MENU)) {
1139 * Frame nextMenu = FrameIO.LoadFrame(i.getLink());
1140 * menu.add(nextMenu.createSubMenu()); // if this menu is continued on
1141 * another frame } else if (i.getLink() != null && ItemUtils.isTag(i,
1142 * ItemUtils.TAG_MENU_NEXT)) {
1143 *
1144 * Frame nextMenu = FrameIO.LoadFrame(i.getLink()); JMenu nmenu =
1145 * nextMenu.createSubMenu(); for(int m = 0; m < nmenu.getComponentCount();
1146 * m++) menu.add(nmenu.getComponent(m)); // if this is a @lit tag, then the
1147 * next item is copied } else if (ItemUtils.isTag(i, ItemUtils.TAG_LITERAL)) {
1148 * literal = true; String title = ItemUtils.StripTag(((Text)
1149 * i).getFirstLine(), ItemUtils.GetTag(ItemUtils.TAG_LITERAL)); if
1150 * (title.length() > 0) litTitle = title; else litTitle = null; } }
1151 *
1152 * return menu; }
1153 */
1154
1155 /*
1156 * private class MenuAction implements ActionListener { private Item _source =
1157 * null;
1158 *
1159 * private boolean _copy = false;
1160 *
1161 * public MenuAction(Item source, boolean copy) { _source = source; _copy =
1162 * copy; }
1163 *
1164 * public void actionPerformed(ActionEvent ae) { if (_copy) { Item copy =
1165 * _source.copy(); copy.setX(DisplayIO.getMouseX());
1166 * copy.setY(DisplayIO.getMouseY()); FrameMouseActions.pickup(copy); return; }
1167 *
1168 * if (_source.getAction() != null) { _source.performActions(); } else {
1169 * FrameUtils.DisplayFrame(_source.getLink()); } } }
1170 */
1171
1172 public boolean isSaved() {
1173 return _saved;
1174 }
1175
1176 public void setSaved() {
1177 _saved = true;
1178 _change = false;
1179 }
1180
1181 public static boolean rubberbandingLine() {
1182 return FreeItems.size() == 2
1183 && (FreeItems.get(0) instanceof Line || FreeItems.get(1) instanceof Line);
1184 }
1185
1186 public static boolean itemAttachedToCursor() {
1187 return FreeItems.size() > 0;
1188 }
1189
1190 public static boolean textItemAttachedToCursor() {
1191 return itemAttachedToCursor() && FreeItems.get(0) instanceof Text;
1192 }
1193
1194 public static Item getItemAttachedToCursor() {
1195 if (itemAttachedToCursor())
1196 return FreeItems.get(0);
1197
1198 return null;
1199 }
1200
1201 /**
1202 * Tests if an item is a non title, non frame name, non special annotation
1203 * text item.
1204 *
1205 * @param it
1206 * the item to be tested
1207 * @return true if the item is a normal text item
1208 */
1209 public boolean isNormalTextItem(Item it) {
1210 if (it instanceof Text && it != getTitle() && it != _frameName
1211 && !((Text) it).isSpecialAnnotation()) {
1212 return true;
1213 }
1214
1215 return false;
1216 }
1217
1218 /**
1219 * Moves the mouse to the end of the text item with a specified index.
1220 *
1221 * @param index
1222 */
1223 public boolean moveMouseToTextItem(int index) {
1224 List<Item> items = getItems();
1225 int itemsFound = 0;
1226 for (int i = 0; i < items.size(); i++) {
1227 Item it = items.get(i);
1228 if (isNormalTextItem(it))
1229 itemsFound++;
1230 if (itemsFound > index) {
1231 DisplayIO.setCursorPosition(((Text) it)
1232 .getEndParagraphPosition().x, it.getY());
1233 DisplayIO.resetCursorOffset();
1234 FrameGraphics.Repaint();
1235 return true;
1236 }
1237 }
1238
1239 return false;
1240 }
1241
1242 /*
1243 * public boolean moveMouseToNextTextItem(int index) { List<Item> items =
1244 * getItems(); int itemsFound = 0; for (int i = 0; i < items.size(); i++) {
1245 * Item it = items.get(i); if ( isNormalTextItem(it)) itemsFound++; if
1246 * (itemsFound > index) {
1247 * DisplayIO.setCursorPosition(((Text)it).getEndParagraphPosition().x,
1248 * it.getY()); DisplayIO.resetCursorOffset(); FrameGraphics.Repaint();
1249 * return true; } }
1250 *
1251 * return false; }
1252 */
1253
1254 /**
1255 * Searches for an annotation item called start to be used as the default
1256 * cursor location when TDFC occurs.
1257 */
1258 public boolean moveMouseToDefaultLocation() {
1259 List<Item> items = getItems();
1260
1261 for (Item it : items) {
1262 if (it instanceof Text) {
1263 Text t = (Text) it;
1264 if (t.getTextNoList().toLowerCase().startsWith("@start:")
1265 || t.getTextNoList().toLowerCase().equals("@start")) {
1266 t.stripFirstWord();
1267
1268 if (t.getTextNoList().equals(""))
1269 DisplayIO.getCurrentFrame().removeItem(t);
1270 if (!Frame.itemAttachedToCursor()) {
1271 DisplayIO.setCursorPosition(((Text) it)
1272 .getEndParagraphPosition());
1273 DisplayIO.resetCursorOffset();
1274 }
1275 FrameGraphics.Repaint();
1276 return true;
1277 }
1278 }
1279 }
1280
1281 return false;
1282 }
1283
1284 /**
1285 * Gets the file name that actions should use to export files created by
1286 * running actions from this frame.
1287 *
1288 * @return the fileName if the frame contains an '@file' tag. Returns the
1289 * name of the frame if the tag isnt on the frame.
1290 */
1291 public String getExportFileName() {
1292 Text tag = ItemUtils.FindTag(getItems(), "@file:");
1293 if (tag != null) {
1294 String file = ItemUtils.StripTag(tag.getFirstLine(), "@file:");
1295 file = file.trim();
1296 if (file.length() > 0)
1297 return file;
1298 }
1299
1300 return _frameName.getTextNoList();
1301 }
1302
1303 public void toggleBackgroundColor() {
1304 setBackgroundColor(ColorUtils.getNextColor(_background,
1305 Frame.COLOR_WHEEL));
1306 }
1307}
Note: See TracBrowser for help on using the repository browser.