source: trunk/src/org/expeditee/items/Item.java@ 87

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

Fixed some stuff with the SIMPLE debugger
Refactored the way the interpretor works to make it easier to give better error messages.

File size: 41.5 KB
Line 
1package org.expeditee.items;
2
3import java.awt.Color;
4import java.awt.Cursor;
5import java.awt.Dimension;
6import java.awt.Graphics2D;
7import java.awt.Point;
8import java.awt.Polygon;
9import java.awt.Rectangle;
10import java.awt.geom.AffineTransform;
11import java.awt.geom.Area;
12import java.util.ArrayList;
13import java.util.Collection;
14import java.util.ConcurrentModificationException;
15import java.util.LinkedHashSet;
16import java.util.LinkedList;
17import java.util.List;
18
19import org.expeditee.actions.Actions;
20import org.expeditee.actions.Simple;
21import org.expeditee.gui.DisplayIO;
22import org.expeditee.gui.Frame;
23import org.expeditee.gui.FrameGraphics;
24import org.expeditee.gui.FrameIO;
25import org.expeditee.gui.FrameUtils;
26import org.expeditee.io.Conversion;
27import org.expeditee.io.Logger;
28import org.expeditee.simple.Context;
29import org.expeditee.stats.AgentStats;
30
31/**
32 * Represents everything that can be drawn on the screen (text, lines, dots,
33 * images). Each specific type is a subclass of Item.
34 *
35 * @author jdm18
36 *
37 */
38public abstract class Item implements Comparable<Item>, Runnable {
39
40 // contains all dots (including this one) that form an enclosure
41 // if this dot is part of an enclosing shape
42 private Collection<Item> _enclosure = null;
43
44 public static final int LEFT_MARGIN = 13;
45
46 protected boolean _connectedToAnnotation = false;
47
48 public static final int PERMISSION_NONE = 0;
49
50 public static final int PERMISSION_FOLLOW_LINKS = 1;
51
52 public static final int PERMISSION_COPY = 2;
53
54 public static final int PERMISSION_TDFC = 3;
55
56 public static final int PERMISSION_FULL = 4;
57
58 public static final int NEAR_DISTANCE = 15;
59
60 /**
61 * The default Color to draw highlighting in
62 */
63 public static final int DEFAULT_HIGHLIGHT_THICKNESS = 2;
64
65 public static final Color DEFAULT_HIGHLIGHT = Color.RED;
66
67 public static final Color DEPRESSED_HIGHLIGHT = Color.GREEN;
68
69 public static final Color DISCONNECT_HIGHLIGHT = Color.BLUE;
70
71 public static final Color LINK_COLOR = Color.BLACK;
72
73 public static final Color ACTION_COLOR = Color.BLACK;
74
75 public static final Color LINK_ACTION_COLOR = Color.RED;
76
77 public static final Color DEFAULT_FOREGROUND = Color.BLACK;
78
79 public static final Color DEFAULT_BACKGROUND = Color.white;
80
81 public static final Color TRANSPARENT = new Color(0, 0, 0, 0);
82
83 /**
84 * The number of pixels highlighting should extend around Items.
85 */
86 public static final int XGRAVITY = 3;
87
88 public static final int MARGIN_RIGHT = 2;
89
90 public static final int MARGIN_LEFT = 15;
91
92 protected static final double DEFAULT_ARROWHEAD_RATIO = 0.5;
93
94 public static final Color GREEN = Color.GREEN.darker();
95
96 /**
97 * The Colors cycled through when using function keys to set the Color of
98 * this Item.
99 */
100 public static Color[] COLOR_WHEEL = { Color.BLACK, Color.RED, Color.BLUE,
101 Item.GREEN, Color.MAGENTA, Color.YELLOW.darker(), Color.WHITE, null };
102
103 public static Color[] FILL_COLOR_WHEEL = { Color.BLACK,
104 new Color(255, 150, 150), new Color(150, 150, 255),
105 new Color(150, 255, 150), new Color(255, 150, 255),
106 new Color(255, 255, 100), Color.WHITE, null };
107
108 public static final int UNCHANGED_CURSOR = -100;
109
110 public static final int DEFAULT_CURSOR = Cursor.DEFAULT_CURSOR;
111
112 public static final int HIDDEN_CURSOR = Cursor.CUSTOM_CURSOR;
113
114 public static final int TEXT_CURSOR = Cursor.TEXT_CURSOR;
115
116 public static final int CROP_CURSOR = Cursor.CROSSHAIR_CURSOR;
117
118 //The default value for integer attributes
119 public static final int DEFAULT_INTEGER = -1;
120
121 public static final int JUSTIFICATION_NONE = DEFAULT_INTEGER;
122
123 public static final int JUSTIFICATION_FULL = 0;
124
125 public static final int JUSTIFICATION_CENTER = 1;
126
127 public static final int JUSTIFICATION_RIGHT = 2;
128
129 public static final int JUSTIFICATION_LEFT = 3;
130
131 public static final int POINTTYPE_SQUARE = -1;
132
133 public static final int POINTTYPE_CIRCLE = 0;
134
135 public static void DuplicateItem(Item source, Item dest) {
136 dest.setX(source.getX());
137 dest.setY(source.getY());
138
139 dest.setActions(source.getAction());
140 dest.setActionCursorEnter(source.getActionCursorEnter());
141 dest.setActionCursorLeave(source.getActionCursorLeave());
142 dest.setActionEnterFrame(source.getActionEnterFrame());
143 dest.setActionLeaveFrame(source.getActionLeaveFrame());
144 dest.setActionMark(source.getActionMark());
145
146 dest.setBackgroundColor(source.getBackgroundColor());
147 dest.setBottomShadowColor(source.getBottomShadowColor());
148 dest.setColor(source.getColor());
149
150 dest.setData(source.getData());
151 dest.setTag(source.getTag());
152 dest.setFillColor(source.getFillColor());
153 dest.setFillPattern(source.getFillPattern());
154
155 dest.setHighlight(source.getHighlight());
156 dest.setLink(source.getLink());
157 dest.setLinkFrameset(source.getLinkFrameset());
158 dest.setLinkMark(source.getLinkMark());
159 dest.setLinkTemplate(source.getLinkTemplate());
160
161 dest.setMaxSize(source.getMaxSize());
162 dest.setOffset(source.getOffset());
163 dest.setOwner(source.getOwner());
164 dest.setThickness(source.getThickness());
165 dest.setSize(source.getSize());
166 dest.setTopShadowColor(source.getTopShadowColor());
167 dest.setLinePattern(source.getLinePattern());
168
169 dest.setFloating(source.isFloating());
170 dest.setArrow(source.getArrowheadLength(), source.getArrowheadRatio());
171
172 dest.setParent(source.getParent());
173 dest._mode = SelectedMode.None;
174 dest._lastMode = source._mode;
175
176 Frame parent = source.getParentOrCurrentFrame();
177 // TODO MIKE says maybe we could tighten up and only give items ID's if
178 // their
179 // current ID is negative?
180 if (parent != null) {
181 dest.setID(source.getParentOrCurrentFrame().getNextItemID());
182 }
183 }
184
185 public static int getGravity() {
186 return org.expeditee.gui.UserSettings.Gravity;
187 }
188
189 public static boolean showLineHighlight() {
190 return org.expeditee.gui.UserSettings.LineHighlight;
191 }
192
193 public enum SelectedMode {
194 None, Enclosed, Connected, Disconnect, Normal
195 }
196
197 public void setSelectedMode(SelectedMode mode) {
198 setSelectedMode(mode, DEFAULT_HIGHLIGHT);
199 }
200
201 protected SelectedMode _mode = SelectedMode.None;
202
203 private Point _offset = new Point(0, 0);
204
205 private int _x;
206
207 private int _y;
208
209 private int _id;
210
211 private String _creationDate = null;
212
213 private boolean _linkMark = true;
214
215 private boolean _actionMark = true;
216
217 private boolean _highlight = true;
218
219 private Dimension _maxSize = null;
220
221 private String _owner = null;
222
223 private String _link = null;
224
225 private StringBuffer _tag = new StringBuffer();
226
227 private List<String> _actionCursorEnter = null;
228
229 private List<String> _actionCursorLeave = null;
230
231 private List<String> _actionEnterFrame = null;
232
233 private List<String> _actionLeaveFrame = null;
234
235 public int Permission = PERMISSION_FULL;
236
237 // A fill color of null represents transparent
238 private Color _colorFill = null;
239
240 // A fore color of null represents the default color
241 private Color _color = null;
242
243 private Color _highlightColor = DEFAULT_HIGHLIGHT;
244
245 private Color _colorBackground = null;
246
247 private Color _colorTopShadow = null;
248
249 private Color _colorBottomShadow = null;
250
251 // the link\action circle
252 private Polygon _circle = null;
253
254 // the invalid link cross
255 private Polygon _circleCross = null;
256
257 private Frame _parent = null;
258
259 protected int _highlightThickness = 2;
260
261 // arrowhead parameters
262 private int _arrowheadLength = 0;
263
264 private double _arrowheadRatio = DEFAULT_ARROWHEAD_RATIO;
265
266 private Polygon _arrowhead = null;
267
268 // the list of lines that this point is part of.
269 private List<Line> _lines = new ArrayList<Line>();
270
271 private int[] _linePattern = null;
272
273 private boolean _floating = false;
274
275 // list of points constrained with this point
276 private List<Constraint> _constraints = new ArrayList<Constraint>();
277
278 private List<String> _actions = null;
279
280 private List<String> _data = null;
281
282 private String _link_frameset = null;
283
284 private String _link_template = null;
285
286 private String _fillPattern = null;
287
288 private boolean _visible = true;
289
290 private SelectedMode _lastMode = SelectedMode.None;
291
292 private float _thickness = -1.0F;
293
294 protected Item() {
295 _creationDate = Logger.EasyDateFormat("ddMMMyyyy:HHmm");
296 }
297
298 /**
299 * Adds an action to this Item.
300 *
301 * @param action
302 * The KMS action language to add to this Item
303 */
304 public void addAction(String action) {
305 if (action == null || action.equals("")) {
306 return;
307 }
308
309 if (_actions == null)
310 _actions = new LinkedList<String>();
311 _actions.add(action);
312 }
313
314 public void addAllConnected(Collection<Item> connected) {
315 if (!connected.contains(this))
316 connected.add(this);
317
318 for (Line line : getLines()) {
319 if (!connected.contains(line))
320 line.addAllConnected(connected);
321 }
322 }
323
324 /**
325 * Adds the given Constraint to this Dot
326 *
327 * @param c
328 * The Constraint to set this Dot as a member of.
329 */
330 public void addConstraint(Constraint c) {
331 // do not add duplicate constraint
332 if (_constraints.contains(c))
333 return;
334
335 _constraints.add(c);
336 }
337
338 /**
339 * Adds a given line to the list of lines that this Point is an end for.
340 *
341 * @param line
342 * The Line that this Point is an end of.
343 */
344 public void addLine(Line line) {
345 if (_lines.contains(line)) {
346 return;
347 }
348
349 _lines.add(line);
350 }
351
352 /**
353 * Items are sorted by their Y coordinate on the screen.
354 *
355 * @param i
356 * The Item to compare this Item to
357 * @return a negative integer, zero, or a positive integer as this object is
358 * less than, equal to, or greater than the specified object.
359 */
360 public int compareTo(Item i) {
361 return getY() - i.getY();
362 }
363
364 /**
365 * Every Item has an area around it defined by a Shape (typically a
366 * rectangle), this method returns true if the given x,y pair lies within
367 * the area and false otherwise.
368 *
369 * @param x
370 * The x coordinate to check
371 * @param y
372 * The y coordinate to check
373 * @return True if the Shape around this Item contains the given x,y pair,
374 * false otherwise.
375 */
376 public boolean contains(int x, int y) {
377 return getPolygon().contains(x, y);
378 }
379
380 /**
381 * Returns a deep copy of this Item, note: it is up to the receiver to
382 * change the Item ID etc as necessary.
383 *
384 * @return A deep copy of this Item.
385 */
386 public abstract Item copy();
387
388 public void delete() {
389 setVisible(false);
390 }
391
392 public boolean equals(Object o) {
393 if (o instanceof Item) {
394 Item i = (Item) o;
395 return i.getID() == getID()
396 && ((i.getParent() == _parent) || (i.getParent() != null && i
397 .getParent().equals(_parent)));
398
399 } else
400 return false;
401 }
402
403 /**
404 * Returns a list of any action code (KMS action language) that is currently
405 * associated with this Item
406 *
407 * @return A List of action code associated with this Item, or null if none
408 * has been assigned.
409 */
410 public List<String> getAction() {
411 return _actions;
412 }
413
414 public List<String> getData() {
415 return _data;
416 }
417
418 public List<String> getActionCursorEnter() {
419 return _actionCursorEnter;
420 }
421
422 public List<String> getActionCursorLeave() {
423 return _actionCursorLeave;
424 }
425
426 public List<String> getActionEnterFrame() {
427 return _actionEnterFrame;
428 }
429
430 public List<String> getActionLeaveFrame() {
431 return _actionLeaveFrame;
432 };
433
434 public boolean getActionMark() {
435 return _actionMark;
436 }
437
438 /**
439 * Gets all the items connected to this item. Uses a recursive approach to
440 * search connected points.
441 *
442 * @return
443 */
444 public Collection<Item> getAllConnected() {
445 Collection<Item> list = new LinkedHashSet<Item>();
446 addAllConnected(list);
447 return list;
448 }
449
450 public Area getArea() {
451 return new Area(getPolygon());
452 }
453
454 public String getArrow() {
455 if (!hasVisibleArrow())
456 return null;
457
458 String ratio = "" + getArrowheadRatio();
459 if (ratio.length() - ratio.indexOf(".") > 2)
460 ratio = ratio.substring(0, ratio.indexOf(".") + 3);
461
462 return getArrowheadLength() + " " + ratio;
463 }
464
465 public Polygon getArrowhead() {
466 return _arrowhead;
467 }
468
469 public int getArrowheadLength() {
470 return _arrowheadLength;
471 }
472
473 public double getArrowheadRatio() {
474 return _arrowheadRatio;
475 }
476
477 public Color getBackgroundColor() {
478 return _colorBackground;
479 }
480
481 /**
482 * Returns the Color being used to shade the bottom half of this Item's
483 * border. This can be NULL if no Color is being used
484 *
485 * @return The Color displayed on the bottom\right half of this Item's
486 * border.
487 */
488 public Color getBottomShadowColor() {
489 return _colorBottomShadow;
490 }
491
492 /**
493 * Returns the height (in pixels) of this Item's surrounding area.
494 *
495 * @return The height (in pixels) of this Item's surrounding area as
496 * returned by getArea().
497 */
498 public int getBoundsHeight() {
499 return getPolygon().getBounds().height;
500 }
501
502 /**
503 * Returns the width (in pixels) of this Item's surrounding area.
504 *
505 * @return The width (in pixels) of this Item's surrounding area as returned
506 * by getArea().
507 */
508 public int getBoundsWidth() {
509 return getPolygon().getBounds().width;
510 }
511
512 protected Polygon getCircle() {
513 if (_circle == null) {
514 int points = 16;
515
516 double radians = 0.0;
517 int xPoints[] = new int[points];
518 int yPoints[] = new int[xPoints.length];
519
520 for (int i = 0; i < xPoints.length; i++) {
521 // circle looks best if these values are not related to gravity
522 xPoints[i] = (int) (3.5 * Math.cos(radians)) + 6;// (2 *
523 // GRAVITY);
524 yPoints[i] = (int) (3.5 * Math.sin(radians)) + 3;// GRAVITY;
525 radians += (2.0 * Math.PI) / xPoints.length;
526 }
527
528 _circle = new Polygon(xPoints, yPoints, xPoints.length);
529 }
530
531 return _circle;
532 }
533
534 protected Polygon getCircleCross() {
535
536 if (_circleCross == null) {
537 _circleCross = new Polygon();
538
539 Rectangle bounds = getCircle().getBounds();
540 int x1 = (int) bounds.getMinX();
541 int x2 = (int) bounds.getMaxX();
542 int y1 = (int) bounds.getMinY();
543 int y2 = (int) bounds.getMaxY();
544 int midX = ((x2 - x1) / 2) + x1;
545 int midY = ((y2 - y1) / 2) + y1;
546
547 _circleCross.addPoint(x1, y1);
548 _circleCross.addPoint(x2, y2);
549 _circleCross.addPoint(midX, midY);
550 _circleCross.addPoint(x1, y2);
551 _circleCross.addPoint(x2, y1);
552 _circleCross.addPoint(midX, midY);
553 }
554
555 return _circleCross;
556 }
557
558 public Color getColor() {
559 return _color;
560 }
561
562 public Collection<Item> getConnected() {
563 List<Item> conn = new LinkedList<Item>();
564 conn.add(this);
565
566 conn.addAll(getLines());
567 return conn;
568 }
569
570 public String getConstraintIDs() {
571 if (_constraints == null || _constraints.size() == 0)
572 return null;
573
574 String cons = "";
575
576 for (Constraint c : _constraints)
577 cons += c.getID() + " ";
578
579 return cons.trim();
580 }
581
582 /*
583 * public void setLinkValid(boolean val) { _isValidLink = val; }
584 */
585
586 /**
587 * Returns a List of any Constraints that this Dot is a memeber of.
588 *
589 * @return a List of Constraints that this Dot is a member of.
590 */
591 public List<Constraint> getConstraints() {
592 return _constraints;
593 }
594
595 public String getTag() {
596 if (_tag != null && _tag.length() > 0)
597 return _tag.toString();
598 return null;
599 }
600
601 public String getDateCreated() {
602 return _creationDate;
603 }
604
605 public Color getFillColor() {
606 return _colorFill;
607 }
608
609 public String getFillPattern() {
610 return _fillPattern;
611 }
612
613 public String getFirstAction() {
614 if (_actions == null || _actions.size() == 0)
615 return null;
616 return _actions.get(0);
617 }
618
619 public boolean getHighlight() {
620 return _highlight;
621 }
622
623 public Color getHighlightColor() {
624 return _highlightColor;
625 }
626
627 /**
628 * Returns the ID of this Item, which must be unique for the Frame.
629 *
630 * @return The ID of this Item.
631 */
632 public int getID() {
633 return _id;
634 }
635
636 /**
637 * Returns the list of IDs of the Lines that this Dot is an end of.
638 *
639 * @return The list of Line IDs that this point is part of.
640 */
641 public String getLineIDs() {
642 String lineID = null;
643
644 if (_lines.size() > 0) {
645 lineID = "" + _lines.get(0).getID();
646
647 for (int i = 1; i < _lines.size(); i++)
648 lineID += " " + _lines.get(i).getID();
649 }
650
651 return lineID;
652 }
653
654 public int[] getLinePattern() {
655 return _linePattern;
656 }
657
658 /**
659 * Returns a list of Lines where this Dot is an end.
660 *
661 * @return A list of the Lines that this Dot is an end for or null if no
662 * Lines have been added.
663 */
664 public List<Line> getLines() {
665 return _lines;
666 }
667
668 /**
669 * Returns the name of a Frame that this Item links to, or null if this Item
670 * has no link.
671 *
672 * @return The name of a Frame that this Item links to (if any) or null if
673 * this Item does not link to anything.
674 */
675 public String getLink() {
676 return _link;
677 }
678
679 public String getLinkFrameset() {
680 return _link_frameset;
681 }
682
683 public boolean getLinkMark() {
684 return _linkMark;
685 }
686
687 public String getLinkTemplate() {
688 return _link_template;
689 }
690
691 public Dimension getMaxSize() {
692 return _maxSize;
693 }
694
695 public Point getOffset() {
696 return _offset;
697 }
698
699 public String getOwner() {
700 return _owner;
701 }
702
703 public Color getPaintBackgroundColor() {
704 if (_colorBackground == null) {
705 if (getParent() != null && getParent().getBackgroundColor() != null)
706 return getParent().getBackgroundColor();
707
708 return DEFAULT_BACKGROUND;
709 }
710
711 return _colorBackground;
712 }
713
714 /**
715 * Returns the foreground Color of this Item.
716 *
717 * @return The Color of this item (foreground)
718 */
719 public Color getPaintColor() {
720 // If color is null then get the paint foregroundColor for the frame the
721 // item is on which is a color adjusted to suit the background
722 if (_color == null) {
723 if (getParent() != null)
724 return getParent().getPaintForegroundColor();
725
726 Frame current = DisplayIO.getCurrentFrame();
727 if (current == null)
728 return DEFAULT_FOREGROUND;
729
730 return current.getPaintForegroundColor();
731 }
732
733 return _color;
734 }
735
736 protected Color getPaintHighlightColor() {
737 if (getParent() != null
738 && getParent().getPaintBackgroundColor()
739 .equals(_highlightColor))
740 return getParent().getPaintForegroundColor();
741
742 return _highlightColor;
743 }
744
745 public Frame getParent() {
746 return _parent;
747 }
748
749 /**
750 * Returns the Shape that surrounds this Item representing this Item's
751 * 'gravity'.
752 *
753 * @return The Shape (rectangle) surrounding this Item, which represents
754 * this Items 'gravity'.
755 */
756 public abstract Polygon getPolygon();
757
758 public Point getPosition() {
759 return new Point(getX(), getY());
760 }
761
762 /**
763 * Returns the size of this Item. For Text this is the Font size, for Lines
764 * and Dots this is the thickness.
765 *
766 * @return The size of this Item.
767 */
768 public int getSize() {
769 return -1;
770 }
771
772 /**
773 * Returns the Color being used to shade the top half of this Item's border.
774 * This can be NULL if no Color is being used
775 *
776 * @return The Color displayed on the top\left half of this Item's border.
777 */
778 public Color getTopShadowColor() {
779 return _colorTopShadow;
780 }
781
782 public String getTypeAndID() {
783 return "T " + getID();
784 }
785
786 public int getWidth() {
787 return 0;
788 }
789
790 /**
791 * Returns the X coordinate of this Item on the screen
792 *
793 * @return The X coordinate of this Item on the screen
794 */
795 public int getX() {
796 return _x;
797 }
798
799 /**
800 * Returns the Y coordinate of this Item on the screen
801 *
802 * @return The Y coordinate of this Item on the screen
803 */
804 public int getY() {
805 return _y;
806 }
807
808 protected boolean hasVisibleArrow() {
809 return false;
810 }
811
812 /**
813 * Checks if the given Shape intersects with the Shape around this Item.
814 * Note: Both Shape objects should be rectangles for this to work properly.
815 *
816 * @param s
817 * The Shape to check.
818 * @return True if the two Shapes overlap, False otherwise.
819 */
820 public boolean intersects(Polygon p) {
821 if (p == null)
822 return false;
823
824 // return p.getBounds().intersects(getArea().getBounds());
825 Area a = new Area(p);
826
827 a.intersect(this.getArea());
828 return !a.isEmpty();
829 }
830
831 /**
832 * Note: Pictures always return False, as they should be drawn even when no
833 * other annotation Items are.
834 *
835 * @return True if this Item is an annotation, False otherwise.
836 */
837 public boolean isAnnotation() {
838 return false;
839 }
840
841 public boolean isFloating() {
842 return _floating;
843 }
844
845 public boolean isFrameName() {
846 if (this.getParent() == null || this.getParent().getNameItem() != this)
847 return false;
848 return true;
849 }
850
851 public boolean isFrameTitle() {
852 if (this.getParent() == null || this.getParent().getTitleItem() != this)
853 return false;
854 return true;
855 }
856
857 /**
858 * Returns True if this Item is currently highlighted.
859 *
860 * @return True if this Item is currently highlighted on the screen, False
861 * otherwise.
862 */
863 public boolean isHighlighted() {
864 return _mode != SelectedMode.None;
865 }
866
867 /**
868 * Tests if the item link is a valid framename, that is, the String must
869 * begin with a character, end with a number with 0 or more letters and
870 * numbers in between. If there is a dot in the framename all the chars
871 * after it must be digits.
872 *
873 * @return True if the given framename is proper, false otherwise.
874 */
875 public boolean isLinkValid() {
876 if (FrameIO.isPositiveInteger(getLink()))
877 return true;
878
879 if (FrameIO.isValidFrameName(getLink()))
880 return true;
881 return false;
882 }
883
884 public boolean isNear(int x, int y) {
885
886 int xLeft = getPolygon().getBounds().x;
887 int yTop = getPolygon().getBounds().y;
888
889 return (x > xLeft - NEAR_DISTANCE && y > yTop - NEAR_DISTANCE
890 && x < xLeft + getBoundsWidth() + NEAR_DISTANCE && y < yTop
891 + getBoundsHeight() + NEAR_DISTANCE);
892 }
893
894 /**
895 * Checks if this item is a frame title.
896 *
897 * @return true if the item is a frame title
898 */
899 /*
900 * public boolean isTitle() { // check if the title has been assigned if
901 * (getID() >= 0 && this instanceof Text) if (getX() < 200 && getY() <
902 * getSize() + system.io.KMSConversion.Y_ADJUST) return true; return false; }
903 */
904
905 public boolean isOldTag() {
906 if (this instanceof Text)
907 if (((Text) this).getTextList().get(0).toLowerCase().equals("@old"))
908 return true;
909 return false;
910 }
911
912 /**
913 * Merges this Item with the given Item. The merger Item should be left
914 * unchanged after this method. The merger may or may not be the same class
915 * as this Item, exact behaviour depends on the subclass, No-op is allowed.
916 *
917 * @param merger
918 * The Item to merge with
919 * @return any Item that should remain on the cursor
920 */
921 public abstract Item merge(Item merger, int mouseX, int mouseY);
922
923 /**
924 * Displays this item directly on the screen. Note: All Items are
925 * responsible for their own drawing, buffering, etc.
926 *
927 * @param g
928 * The Graphics to draw this Item on.
929 */
930 public abstract void paint(Graphics2D g);
931
932 public void paintFill(Graphics2D g) {
933 if (getFillColor() != null && getEnclosingDots() != null) {
934 g.setColor(getFillColor());
935 // Shape s = getEnclosedShape();
936 // Rectangle b = s.getBounds();
937 // GradientPaint gp = new GradientPaint((int) (b.x + b.width * 0.3),
938 // b.y, getFillColor(), (int) (b.x + b.width * 1.3), b.y,
939 // Color.white);
940 // g.setPaint(gp);
941 // g.fill(s);
942 g.fillPolygon(getEnclosedShape());
943 }
944 }
945
946 /**
947 * This method performs all the actions in an items list. If it contains a
948 * link as well the link is used as the source frame for all acitons.
949 */
950 public void performActions() {
951 Frame sourceFrame = null;
952 // if a link exists make it the source frame for this action
953 if (getLink() != null) {
954 sourceFrame = FrameUtils.getFrame(getAbsoluteLink());
955 }
956 // if no link exists or the link is bad then use the
957 // currently displayed frame as the source frame for the
958 // action
959 if (sourceFrame == null) {
960 sourceFrame = DisplayIO.getCurrentFrame();
961 }
962
963 for (String s : getAction()) {
964 Actions.PerformAction(sourceFrame, this, s);
965 }
966 }
967
968 /**
969 * Removes all constraints that this item has.
970 *
971 */
972 public void removeAllConstraints() {
973 while (_constraints.size() > 0) {
974 Constraint c = _constraints.get(0);
975 c.getEnd().removeConstraint(c);
976 c.getStart().removeConstraint(c);
977 }
978 }
979
980 /**
981 * Clears the list of Lines that this Dot is an end of. Note: This only
982 * clears this Dot's list and does not have any affect on the Lines or other
983 * Dots.
984 */
985 public void removeAllLines() {
986 _lines.clear();
987 }
988
989 /**
990 * Removes the given Constraint from the list of constraintss that this Dot
991 * is a part of.
992 *
993 * @param c
994 * The Constraint that this Dot is no longer a part of.
995 */
996 public void removeConstraint(Constraint c) {
997 _constraints.remove(c);
998 }
999
1000 /**
1001 * Removes the given Line from the list of lines that this Dot is an end
1002 * for.
1003 *
1004 * @param line
1005 * The Line that this Dot is no longer an end of.
1006 */
1007 public void removeLine(Line line) {
1008 _lines.remove(line);
1009 }
1010
1011 public void run() {
1012 try {
1013 Simple.ProgramStarted();
1014 Simple.RunFrameAndReportError(this, new Context());
1015 Simple.ProgramFinished();
1016 FrameGraphics.DisplayMessage(AgentStats.getStats(), GREEN);
1017 } catch (ConcurrentModificationException ce) {
1018 Simple.ProgramFinished();
1019 ce.printStackTrace();
1020 } catch (Exception e) {
1021 FrameGraphics.LinkedErrorMessage(e.getMessage());
1022 Simple.ProgramFinished();
1023 }
1024 }
1025
1026 /**
1027 * Check if it has a relative link if so make it absolute.
1028 *
1029 */
1030 public void setAbsoluteLink() {
1031 String link = getLink();
1032 if (link == null)
1033 return;
1034 // Check if all the characters are digits and hence it is a relative
1035 // link
1036 for (int i = 0; i < link.length(); i++) {
1037 if (!Character.isDigit(link.charAt(i)))
1038 return;
1039 }
1040
1041 // Make it an absolute link
1042 String framesetName;
1043
1044 if (_parent == null)
1045 framesetName = DisplayIO.getCurrentFrame().getFramesetName();
1046 else
1047 framesetName = _parent.getFramesetName();
1048
1049 setLink(framesetName + link);
1050 }
1051
1052 /**
1053 * Sets any action code (KMS action language) that should be associated with
1054 * this Item Each entry in the list is one line of code
1055 *
1056 * @param actions
1057 * The lines of code to associate with this Item
1058 */
1059 public void setActions(List<String> actions) {
1060 if (actions == null || actions.size() == 0)
1061 _actions = null;
1062 else
1063 _actions = new LinkedList<String>(actions);
1064 }
1065
1066 public void setData(List<String> data) {
1067 if (data == null || data.size() == 0)
1068 _data = null;
1069 else
1070 _data = new LinkedList<String>(data);
1071 }
1072
1073 public void setActionCursorEnter(List<String> enter) {
1074 _actionCursorEnter = enter;
1075 }
1076
1077 public void setActionCursorLeave(List<String> leave) {
1078 _actionCursorLeave = leave;
1079 }
1080
1081 public void setActionEnterFrame(List<String> enter) {
1082 _actionEnterFrame = enter;
1083 }
1084
1085 public void setActionLeaveFrame(List<String> leave) {
1086 _actionLeaveFrame = leave;
1087 }
1088
1089 public void setActionMark(boolean val) {
1090 _actionMark = val;
1091 }
1092
1093 /**
1094 * Sets whether this Item is an Annotation.
1095 *
1096 * @param val
1097 * True if this Item is an Annotation, False otherwise.
1098 */
1099 public abstract void setAnnotation(boolean val);
1100
1101 /**
1102 * Used to set this Line as an Arrow. If length and ratio are 0, no arrow is
1103 * shown.
1104 *
1105 * @param length
1106 * The how far down the shaft of the line the arrowhead should
1107 * come.
1108 * @param ratio
1109 * The ratio of the arrow's length to its width.
1110 */
1111 public void setArrow(int length, double ratio) {
1112 _arrowheadLength = length;
1113 _arrowheadRatio = ratio;
1114 updateArrowPolygon();
1115 }
1116
1117 public void setArrowhead(Polygon arrow) {
1118 _arrowhead = arrow;
1119 }
1120
1121 public void setArrowheadLength(int length) {
1122 _arrowheadLength = length;
1123 updateArrowPolygon();
1124 }
1125
1126 public void setArrowheadRatio(double ratio) {
1127 _arrowheadRatio = ratio;
1128 updateArrowPolygon();
1129 }
1130
1131 public void setBackgroundColor(Color c) {
1132 _colorBackground = c;
1133 }
1134
1135 /**
1136 * Sets the Color to use on the bottom and right sections of this Item's
1137 * border. If top is NULL, then the Item's background Color will be used.
1138 *
1139 * @param top
1140 * The Color to display in the bottom and right sections of this
1141 * Item's border.
1142 */
1143 public void setBottomShadowColor(Color bottom) {
1144 _colorBottomShadow = bottom;
1145 }
1146
1147 /**
1148 * Sets the foreground Color of this Item to the given Color.
1149 *
1150 * @param c
1151 */
1152 public void setColor(Color c) {
1153 _color = c;
1154 }
1155
1156 public void setConstraintIDs(String IDs) {
1157 }
1158
1159 public void setConstraints(List<Constraint> constraints) {
1160 _constraints = constraints;
1161 }
1162
1163 public void setTag(String newData) {
1164 if (newData != null)
1165 _tag = new StringBuffer(newData);
1166 else
1167 _tag = null;
1168 }
1169
1170 /**
1171 * Sets the created date of this Frame to the given String.
1172 *
1173 * @param date
1174 * The date to use for this Frame.
1175 */
1176 public void setDateCreated(String date) {
1177 _creationDate = date;
1178 }
1179
1180 public void setFillColor(Color c) {
1181 _colorFill = c;
1182
1183 for (Line line : _lines) {
1184 Item other = line.getOppositeEnd(this);
1185 if (other.getFillColor() != c)
1186 other.setFillColor(c);
1187 }
1188 }
1189
1190 public void setFilledHighlight(boolean value) {
1191 }
1192
1193 public void setFillPattern(String patternLink) {
1194 _fillPattern = patternLink;
1195 }
1196
1197 public void setFloating(boolean val) {
1198 _floating = val;
1199 }
1200
1201 public void setHighlight(boolean val) {
1202 _highlight = val;
1203 }
1204
1205 /**
1206 * Sets the ID of this Item to the given Integer. Note: Items with ID's < 0
1207 * are not saved
1208 *
1209 * @param newID
1210 * The new ID to assign this Item.
1211 */
1212 public void setID(int newID) {
1213 _id = newID;
1214 }
1215
1216 /**
1217 * Sets the list of lines that this point is part of (may be set to null).
1218 *
1219 * @param lineID
1220 * A String of line ID numbers separated by spaces.
1221 */
1222 public void setLineIDs(String lineID) {
1223 }
1224
1225 public void setLinePattern(int[] pattern) {
1226 _linePattern = pattern;
1227
1228 for (Line line : getLines())
1229 line.setLinePattern(pattern);
1230 }
1231
1232 public void setLines(List<Line> lines) {
1233 _lines = lines;
1234
1235 for (Line line : lines)
1236 line.setLinePattern(getLinePattern());
1237 }
1238
1239 /**
1240 * Links this item to the given Frame, this may be set to null to remove a
1241 * link.
1242 *
1243 * @param frameName
1244 * The name of the Frame to link this item to.
1245 */
1246 public void setLink(String frameName) {
1247 if (FrameIO.isValidLink(frameName))
1248 _link = frameName;
1249 else
1250 FrameGraphics.ErrorMessage("[" + frameName
1251 + "] is not a valid frame name");
1252 // TODO make this throw exceptions etc...
1253 }
1254
1255 public void setLinkFrameset(String frameset) {
1256 if (frameset == null || FrameIO.isValidFramesetName(frameset))
1257 _link_frameset = frameset;
1258 else
1259 FrameGraphics.ErrorMessage("[" + frameset
1260 + "] is not a valid frameset name");
1261 // TODO make this throw exceptions etc...
1262 }
1263
1264 public void setLinkMark(boolean val) {
1265 _linkMark = val;
1266 }
1267
1268 public void setLinkTemplate(String template) {
1269 if (FrameIO.isValidLink(template))
1270 _link_template = template;
1271 else
1272 FrameGraphics.ErrorMessage("[" + template
1273 + "] is not a valid frame name");
1274 // TODO make this throw exceptions etc...
1275 }
1276
1277 /**
1278 * Sets the maximum coordinates on the screen that this item may occupy.
1279 * This is used by Text items to compute word-wrapping lengths.
1280 *
1281 * @param d
1282 * The Maximum size of the Frame containing this Item.
1283 */
1284 public void setMaxSize(Dimension d) {
1285 if (d != null) {
1286 _maxSize = d;
1287 updatePolygon();
1288 }
1289 }
1290
1291 public void setOffset(int x, int y) {
1292 _offset.setLocation(x, y);
1293 }
1294
1295 public void setOffset(Point p) {
1296 _offset.setLocation(p);
1297 }
1298
1299 public void setOwner(String own) {
1300 _owner = own;
1301 }
1302
1303 public void setParent(Frame frame) {
1304 _parent = frame;
1305 }
1306
1307 /**
1308 * Sets the position of this item on the screen
1309 *
1310 * @param x
1311 * The new X coordinate
1312 * @param y
1313 * The new Y coordinate
1314 */
1315 public void setPosition(int x, int y) {
1316 _x = x;
1317 _y = y;
1318
1319 updatePolygon();
1320
1321 // update the position of any dots that are constrained by this one
1322 for (Constraint c : _constraints) {
1323 Item other = c.getOppositeEnd(this);
1324
1325 // only set position if the other dot is still fixed to the
1326 // frame
1327 if (/*this.isFloating() &&*/ !other.isFloating()) {
1328 if (c.getType() == Constraint.HORIZONTAL) {
1329 if (other.getY() != y)
1330 other.setY(y);
1331 }
1332 if (c.getType() == Constraint.VERTICAL) {
1333 if (other.getX() != x)
1334 other.setX(x);
1335 }
1336 }
1337 }
1338
1339 for (Line line : getLines())
1340 line.updatePolygon();
1341 }
1342
1343 public void setPosition(Point position) {
1344 setPosition(position.x, position.y);
1345 }
1346
1347 public void setRelativeLink() {
1348 String link = getLink();
1349 if (link == null)
1350 return;
1351 assert (_parent != null);
1352 // Check if the link is for the current frameset
1353 if (_parent.getFramesetName().equalsIgnoreCase(
1354 Conversion.getFrameset(link))) {
1355 setLink("" + Conversion.getFrameNumber(link));
1356 }
1357 }
1358
1359 /**
1360 * Sets the size of this Item. For Text this is the Font size. For Lines and
1361 * Dots this is the thickness.
1362 */
1363 public void setSize(int size) {
1364 }
1365
1366 public void setThickness(float thick) {
1367 _thickness = thick;
1368 // update the size of any lines
1369 for (Line line : getLines())
1370 line.setThickness(thick);
1371 }
1372
1373 /**
1374 * Returns the thickness (in pixels) of this Dot.
1375 *
1376 * @return The 'thickness' of this Dot. (returns -1 if the thickness is not
1377 * set).
1378 */
1379 public float getThickness() {
1380 return _thickness;
1381 }
1382
1383 /**
1384 * Sets the Color to use on the top and left sections of this Item's border.
1385 * If top is NULL, then the Item's background Color will be used.
1386 *
1387 * @param top
1388 * The Color to display in the top and left sections of this
1389 * Item's border.
1390 */
1391 public void setTopShadowColor(Color top) {
1392 _colorTopShadow = top;
1393 }
1394
1395 public void setWidth(int width) throws UnsupportedOperationException {
1396 throw new UnsupportedOperationException(
1397 "Item type does not support width attribute!");
1398 }
1399
1400 /**
1401 * Sets the position of this Item on the X axis
1402 *
1403 * @param newX
1404 * The position on the X axis to assign to this Item
1405 */
1406 public void setX(int newX) {
1407 setPosition(newX, getY());
1408 }
1409
1410 /**
1411 * Sets the position of this Item on the Y axis
1412 *
1413 * @param newY
1414 * The position on the Y axis to assign to this Item
1415 */
1416 public void setY(int newY) {
1417 setPosition(getX(), newY);
1418 }
1419
1420 /**
1421 * Paints any highlighting of this Item. This may include changing the
1422 * thickness (lines) or painting a box around the item (Text, Images). If
1423 * val is True then the Graphics Color is changed to the highlight Color, if
1424 * False then the Graphics Color is left unchanged (for clearing of
1425 * highlighting).
1426 *
1427 * @param val
1428 * True if this Item should be highlighted, false if the
1429 * highlighting is being cleared.
1430 * @return The desired mouse cursor when this Item is highlighted (negative
1431 * means no change)
1432 */
1433 public int setSelectionColor() {
1434 return setSelectionColor(DEFAULT_HIGHLIGHT);
1435 }
1436
1437 public int setSelectionColor(Color c) {
1438 _highlightThickness = DEFAULT_HIGHLIGHT_THICKNESS;
1439 if (c != null)
1440 _highlightColor = c;
1441 else
1442 _highlightColor = DEFAULT_HIGHLIGHT;
1443
1444 return Item.UNCHANGED_CURSOR;
1445 }
1446
1447 private void updateArrowPolygon() {
1448 if (getArrowheadLength() < 0 || getArrowheadRatio() < 0)
1449 _arrowhead = null;
1450 else {
1451 _arrowhead = new Polygon();
1452 _arrowhead.addPoint((int) getX(), (int) getY());
1453 _arrowhead
1454 .addPoint(
1455 (int) getX() - getArrowheadLength(),
1456 (int) (getY() - (getArrowheadLength() * getArrowheadRatio())));
1457 _arrowhead.addPoint((int) getX(), (int) getY());
1458 _arrowhead
1459 .addPoint(
1460 (int) getX() - getArrowheadLength(),
1461 (int) (getY() + (getArrowheadLength() * getArrowheadRatio())));
1462 }
1463 }
1464
1465 protected abstract void updatePolygon();
1466
1467 public void setVisible(boolean state) {
1468 this._visible = state;
1469 }
1470
1471 public boolean isVisible() {
1472 return _visible;
1473 }
1474
1475 /**
1476 * Raised whenever the item is removed, added, no longer in view (That is,
1477 * when it is not on any of the current frames, of overlays of the current
1478 * frames) or has become visible. That is, when it is either on a current
1479 * frames, or an overlay of a current frame.
1480 *
1481 * @param e
1482 * The event
1483 */
1484 public void onParentStateChanged(ItemParentStateChangedEvent e) {
1485 }
1486
1487 public void setSelectedMode(SelectedMode mode, Color color) {
1488 setSelectionColor(color);
1489 _lastMode = _mode;
1490 _mode = mode;
1491 }
1492
1493 public void restoreLastMode(Color selectionColor) {
1494 setSelectionColor(selectionColor);
1495 if (_mode != SelectedMode.None)
1496 return;
1497 _mode = _lastMode;
1498 _lastMode = SelectedMode.None;
1499 }
1500
1501 public SelectedMode getSelectedMode() {
1502 return _mode;
1503 }
1504
1505 public void anchor() {
1506 Frame current = getParentOrCurrentFrame();
1507 setID(current.getNextItemID());
1508 setOffset(0, 0);
1509 setParent(current);
1510
1511 current.addItem(this);
1512 current.setResort(true);
1513 setRelativeLink();
1514 setFloating(false);
1515 }
1516
1517 /**
1518 * Gets the parent frame if it is set or the current frame if this item does
1519 * not have a parent set.
1520 *
1521 * @return
1522 */
1523 public Frame getParentOrCurrentFrame() {
1524 // if the item is from an overlay the parent will NOT be null
1525 if (getParent() == null) {
1526 return DisplayIO.getCurrentFrame();
1527 }
1528 return getParent();
1529 }
1530
1531 /**
1532 * Sets the list of Dots (including this one) that form a closed shape.
1533 * Passing null sets this dot back to its normal (non-enclosed) state.
1534 *
1535 * @param enclosed
1536 * The List of Dots including this one that form a closed shape,
1537 * or null.
1538 */
1539 public void setEnclosedList(Collection<Item> enclosed) {
1540 _enclosure = enclosed;
1541 }
1542
1543 /**
1544 * Returns the polygon that represents the shape created by all the Dots in
1545 * this Dot's enclosed list. If the list is null, then null is returned.
1546 *
1547 * @return A Polygon the same shape and position as created by the Dots in
1548 * the enclosed list.
1549 */
1550 public Polygon getEnclosedShape() {
1551 if (_enclosure == null)
1552 return null;
1553
1554 Polygon poly = new Polygon();
1555 for (Item d : _enclosure) {
1556 poly.addPoint(d.getX(), d.getY());
1557 }
1558
1559 return poly;
1560 }
1561
1562 /**
1563 * Returns the list of Dots that, along with this Dot, form an enclosed
1564 * polygon. If this Dot is not part of an enclosure null may be returned.
1565 *
1566 * @return The List of Dots that form an enclosed shape with this Dot, or
1567 * null if this Dot is not part of an enclosure.
1568 */
1569 public Collection<Item> getEnclosingDots() {
1570 return _enclosure;
1571 }
1572
1573 /**
1574 * Returns whether this Dot has an assigned enclosure list of other Dots.
1575 * The result is the same as getEnclosedShape() != null.
1576 *
1577 * @return True if this Dot has an enclosure list of other Dots, false
1578 * otherwise.
1579 */
1580 public boolean isEnclosed() {
1581 return _enclosure != null;
1582 }
1583
1584 public boolean isLineEnd() {
1585 return _lines.size() > 0;
1586 }
1587
1588 /**
1589 * Method that is called to notify an item that is on the end of a line that
1590 * its line has changed color.
1591 *
1592 * @param c
1593 * the new color for the line
1594 */
1595 protected void lineColorChanged(Color c) {
1596 for (Line l : getLines()) {
1597 if (l.getColor() != c)
1598 l.setColor(c);
1599 }
1600 }
1601
1602 /**
1603 * Checks if this item is off the left or top of the screen
1604 *
1605 * @return
1606 */
1607 public boolean offScreenTopOrLeft() {
1608 Rectangle itemRect = getArea().getBounds();
1609 // Check that the bottom right corner of this item is on the screen
1610 if (itemRect.x + itemRect.width >= 0
1611 && itemRect.y + itemRect.height >= 0)
1612 return false;
1613 // Check if all the items it is connected to are offscreen
1614 for (Item i : getAllConnected()) {
1615 Rectangle iRect = i.getArea().getBounds();
1616 // Check that the bottom right corner of this item is on the screen
1617 if (iRect.x + iRect.width >= 0 && iRect.y + iRect.height >= 0) {
1618 return false;
1619 }
1620 }
1621 return true;
1622 }
1623
1624 public void setConnectedToAnnotation(boolean val) {
1625 _connectedToAnnotation = val;
1626 }
1627
1628 public boolean isConnectedToAnnotation() {
1629 return _connectedToAnnotation;
1630 }
1631
1632 public void setData(String data) {
1633 if (data == null || data.length() == 0)
1634 _data = null;
1635 else {
1636 _data = new LinkedList<String>();
1637 _data.add(data);
1638 }
1639 }
1640
1641 public void setAction(String string) {
1642 _actions = new LinkedList<String>();
1643 _actions.add(string);
1644 }
1645
1646 protected int getLinkYOffset() {
1647 return 0;
1648 }
1649
1650 /**
1651 * Paint the link symbol for the item if it is a
1652 *
1653 * @param g
1654 */
1655 protected void paintLink(Graphics2D g) {
1656 if (FrameGraphics.isAudienceMode())
1657 return;
1658
1659 if (getLink() != null || getAction() != null) {
1660 if (getLink() != null && getAction() != null) {
1661 g.setColor(LINK_ACTION_COLOR);
1662 } else if (getLink() != null) {
1663 g.setColor(LINK_COLOR);
1664 } else if (getAction() != null) {
1665 g.setColor(ACTION_COLOR);
1666 }
1667
1668 AffineTransform at = new AffineTransform();
1669 AffineTransform orig = g.getTransform();
1670 at.translate(getX() - LEFT_MARGIN, getY() + getLinkYOffset());
1671 g.setTransform(at);
1672
1673 if (getLinkMark() && getLink() != null) {
1674 g.drawPolygon(getCircle());
1675
1676 // if the link is not valid, cross out the circle
1677 if (!isLinkValid())
1678 g.drawPolygon(getCircleCross());
1679 }
1680
1681 if (getActionMark() && getAction() != null) {
1682 g.drawPolygon(getCircle());
1683 g.fillPolygon(getCircle());
1684
1685 // if the link is not valid, cross out the circle
1686 if (!isLinkValid() && getLink() != null) {
1687 g.setColor(getParent().getPaintBackgroundColor());
1688 g.drawPolygon(getCircleCross());
1689 }
1690 }
1691
1692 // reset the graphics tranformation
1693 g.setTransform(orig);
1694 }
1695 }
1696
1697 /**
1698 * Gets the distance between the start of the text and the left border of
1699 * the item. This distance changes depending on whether or not the item is
1700 * linked or has an associated action.
1701 *
1702 * @return the gap size in pixels
1703 */
1704 protected int getLeftMargin() {
1705 return ((getLinkMark() && getLink() != null)
1706 || (getActionMark() && getAction() != null) ? MARGIN_LEFT
1707 - MARGIN_RIGHT : MARGIN_RIGHT);
1708 }
1709
1710 public String getName() {
1711 return null;
1712 }
1713
1714 final public String getAbsoluteLinkTemplate() {
1715 return getAbsoluteLink(getLinkTemplate());
1716 }
1717
1718 final public String getAbsoluteLinkFrameset() {
1719 return getAbsoluteLink(getLinkFrameset());
1720 }
1721
1722 final public String getAbsoluteLink() {
1723 return getAbsoluteLink(getLink());
1724 }
1725
1726 /**
1727 * @param link
1728 * @return
1729 */
1730 private String getAbsoluteLink(String link) {
1731 if (link == null)
1732 return null;
1733 // assert (_parent!= null);
1734 if (_parent == null) {
1735 // if parent is null it is an item on the message box
1736 // so it must already be absolute
1737 assert (!FrameIO.isPositiveInteger(link));
1738 return link;
1739 }
1740
1741 // if its a relative link then return absolute
1742 if (FrameIO.isPositiveInteger(link)) {
1743 return _parent.getFramesetName() + link;
1744 }
1745 return link;
1746 }
1747}
Note: See TracBrowser for help on using the repository browser.