source: trunk/src/org/expeditee/gui/Frame.java@ 24

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

Valid frameset names must not begin and end with a letter, and be all letters and digits in between. Thus removing the need for framesetNameAdjustment methods.

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