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

Last change on this file since 1417 was 1417, checked in by bln4, 5 years ago

Removed redundancy.

File size: 120.1 KB
Line 
1/**
2 * Item.java
3 * Copyright (C) 2010 New Zealand Digital Library, http://expeditee.org
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19package org.expeditee.items;
20
21import java.util.ArrayList;
22import java.util.Collection;
23import java.util.ConcurrentModificationException;
24import java.util.HashMap;
25import java.util.HashSet;
26import java.util.LinkedHashSet;
27import java.util.LinkedList;
28import java.util.List;
29import java.util.Map;
30import java.util.Set;
31
32import org.expeditee.actions.Actions;
33import org.expeditee.actions.IncorrectUseOfStatementException;
34import org.expeditee.actions.Javascript;
35import org.expeditee.actions.Misc;
36import org.expeditee.actions.Simple;
37import org.expeditee.core.Anchoring;
38import org.expeditee.core.Colour;
39import org.expeditee.core.Cursor;
40import org.expeditee.core.Dimension;
41import org.expeditee.core.Fill;
42import org.expeditee.core.GradientFill;
43import org.expeditee.core.Point;
44import org.expeditee.core.Stroke;
45import org.expeditee.core.bounds.AxisAlignedBoxBounds;
46import org.expeditee.core.bounds.Bounds;
47import org.expeditee.core.bounds.EllipticalBounds;
48import org.expeditee.core.bounds.PolygonBounds;
49import org.expeditee.encryption.items.surrogates.EncryptionDetail;
50import org.expeditee.encryption.items.surrogates.EncryptionDetail.Type;
51import org.expeditee.encryption.items.surrogates.Label;
52import org.expeditee.encryption.items.surrogates.Label.LabelResult;
53//import org.expeditee.encryption.items.surrogates.Surrogate;
54import org.expeditee.gio.EcosystemManager;
55import org.expeditee.gio.GraphicsManager;
56import org.expeditee.gio.gesture.StandardGestureActions;
57import org.expeditee.gui.AttributeValuePair;
58import org.expeditee.gui.DisplayController;
59import org.expeditee.gui.Frame;
60import org.expeditee.gui.FrameIO;
61import org.expeditee.gui.FrameUtils;
62import org.expeditee.gui.FreeItems;
63import org.expeditee.gui.MessageBay;
64import org.expeditee.gui.Overlay;
65import org.expeditee.gui.Vector;
66import org.expeditee.io.Conversion;
67import org.expeditee.io.DefaultFrameWriter;
68import org.expeditee.settings.UserSettings;
69import org.expeditee.settings.legacy.LegacyFeatures;
70import org.expeditee.simple.Context;
71import org.expeditee.stats.AgentStats;
72import org.expeditee.stats.Formatter;
73import org.mozilla.javascript.Scriptable;
74import org.mozilla.javascript.ScriptableObject;
75
76/**
77 * Represents everything that can be drawn on the screen (text, lines, dots,
78 * images). Each specific type is a subclass of Item.
79 *
80 * @author jdm18
81 *
82 */
83public abstract class Item implements Comparable<Item>, Runnable {
84
85 public enum HighlightMode {
86 None, // The item has no highlighting
87 Enclosed, // The item is part of the current enclosure
88 Connected, // The item is connected to the current item
89 Disconnect, // The item is a free item
90 Normal // The item is the current item
91 }
92
93 /** Which edge of the window things are anchored to. */
94 public enum AnchorEdgeType {
95 None, Left, Right, Top, Bottom
96 }
97
98 public static final float SIZE_NOT_APPLICABLE = Float.NaN;
99
100 public static final Float DEFAULT_THICKNESS = 2f;
101
102 public static final Float MINIMUM_THICKNESS = 0f;
103
104 public static final Float MINIMUM_PAINT_THICKNESS = 1f;
105
106 protected static final Stroke.JOIN DEFAULT_JOIN = Stroke.JOIN.ROUND;
107
108 protected static final Stroke.CAP DEFAULT_CAP = Stroke.CAP.BUTT;
109
110 protected static final Stroke DOT_STROKE = new Stroke(DEFAULT_THICKNESS, DEFAULT_CAP, DEFAULT_JOIN);
111
112 protected static final Stroke HIGHLIGHT_STROKE = new Stroke(MINIMUM_THICKNESS, DEFAULT_CAP, DEFAULT_JOIN);
113
114 public static final int LEFT_MARGIN = 13;
115
116 public static final int NEAR_DISTANCE = 15;
117
118 public static final int DEFAULT_HIGHLIGHT_THICKNESS = 2;
119
120 /** The default colour to draw highlighting in */
121 public static final Colour DEFAULT_HIGHLIGHT = Colour.RED;
122
123 public static final Colour DEPRESSED_HIGHLIGHT = Colour.GREEN;
124
125 public static final Colour ALTERNATE_HIGHLIGHT = Colour.BLUE;
126
127 public static final Colour LINK_COLOR = Colour.BLACK;
128
129 public static final Colour ACTION_COLOR = Colour.BLACK;
130
131 public static final Colour LINK_ACTION_COLOR = Colour.RED;
132
133 public static final Colour DEFAULT_FOREGROUND = Colour.BLACK;
134
135 public static final Colour DEFAULT_BACKGROUND = Colour.WHITE;
136
137 public static final Colour TRANSPARENT = new Colour(0, 0, 0, 0);
138
139 /** The number of pixels highlighting should extend around Items. */
140 public static final int XGRAVITY = 3;
141
142 public static final int MARGIN_RIGHT = 2;
143
144 public static final int MARGIN_LEFT = 15;
145
146 protected static final double DEFAULT_ARROWHEAD_RATIO = 0.3; // used to be 0.5
147
148 public static final double DEFAULT_ARROWHEAD_NIB_PERC = 0.75;
149
150 public static final Colour GREEN = Colour.GREEN.darker();
151
152 //public static final int UNCHANGED_CURSOR = -100;
153
154 public static final Cursor.CursorType DEFAULT_CURSOR = Cursor.CursorType.DEFAULT;
155
156 public static final Cursor.CursorType HIDDEN_CURSOR = Cursor.CursorType.CUSTOM;
157
158 public static final Cursor.CursorType TEXT_CURSOR = Cursor.CursorType.TEXT;
159
160 public static final Cursor.CursorType CROP_CURSOR = Cursor.CursorType.CROSSHAIR;
161
162 /** The default value for integer attributes */
163 public static final int DEFAULT_INTEGER = -1;
164
165 private static final int BRIGHTNESS = 185;
166
167 /** Contains all dots (including this one) that form an enclosure if this dot is part of an enclosing shape. */
168 private Collection<Item> _enclosure = null;
169
170 /** The area which this item covers (including its gravity). */
171 private Bounds _bounds = null;
172
173 /** The area this item covered before it was invalidated. */
174 private Bounds _oldBounds = null;
175
176 protected boolean _connectedToAnnotation = false;
177
178 protected boolean _save = true;
179
180 /** The angle of change for gradient colour fills (in radians). */
181 private double _gradientAngle = 0.0;
182
183 private Tooltip _tooltip = new Tooltip();
184
185 protected Anchoring _anchoring = new Anchoring();
186
187 /** The highlight mode for this item. */
188 protected HighlightMode _highlightMode = HighlightMode.None;
189
190 private Point _offset = new Point(0, 0);
191
192 protected float _x;
193 protected float _y;
194
195 private int _id;
196
197 private Item _editTarget = this;
198
199 private String _creationDate = null;
200
201 /** Whether or not this item should display a mark indicating it has a link. */
202 private boolean _linkMark = true;
203
204 /** Whether or not this item should display a mark indicating it has an action. */
205 private boolean _actionMark = true;
206
207 /** TODO: Appears unused? cts16 */
208 private boolean _highlight = true;
209
210 // private int _maxWidth = -1;
211
212 private String _owner = null;
213
214 private String _link = null;
215
216 private boolean _linkHistory = true;
217
218 private StringBuffer _tag = new StringBuffer();
219
220 private List<String> _actionCursorEnter = null;
221
222 private List<String> _actionCursorLeave = null;
223
224 private List<String> _actionEnterFrame = null;
225
226 private List<String> _actionLeaveFrame = null;
227
228 private PermissionTriple _permissionTriple = null;
229
230 private UserAppliedPermission _overlayPermission = null;
231
232 /** The primary fill colour of this item. A fill colour of null represents transparent. */
233 private Colour _fillColour = null;
234
235 /** The secondary fill colour if this item has a gradient fill. Null represents no gradient. */
236 private Colour _gradientColour = null;
237
238 /** The primary draw colour of this item. Null represents the default colour. */
239 private Colour _foregroundColour = null;
240
241 /** The colour to draw highlights on this item. */
242 protected Colour _highlightColour = DEFAULT_HIGHLIGHT;
243
244 /** The background colour for this item. */
245 private Colour _backgroundColour = null;
246
247 private Colour _colorBorder = null;
248
249 private Colour _colorTopShadow = null;
250
251 private Colour _colorBottomShadow = null;
252
253 /** The shape representing the circle drawn next to link/action items. */
254 private static EllipticalBounds _linkCircle = null;
255
256 /** The shape representing the cross drawn next to invalid links. */
257 private static PolygonBounds _linkCircleCross = null;
258
259 private Frame _parent = null;
260 private Frame _oldParent = null;
261
262 protected int _highlightThickness = 2;
263
264 protected int _vectorHighlightThickness = 1;
265
266 // arrowhead parameters
267 private float _arrowheadLength = 0;
268 private double _arrowheadRatio = DEFAULT_ARROWHEAD_RATIO;
269 private double _arrowheadNibPerc = DEFAULT_ARROWHEAD_NIB_PERC;
270
271 private PolygonBounds _arrowhead = null;
272
273 // the list of lines that this point is part of.
274 private List<Line> _lines = new ArrayList<Line>();
275
276 private int[] _linePattern = null;
277
278 private boolean _floating = false;
279
280 // list of points constrained with this point
281 private List<Constraint> _constraints = new ArrayList<Constraint>();
282
283 private List<String> _actions = null;
284
285 private String _formula = null;
286
287 private String _link_frameset = null;
288
289 private String _link_template = null;
290
291 private String _fillPattern = null;
292
293 private boolean _visible = true;
294
295 private float _thickness = -1.0F;
296
297 protected Collection<XRayable> _enclosures = new HashSet<XRayable>();
298
299 private boolean _deleted = false;
300
301 private Overlay _overlay = null;
302
303 protected AttributeValuePair _attributeValuePair = null;
304
305 private Float _autoStamp = null;
306
307 private Item _magnetizedItemLeft = null;
308
309 private Item _magnetizedItemRight = null;
310
311 private Item _magnetizedItemTop = null;
312
313 private Item _magnetizedItemBottom = null;
314
315 private String _encryptionLabel = null;
316
317 protected DotType _type = DotType.square;
318
319 protected boolean _filled = true;
320
321 private Data _data = new Data();
322
323 // Used via reflection by AttributeUtils to determine if the boolean value is different from default.
324 public static final boolean acceptsKeyboardEnterDefault = false;
325 private boolean _acceptsKeyboardEnter = acceptsKeyboardEnterDefault;
326
327 private Item surrogateFor = null;
328 private Set<Item> surrogateItems = new HashSet<Item>();
329 private static Map<String, EncryptionDetail> primaryPropertyEncryptionDefault = new HashMap<String, EncryptionDetail>();
330 private static Map<String, Boolean> surrogatePropertyInheritanceDefault = new HashMap<String, Boolean>();
331 protected Map<String, EncryptionDetail> primaryPropertyEncryption = new HashMap<String, EncryptionDetail>(primaryPropertyEncryptionDefault);
332 protected Map<String, Boolean> surrogatePropertyInheritance = new HashMap<String, Boolean>(surrogatePropertyInheritanceDefault);
333
334 {
335 EncryptionDetail unencryptedOnSave = new EncryptionDetail(EncryptionDetail.Type.UnencryptedOnSave);
336 for(Character tag: DefaultFrameWriter.getItemTags().keySet()) {
337 if (tag == 'T' || tag == 'S') {
338 surrogatePropertyInheritanceDefault.put(tag + "", false);
339 } else {
340 surrogatePropertyInheritanceDefault.put(tag + "", true);
341 }
342 primaryPropertyEncryptionDefault.put(tag + "", unencryptedOnSave);
343 }
344
345 for(String tag: DefaultFrameWriter.getItemTagsExt().keySet()) {
346 surrogatePropertyInheritanceDefault.put(tag, true);
347 primaryPropertyEncryptionDefault.put(tag, unencryptedOnSave);
348 }
349 }
350
351 /** Just calls source.duplicateOnto(dest). */
352 public static void DuplicateItem(Item source, Item dest)
353 {
354 if (source == null) return;
355
356 source.duplicateOnto(dest);
357 }
358
359 /** Sets the properties of dest so that they match this item's properties. */
360 public void duplicateOnto(Item dest)
361 {
362 if (dest == null) return;
363
364 dest.setX(this.getX());
365 dest.setY(this.getY());
366
367 dest.setActions(this.getAction());
368 dest.setActionCursorEnter(this.getActionCursorEnter());
369 dest.setActionCursorLeave(this.getActionCursorLeave());
370 dest.setActionEnterFrame(this.getActionEnterFrame());
371 dest.setActionLeaveFrame(this.getActionLeaveFrame());
372 dest.setActionMark(this.getActionMark());
373
374 dest.setBackgroundColor(this.getBackgroundColor());
375 dest.setBottomShadowColor(this.getBottomShadowColor());
376 dest.setColor(this.getColor());
377 dest.setBorderColor(this.getBorderColor());
378
379 dest.setTooltips(this.getTooltip());
380 dest.setData(this.getData());
381 dest.setTag(this.getTag());
382 dest.setFillColor(this.getFillColor());
383 dest.setGradientColor(this.getGradientColor());
384 dest.setGradientAngle(this.getGradientAngle());
385 dest.setFillPattern(this.getFillPattern());
386
387 dest.setHighlight(this.getHighlight());
388 dest.setLink(this.getLink());
389 dest.setLinkFrameset(this.getLinkFrameset());
390 dest.setLinkMark(this.getLinkMark());
391 dest.setLinkTemplate(this.getLinkTemplate());
392
393 // dest.setWidth(this.getWidth());
394
395 dest.setOffset(this.getOffset());
396 // dest.setOwner(this.getOwner());
397 dest.setThickness(this.getThickness());
398 dest.setSize(this.getSize());
399 dest.setTopShadowColor(this.getTopShadowColor());
400 dest.setLinePattern(this.getLinePattern());
401
402 dest.setFloating(this.isFloating());
403 dest.setArrow(this.getArrowheadLength(), this.getArrowheadRatio(), this.getArrowheadNibPerc());
404 dest.setDotType(this.getDotType());
405 dest.setFilled(this.getFilled());
406 /*
407 * Calling the methods will move the item... This messes things up when
408 * the user uses backspace to delete a text line end
409 */
410 // dest._anchorLeft = this._anchorLeft;
411 // dest._anchorRight = this._anchorRight;
412 // dest._anchorTop = this._anchorTop;
413 // dest._anchorBottom = this._anchorBottom;
414 dest.setFormula(this.getFormula());
415 dest._overlay = this._overlay;
416 dest._highlightMode = this._highlightMode;// SelectedMode.None;
417 // dest._highlightColor = this._highlightColor;
418 // dest.setHighlight(this.getHighlight());
419
420 dest._visible = this._visible;
421
422 Frame parent = DisplayController.getCurrentFrame();
423 if (parent == null) parent = this.getParentOrCurrentFrame();
424 dest.setParent(parent);
425
426 /*
427 * TODO MIKE says maybe we could tighten up and only give items ID's if
428 * their current ID is negative?
429 */
430 if (parent != null) {
431 dest.setID(parent.getNextItemID());
432 }
433
434 String currentUser = UserSettings.UserName.get();
435// if (parent != null && !currentUser.equals(parent.getOwner())) {
436// //dest.setOwner(currentUser);
437// } else {
438// System.err.println("I have duplicated a item and made it owned by "
439// + "current user, whereas the old code would not have "
440// + "changed ownership at this time.");
441// System.err.println("Item: " + dest + ", Class: " + dest.getClass());
442// System.err.println("Current owner: " + dest.getOwner());
443// System.err.println("Current user: " + currentUser);
444// }
445 dest.setOwner(currentUser);
446 }
447
448 public void setDotType(DotType type) {
449 invalidateAll();
450 _type = type;
451 invalidateAll();
452 if (isSurrogate()) {
453 surrogatePropertyInheritance.put(DefaultFrameWriter.DOT_TYPE_STR, false);
454 Item primary = getPrimary();
455 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.DOT_TYPE_STR)) {
456 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
457 primary.primaryPropertyEncryption.put(DefaultFrameWriter.DOT_TYPE_STR, inheritanceCheckOnSave);
458 }
459 }
460 }
461
462 public DotType getDotType() {
463 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.DOT_TYPE_STR)) {
464 return this.getPrimary().getDotType();
465 } else {
466 return _type;
467 }
468 }
469
470
471 public void setFilled(boolean filled) {
472 invalidateAll();
473 _filled = filled;
474 invalidateAll();
475
476 if (isSurrogate()) {
477 surrogatePropertyInheritance.put(DefaultFrameWriter.FILLED_STR, false);
478 Item primary = getPrimary();
479 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.DOT_TYPE_STR)) {
480 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
481 primary.primaryPropertyEncryption.put(DefaultFrameWriter.FILLED_STR, inheritanceCheckOnSave);
482 }
483 }
484 }
485
486 public boolean getFilled() {
487 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.FILLED_STR)) {
488 return this.getPrimary().getFilled();
489 } else {
490 return _filled;
491 }
492 }
493
494 /**
495 * Sets the angle of colour change for gradient colour fills.
496 *
497 * @param gradientAngle The new angle of colour change.
498 */
499 public void setGradientAngle(double gradientAngle) {
500 _gradientAngle = gradientAngle;
501
502 for (Line line : _lines) {
503 Item other = line.getOppositeEnd(this);
504 if (other.getGradientAngle() != gradientAngle) other.setGradientAngle(gradientAngle);
505 }
506
507 invalidateCommonTrait(ItemAppearence.GradientColor);
508 invalidateFill();
509
510 if (isSurrogate()) {
511 surrogatePropertyInheritance.put(DefaultFrameWriter.GRADIENT_ANGLE_STR, false);
512 Item primary = getPrimary();
513 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.DOT_TYPE_STR)) {
514 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
515 primary.primaryPropertyEncryption.put(DefaultFrameWriter.GRADIENT_ANGLE_STR, inheritanceCheckOnSave);
516 }
517 }
518 }
519
520 /**
521 * Gets the angle of colour change for gradient fills.
522 *
523 * @return The angle of colour change.
524 */
525 public double getGradientAngle() {
526 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.GRADIENT_ANGLE_STR)) {
527 return this.getPrimary().getGradientAngle();
528 } else {
529 return _gradientAngle;
530 }
531 }
532
533 /**
534 * Gets the gravity for this item. Gravity is the distance from the item at which mouse interaction
535 * applies to the item (like a small buffer zone so you don't need to click exactly on the item).
536 *
537 * @return The gravity distance for this item.
538 */
539 public int getGravity()
540 {
541 if (isVectorItem()) return 2;
542
543 return UserSettings.Gravity.get();
544 }
545
546 /**
547 * Whether or not line highlights should be shown.
548 * TODO: Not really an item method is it? Goes straight to user settings. Refactor. cts16
549 *
550 * @return <code>true</code> if line highlighting should be shown, <code>false</code> otherwise.
551 */
552 public static boolean shouldShowLineHighlight()
553 {
554 return UserSettings.LineHighlight.get();
555 }
556
557 /**
558 * Sets the highlight mode for this item.
559 *
560 * @param mode The new highlight mode.
561 */
562 public void setHighlightMode(HighlightMode mode)
563 {
564 if (hasPermission(UserAppliedPermission.followLinks) || getEditTarget().hasPermission(UserAppliedPermission.followLinks)) {
565 if (_highlightMode != mode) {
566 _highlightMode = mode;
567 this.invalidateCommonTrait(ItemAppearence.HighlightModeChanged);
568 }
569 }
570 }
571
572 public void setOverlayPermission(UserAppliedPermission overlayPermission)
573 {
574 _overlayPermission = overlayPermission;
575 }
576
577 public void setPermission(PermissionTriple permissionPair) {
578 List<String> groupMembers = getParent() != null ? getParent().getGroupMembers() : new ArrayList<String>();
579 _permissionTriple = permissionPair;
580 if (_permissionTriple.getPermission(_owner, groupMembers) == UserAppliedPermission.denied) {
581 this.getParent().moveItemToBodyHiddenDueToPermission(this);
582 }
583
584 if (isSurrogate()) {
585 surrogatePropertyInheritance.put(DefaultFrameWriter.PERMISSION_STR, false);
586 Item primary = getPrimary();
587 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.DOT_TYPE_STR)) {
588 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
589 primary.primaryPropertyEncryption.put(DefaultFrameWriter.PERMISSION_STR, inheritanceCheckOnSave);
590 }
591 }
592 }
593
594 public PermissionTriple getPermission() {
595 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.PERMISSION_STR)) {
596 return this.getPrimary().getPermission();
597 } else {
598 return _permissionTriple;
599 }
600 }
601
602 public UserAppliedPermission getUserAppliedPermission() {
603 List<String> groupMembers = getParent() != null ? getParent().getGroupMembers() : new ArrayList<String>();
604 String owner = _owner != null ? _owner : _parent != null ? _parent.getOwner() : null;
605 if(_permissionTriple != null) return _permissionTriple.getPermission(owner, groupMembers);
606 if(_overlayPermission != null) return _overlayPermission;
607 if(_parent != null) return _parent.getUserAppliedPermission();
608 return UserAppliedPermission.full;
609 }
610
611 public boolean hasPermission(UserAppliedPermission permission) {
612 return getUserAppliedPermission().ordinal() >= permission.ordinal();
613 }
614
615 protected Item() {
616 _creationDate = Formatter.getLongDateTime();
617 }
618
619 /**
620 * Adds an action to this Item.
621 *
622 * @param action
623 * The name of the action to add to this Item.
624 */
625 public void addAction(String action)
626 {
627 if (action == null || action.equals("")) return;
628
629 if (_actions == null) {
630 _actions = new LinkedList<String>();
631 }
632
633 _actions.add(action);
634
635 if (_actions.size() == 1) {
636 invalidateBounds();
637 invalidateCommonTrait(ItemAppearence.LinkChanged);
638 }
639 }
640
641 public void addAllConnected(Collection<Item> connected)
642 {
643 if (!connected.contains(this)) connected.add(this);
644
645 for (Item item : getConnected()) {
646 if (!connected.contains(item)) {
647 item.addAllConnected(connected);
648 }
649 }
650 }
651
652 /**
653 * Adds the given Constraint to this Dot
654 *
655 * @param c
656 * The Constraint to set this Dot as a member of.
657 */
658 public void addConstraint(Constraint c)
659 {
660 // do not add duplicate constraint
661 if (_constraints.contains(c))
662 return;
663
664 _constraints.add(c);
665 }
666
667 /**
668 * Adds a given line to the list of lines that this Point is an end for.
669 *
670 * @param line
671 * The Line that this Point is an end of.
672 */
673 public void addLine(Line line)
674 {
675 if (_lines.contains(line)) {
676 return;
677 }
678
679 _lines.add(line);
680 }
681
682 /**
683 * Items are sorted by their Y coordinate on the screen.
684 *
685 * @param i
686 * The Item to compare this Item to
687 * @return a negative integer, zero, or a positive integer as this object is
688 * less than, equal to, or greater than the specified object.
689 */
690 public int compareTo(Item i)
691 {
692 return getY() - i.getY();
693 }
694
695 /**
696 * Every Item has an area around it defined by a Shape (typically a
697 * rectangle), this method returns true if the given x,y pair lies within
698 * the area and false otherwise.
699 *
700 * @param p
701 * The coordinate to check
702 * @return True if the Shape around this Item contains the given x,y pair,
703 * false otherwise.
704 */
705 public boolean contains(Point p)
706 {
707 return getBounds().contains(p);
708 }
709
710 /**
711 * Returns a deep copy of this Item, note: it is up to the receiver to
712 * change the Item ID etc as necessary.
713 *
714 * @return A deep copy of this Item.
715 */
716 public abstract Item copy();
717
718 public void delete()
719 {
720 _deleted = true;
721 }
722
723 @Override
724 public boolean equals(Object o)
725 {
726 if (o == null)
727 return false;
728 if (getClass().equals(o.getClass())) {
729 Item i = (Item) o;
730 return i.getID() == getID()
731 && ((i.getParent() == _parent) || (i.getParent() != null && i
732 .getParent().equals(_parent)));
733 } else
734 return false;
735 }
736
737 /**
738 * Returns a list of any action code that is currently associated with this
739 * Item
740 *
741 * @return A List of action code associated with this Item, or null if none
742 * has been assigned.
743 */
744 public List<String> getAction() {
745 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.ACTION_STR)) {
746 return this.getPrimary().getAction();
747 } else {
748 return _actions;
749 }
750 }
751
752 public List<String> getData() {
753 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.DATA_STR)) {
754 return this.getPrimary().getData();
755 } else {
756 return _data.getData();
757 }
758 }
759
760 public List<String> getActionCursorEnter() {
761 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.ACTION_CURSOR_ENTER_STR)) {
762 return this.getPrimary().getActionCursorEnter();
763 } else {
764 return _actionCursorEnter;
765 }
766 }
767
768 public List<String> getActionCursorLeave() {
769 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.ACTION_CURSOR_LEAVE_STR)) {
770 return this.getPrimary().getActionCursorLeave();
771 } else {
772 return _actionCursorLeave;
773 }
774 }
775
776 public List<String> getActionEnterFrame() {
777 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.ACTION_ENTER_FRAME_STR)) {
778 return this.getPrimary().getActionEnterFrame();
779 } else {
780 return _actionEnterFrame;
781 }
782 }
783
784 public List<String> getActionLeaveFrame() {
785 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.ACTION_LEAVE_FRAME_STR)) {
786 return this.getPrimary().getActionLeaveFrame();
787 } else {
788 return _actionLeaveFrame;
789 }
790 }
791
792 public boolean getActionMark() {
793 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.ACTION_MARK_STR)) {
794 return this.getPrimary().getActionMark();
795 } else {
796 return _actionMark;
797 }
798 }
799
800 /**
801 * Gets all the items connected to this item. Uses a recursive approach to
802 * search connected points.
803 *
804 * @return
805 */
806 public Collection<Item> getAllConnected()
807 {
808 Collection<Item> list = new LinkedHashSet<Item>();
809 addAllConnected(list);
810 return list;
811 }
812
813/* public Area getArea() {
814 return new Area(getPolygon());
815 }*/
816
817 public String getArrow() {
818 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.ARROW_STR)) {
819 return this.getPrimary().getArrow();
820 } else {
821 if (!hasVisibleArrow())
822 return null;
823
824 String ratio = "" + getArrowheadRatio();
825 if (ratio.length() - ratio.indexOf(".") > 2)
826 ratio = ratio.substring(0, ratio.indexOf(".") + 3);
827
828 return getArrowheadLength() + " " + ratio + " " + getArrowheadNibPerc();
829 }
830 }
831
832 public PolygonBounds getArrowhead()
833 {
834 return _arrowhead;
835 }
836
837 public float getArrowheadLength()
838 {
839 return _arrowheadLength;
840 }
841
842 public double getArrowheadRatio()
843 {
844 return _arrowheadRatio;
845 }
846
847 public double getArrowheadNibPerc()
848 {
849 return _arrowheadNibPerc;
850 }
851
852 public Colour getBackgroundColor() {
853 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.BACKGROUND_COLOR_STR)) {
854 return this.getPrimary().getBackgroundColor();
855 } else {
856 return _backgroundColour;
857 }
858 }
859
860 public Colour getBorderColor() {
861 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.BORDER_COLOR_STR)) {
862 return this.getPrimary().getBorderColor();
863 } else {
864 return _colorBorder;
865 }
866 }
867
868 /**
869 * Returns the Color being used to shade the bottom half of this Item's
870 * border. This can be NULL if no Color is being used
871 *
872 * @return The Color displayed on the bottom\right half of this Item's
873 * border.
874 */
875 public Colour getBottomShadowColor()
876 {
877 return _colorBottomShadow;
878 }
879
880 /**
881 * Returns the height (in pixels) of this Item's surrounding area.
882 *
883 * @return The height (in pixels) of this Item's surrounding area as
884 * returned by getArea().
885 */
886 public int getBoundsHeight()
887 {
888 return AxisAlignedBoxBounds.getEnclosing(getBounds()).getHeight();
889 }
890
891 /**
892 * Returns the width (in pixels) of this Item's surrounding area.
893 *
894 * @return The width (in pixels) of this Item's surrounding area as returned
895 * by getArea().
896 */
897 public int getBoundsWidth()
898 {
899 return AxisAlignedBoxBounds.getEnclosing(getBounds()).getWidth();
900 }
901
902 // TODO: Remove magic constants. cts16
903 public EllipticalBounds getLinkBounds()
904 {
905 if (_linkCircle == null) {
906 _linkCircle = new EllipticalBounds(new Point(6, 3), 7);
907 }
908
909 return _linkCircle;
910 }
911
912 protected PolygonBounds getCircleCross()
913 {
914
915 if (_linkCircleCross == null) {
916 _linkCircleCross = new PolygonBounds();
917
918 EllipticalBounds poly = getLinkBounds();
919 int x1 = poly.getMinX();
920 int x2 = poly.getMaxX();
921 int y1 = poly.getMinY();
922 int y2 = poly.getMaxY();
923 int midX = (x2 + x1) / 2;
924 int midY = (y2 + y1) / 2;
925
926 _linkCircleCross.addPoint(new Point(x1, y1));
927 _linkCircleCross.addPoint(new Point(x2, y2));
928 _linkCircleCross.addPoint(new Point(midX, midY));
929 _linkCircleCross.addPoint(new Point(x1, y2));
930 _linkCircleCross.addPoint(new Point(x2, y1));
931 _linkCircleCross.addPoint(new Point(midX, midY));
932 }
933
934 return _linkCircleCross;
935 }
936
937 public Colour getColor() {
938 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.COLOR_STR)) {
939 return this.getPrimary().getColor();
940 } else {
941 return _foregroundColour;
942 }
943 }
944
945 public Collection<Item> getConnected()
946 {
947 List<Item> conn = new LinkedList<Item>();
948 conn.add(this);
949 conn.addAll(getEnclosures());
950 conn.addAll(getLines());
951 return conn;
952 }
953
954 public String getConstraintIDs() {
955 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.CONSTRAINT_IDS_STR)) {
956 return this.getPrimary().getConstraintIDs();
957 } else {
958 if (_constraints == null || _constraints.size() == 0)
959 return null;
960
961 String cons = "";
962
963 for (Constraint c : _constraints)
964 cons += c.getID() + " ";
965
966 return cons.trim();
967 }
968 }
969
970 /*
971 * public void setLinkValid(boolean val) { _isValidLink = val; }
972 */
973
974 /**
975 * Returns a List of any Constraints that this Dot is a memeber of.
976 *
977 * @return a List of Constraints that this Dot is a member of.
978 */
979 public List<Constraint> getConstraints()
980 {
981 return _constraints;
982 }
983
984 public String getTag()
985 {
986 if (_tag != null && _tag.length() > 0)
987 return _tag.toString();
988 return null;
989 }
990
991 public String getDateCreated() {
992 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.DATE_CREATED_STR)) {
993 return this.getPrimary().getDateCreated();
994 } else {
995 return _creationDate;
996 }
997 }
998
999 public Colour getFillColor() {
1000 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.FILL_COLOR_STR)) {
1001 return this.getPrimary().getFillColor();
1002 } else {
1003 return _fillColour;
1004 }
1005 }
1006
1007 public String getFillPattern() {
1008 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.FILL_PATTERN_STR)) {
1009 return this.getPrimary().getFillPattern();
1010 } else {
1011 return _fillPattern;
1012 }
1013 }
1014
1015 public String getFirstAction()
1016 {
1017 if (_actions == null || _actions.size() == 0)
1018 return null;
1019 return _actions.get(0);
1020 }
1021
1022 /**
1023 * Gets the value of <code>_highlight</code> for this item.
1024 * TODO: Appears unused? cts16.
1025 *
1026 * @return The value of <code>_highlight</code>.
1027 */
1028 public boolean getHighlight() {
1029 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.HIGHLIGHT_STR)) {
1030 return this.getPrimary().getHighlight();
1031 } else {
1032 return _highlight;
1033 }
1034 }
1035
1036 public Colour getHighlightColor()
1037 {
1038 if (_highlightColour.equals(getPaintColor())) return getAlternateHighlightColor();
1039
1040 return getDefaultHighlightColor();
1041 }
1042
1043 /**
1044 * Returns the ID of this Item, which must be unique for the Frame.
1045 *
1046 * @return The ID of this Item.
1047 *
1048 * TODO: What does it mean to have a negative ID# (as used in TDFC)? cts16
1049 */
1050 public int getID()
1051 {
1052 return _id;
1053 }
1054
1055 /**
1056 * Returns the list of IDs of the Lines that this Dot is an end of.
1057 *
1058 * @return The list of Line IDs that this point is part of.
1059 */
1060 public String getLineIDs() {
1061 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.LINE_IDS_STR)) {
1062 return this.getPrimary().getLineIDs();
1063 } else {
1064 String lineID = null;
1065
1066 if (_lines.size() > 0) {
1067 lineID = "" + _lines.get(0).getID();
1068
1069 for (int i = 1; i < _lines.size(); i++)
1070 lineID += " " + _lines.get(i).getID();
1071 }
1072
1073 return lineID;
1074 }
1075 }
1076
1077 public int[] getLinePattern() {
1078 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.LINE_PATTERN_STR)) {
1079 return this.getPrimary().getLinePattern();
1080 } else {
1081 return _linePattern;
1082 }
1083 }
1084
1085 /**
1086 * Returns a list of Lines where this Dot is an end.
1087 *
1088 * @return A list of the Lines that this Dot is an end for or null if no
1089 * Lines have been added.
1090 */
1091 public List<Line> getLines()
1092 {
1093 return _lines;
1094 }
1095
1096 /**
1097 * Returns the name of a Frame that this Item links to, or null if this Item
1098 * has no link.
1099 *
1100 * @return The name of a Frame that this Item links to (if any) or null if
1101 * this Item does not link to anything.
1102 */
1103 public String getLink() {
1104 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.LINK_STR)) {
1105 return this.getPrimary().getLink();
1106 } else {
1107 return _link;
1108 }
1109 }
1110
1111 public String getFormula() {
1112 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.FORMULA_STR)) {
1113 return this.getPrimary().getFormula();
1114 } else {
1115 return _formula;
1116 }
1117 }
1118
1119 public boolean hasFormula()
1120 {
1121 return _formula != null;
1122 }
1123
1124 public boolean hasAttributeValuePair()
1125 {
1126 return _attributeValuePair != null && _attributeValuePair.hasPair();
1127 }
1128
1129 public void setFormula(String formula) {
1130 _formula = formula;
1131
1132 if (isSurrogate()) {
1133 surrogatePropertyInheritance.put(DefaultFrameWriter.FORMULA_STR, false);
1134 Item primary = getPrimary();
1135 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.FORMULA_STR)) {
1136 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
1137 primary.primaryPropertyEncryption.put(DefaultFrameWriter.FORMULA_STR, inheritanceCheckOnSave);
1138 }
1139 }
1140 }
1141
1142 public boolean calculate(String formula)
1143 {
1144 setFormula(formula);
1145 return true;
1146 }
1147
1148 public String getLinkFrameset() {
1149 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.LINK_FRAMESET_STR)) {
1150 return this.getPrimary().getLinkFrameset();
1151 } else {
1152 return _link_frameset;
1153 }
1154 }
1155
1156 public boolean getLinkMark() {
1157 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.LINK_MARK_STR)) {
1158 return this.getPrimary().getLinkMark();
1159 } else {
1160 return _linkMark;
1161 }
1162 }
1163
1164 public String getLinkTemplate() {
1165 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.LINK_TEMPLATE_STR)) {
1166 return this.getPrimary().getLinkTemplate();
1167 } else {
1168 return _link_template;
1169 }
1170 }
1171
1172 public Point getOffset()
1173 {
1174 return _offset;
1175 }
1176
1177 public String getOwner() {
1178 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.OWNER_STR)) {
1179 return this.getPrimary().getOwner();
1180 } else {
1181 return _owner;
1182 }
1183 }
1184
1185 public Colour getPaintBackgroundColor()
1186 {
1187 Colour colorBackground = getBackgroundColor();
1188 if (colorBackground == null) {
1189 if (getParent() != null && getParent().getBackgroundColor() != null)
1190 return getParent().getBackgroundColor();
1191
1192 return DEFAULT_BACKGROUND;
1193 }
1194
1195 return colorBackground;
1196 }
1197
1198 /**
1199 * Returns the foreground Color of this Item.
1200 *
1201 * @return The Color of this item (foreground)
1202 */
1203 public final Colour getPaintColor()
1204 {
1205 // If color is null then get the paint foregroundColor for the frame the
1206 // item is on which is a color adjusted to suit the background
1207 Colour color = getColor();
1208
1209 if (color == null) {
1210 if (getParent() != null)
1211 return getParent().getPaintForegroundColor();
1212
1213 Frame current = DisplayController.getCurrentFrame();
1214 if (current == null) {
1215 return DEFAULT_FOREGROUND;
1216 }
1217 return current.getPaintForegroundColor();
1218 }
1219
1220 return color;
1221 }
1222
1223 public final Colour getPaintBorderColor()
1224 {
1225 // If color is null then get the paint foregroundColor for the frame the
1226 // item is on which is a color adjusted to suit the background
1227 Colour color = getBorderColor();
1228
1229 if (color == null) {
1230 if (getParent() != null)
1231 return getParent().getPaintForegroundColor();
1232
1233 Frame current = DisplayController.getCurrentFrame();
1234 if (current == null) {
1235 return DEFAULT_FOREGROUND;
1236 }
1237 return current.getPaintForegroundColor();
1238 }
1239
1240 return color;
1241 }
1242
1243 protected Colour getPaintHighlightColor()
1244 {
1245 Colour highlightColor = getDefaultHighlightColor();
1246 if (hasVisibleBorder()) {
1247 if (getPaintBorderColor().equals(highlightColor)) {
1248 highlightColor = getDefaultHighlightColor();
1249 }
1250 } else if (getPaintBackgroundColor().equals(highlightColor)) {
1251 highlightColor = getDefaultHighlightColor();
1252 }
1253
1254 if (getParent() != null && getParent().getPaintBackgroundColor().equals(highlightColor)) {
1255 highlightColor = getParent().getPaintForegroundColor();
1256 }
1257
1258 if (hasVisibleBorder()) {
1259 if (highlightColor.equals(getBorderColor()) && getThickness() == getHighlightThickness()) {
1260 highlightColor = highlightColor.clone();
1261 highlightColor.setAlpha(Colour.FromComponent255(150));
1262 }
1263 }
1264
1265 return highlightColor;
1266 }
1267
1268 protected Colour getDefaultHighlightColor()
1269 {
1270 if (isVectorItem() && !this.contains(EcosystemManager.getInputManager().getCursorPosition())) {
1271 return Colour.FromRGB255(255, BRIGHTNESS, BRIGHTNESS);
1272 }
1273 return _highlightColour;
1274 }
1275
1276 protected Colour getAlternateHighlightColor()
1277 {
1278 if (isVectorItem() && !this.contains(EcosystemManager.getInputManager().getCursorPosition())) {
1279 return Colour.FromRGB255(BRIGHTNESS, BRIGHTNESS, 255);
1280 }
1281 return ALTERNATE_HIGHLIGHT;
1282 }
1283
1284 protected int getHighlightThickness()
1285 {
1286 if (isVectorItem()) return _vectorHighlightThickness;
1287
1288 return _highlightThickness;
1289 }
1290
1291 public final Frame getParent()
1292 {
1293 return _parent;
1294 }
1295
1296 /** Gets the position of this item. */
1297 public final Point getPosition() {
1298 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.POSITION_STR)) {
1299 return this.getPrimary().getPosition();
1300 } else {
1301 return new Point(getX(), getY());
1302 }
1303 }
1304
1305 /**
1306 * Returns the size of this Item. For Text this is the Font size, for Lines
1307 * and Dots this is the thickness.
1308 *
1309 * @return The size of this Item.
1310 */
1311 public float getSize()
1312 {
1313 return SIZE_NOT_APPLICABLE;
1314 }
1315
1316 /**
1317 * Returns the Color being used to shade the top half of this Item's border.
1318 * This can be NULL if no Color is being used
1319 *
1320 * @return The Color displayed on the top\left half of this Item's border.
1321 */
1322 public Colour getTopShadowColor()
1323 {
1324 return _colorTopShadow;
1325 }
1326
1327 public String getTypeAndID() {
1328 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.TYPE_AND_ID_STR)) {
1329 return this.getPrimary().getTypeAndID();
1330 } else {
1331 return "T " + getID();
1332 }
1333 }
1334
1335 public Integer getWidthToSave() {
1336 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.WIDTH_TO_SAVE_STR)) {
1337 return this.getPrimary().getWidthToSave();
1338 } else {
1339 return getWidth();
1340 }
1341 }
1342
1343 public Integer getMinWidthToSave() {
1344 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.MIN_WIDTH_TO_SAVE_STR)) {
1345 return this.getPrimary().getMinWidthToSave();
1346 } else {
1347 return getMinWidth();
1348 }
1349 }
1350
1351 public Integer getWidth()
1352 {
1353 return null;
1354 }
1355
1356 public Integer getMinWidth() {
1357 return null;
1358 }
1359
1360 public int getHeight()
1361 {
1362 return 0;
1363 }
1364
1365 /**
1366 * Returns the X coordinate of this Item on the screen
1367 *
1368 * @return The X coordinate of this Item on the screen
1369 */
1370 public int getX() {
1371 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.POSITION_STR)) {
1372 return this.getPrimary().getX();
1373 } else {
1374 return Math.round(_x);
1375 }
1376 }
1377
1378 /**
1379 * Returns the Y coordinate of this Item on the screen
1380 *
1381 * @return The Y coordinate of this Item on the screen
1382 */
1383 public int getY() {
1384 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.POSITION_STR)) {
1385 return this.getPrimary().getY();
1386 } else {
1387 return Math.round(_y);
1388 }
1389 }
1390
1391 public boolean hasVisibleArrow()
1392 {
1393 return isLineEnd() && getArrowheadRatio() != 0 && getArrowheadLength() != 0;
1394 }
1395
1396 /**
1397 * Checks if the given Shape intersects with the Shape around this Item.
1398 *
1399 * @param s
1400 * The Shape to check.
1401 * @return True if the two Shapes overlap, False otherwise.
1402 */
1403 public boolean intersects(PolygonBounds otherBounds)
1404 {
1405 if (otherBounds == null) return false;
1406
1407 Bounds thisBounds = getBounds();
1408
1409 // Need to do this check for circles
1410 if (otherBounds.equals(thisBounds)) return true;
1411
1412 boolean intersects = otherBounds.intersects(thisBounds);
1413
1414 /*if (intersects) {
1415 System.err.println("Found intersection between this item (" + this + ") with bounds: " + thisBounds + "...and...");
1416 System.err.println("item with bounds: " + otherBounds.toString());
1417 }*/
1418 return intersects;
1419
1420 // Need to check the second equality so that we dont pick up circles
1421 // inside other circles
1422 //return !a.isEmpty() && !a.equals(new Area(p));
1423 }
1424
1425 /**
1426 * Note: Pictures always return False, as they should be drawn even when no
1427 * other annotation Items are.
1428 *
1429 * @return True if this Item is an annotation, False otherwise.
1430 */
1431 public boolean isAnnotation()
1432 {
1433 return false;
1434 }
1435
1436 public boolean isFloating()
1437 {
1438 return _floating;
1439 }
1440
1441 public boolean isFrameName()
1442 {
1443 if (this.getParent() == null || this.getParent().getNameItem() != this)
1444 return false;
1445 return true;
1446 }
1447
1448 public boolean isFrameTitle()
1449 {
1450 if (this.getParent() == null || this.getParent().getTitleItem() != this)
1451 return false;
1452 return true;
1453 }
1454
1455 /**
1456 * Returns True if this Item is currently highlighted.
1457 *
1458 * @return True if this Item is currently highlighted on the screen, False
1459 * otherwise.
1460 */
1461 public boolean isHighlighted()
1462 {
1463 if (isFloating())
1464 return false;
1465 return _highlightMode != HighlightMode.None;
1466 }
1467
1468 /**
1469 * Tests if the item link is a valid framename, that is, the String must
1470 * begin with a character, end with a number with 0 or more letters and
1471 * numbers in between. If there is a dot in the framename all the chars
1472 * after it must be digits.
1473 *
1474 * @return True if the given framename is proper, false otherwise.
1475 */
1476 public boolean isLinkValid()
1477 {
1478 if (FrameIO.isPositiveInteger(getLink()))
1479 return true;
1480
1481 if (FrameIO.isValidFrameName(getLink()))
1482 return true;
1483 return false;
1484 }
1485
1486 /**
1487 * Checks if the given point is 'near' to the item. Here 'near' means within a certain distance
1488 * of the axis-aligned box bounding the item's polygon.
1489 *
1490 * @param x
1491 * The x-coordinate of the point to check.
1492 *
1493 * @param y
1494 * The y-coordinate of the point to check.
1495 *
1496 * @return
1497 * True if the given point is 'near' to the item, false otherwise.
1498 */
1499 public boolean isNear(int x, int y)
1500 {
1501 AxisAlignedBoxBounds box = ItemUtils.expandRectangle(getBoundingBox(), NEAR_DISTANCE * 2);
1502
1503 return box.contains(x, y);
1504 }
1505
1506 public boolean isOldTag()
1507 {
1508 if (this instanceof Text)
1509 if (((Text) this).getTextList().get(0).toLowerCase().equals("@old"))
1510 return true;
1511 return false;
1512 }
1513
1514 /**
1515 * Merges this Item with the given Item. The merger Item should be left
1516 * unchanged after this method. The merger may or may not be the same class
1517 * as this Item, exact behaviour depends on the subclass, No-op is allowed.
1518 *
1519 * @param merger
1520 * The Item to merge with
1521 * @return any Item that should remain on the cursor
1522 */
1523 public abstract Item merge(Item merger, int mouseX, int mouseY);
1524
1525 /**
1526 * Displays this item directly on the screen. Note: All Items are
1527 * responsible for their own drawing, buffering, etc.
1528 *
1529 * @param g
1530 * The Graphics to draw this Item on.
1531 */
1532 public abstract void paint();
1533
1534 public void setTooltips(final List<String> tooltips)
1535 {
1536 if (tooltips == null || tooltips.size() == 0) {
1537 _tooltip = new Tooltip();
1538 } else {
1539 for (final String content: tooltips) _tooltip.addTooltip(content, this);
1540 }
1541 }
1542
1543 public void setTooltip(final String tooltip) {
1544 if(tooltip != null && tooltip.trim().length() > 0) {
1545 _tooltip.addTooltip(tooltip, this);
1546 }
1547
1548 if (isSurrogate()) {
1549 surrogatePropertyInheritance.put(DefaultFrameWriter.TOOLTIP_STR, false);
1550 Item primary = getPrimary();
1551 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.TOOLTIP_STR)) {
1552 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
1553 primary.primaryPropertyEncryption.put(DefaultFrameWriter.TOOLTIP_STR, inheritanceCheckOnSave);
1554 }
1555 }
1556 }
1557
1558 public List<String> getTooltip() {
1559 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.TOOLTIP_STR)) {
1560 return this.getPrimary().getTooltip();
1561 } else {
1562 return _tooltip.asStringList();
1563 }
1564 }
1565
1566 public Collection<Text> getTooltipItems()
1567 {
1568 return _tooltip.getTooltips();
1569 }
1570
1571 public void clearTooltips()
1572 {
1573 final Frame frame = this.getParent();
1574 if(_tooltip != null) {
1575 for(final Text tooltip: _tooltip.getTooltips()) frame.removeItem(tooltip);
1576 }
1577 }
1578
1579 public void paintTooltip()
1580 {
1581 final Bounds bounds = AxisAlignedBoxBounds.getEnclosing(this.getBoundingBox());
1582 Dimension frameSize = DisplayController.getFramePaintAreaSize();
1583
1584 int x = bounds.getMaxX();
1585
1586 // If the tooltip goes off the right side of the window, move it left so it's completely on
1587 if(x + _tooltip.getWidth() > frameSize.getWidth()) {
1588 x = frameSize.getWidth() - _tooltip.getWidth();
1589 }
1590
1591 int y = bounds.getMaxY();
1592
1593 if(y + _tooltip.getCollectiveHeight() > frameSize.getHeight()) {
1594 y = (bounds.getMinY() + bounds.getMaxY()) / 2 - _tooltip.getCollectiveHeight();
1595 }
1596
1597 for(final Text tooltip : _tooltip.getTooltips()) {
1598 this.getParent().addItem(tooltip);
1599 tooltip.setPosition(x, y);
1600 tooltip.paint();
1601 y += tooltip.getHeight();
1602 }
1603 }
1604
1605 public void paintFill() {
1606 Colour fillColor = getFillColor();
1607 if (fillColor != null && getEnclosingDots() != null) {
1608 Fill fill = getFill();
1609 EcosystemManager.getGraphicsManager().drawPolygon(getEnclosedShape(), null, null, 0.0f, fill, null, null);
1610 }
1611 }
1612
1613 protected Fill getFill() {
1614 Fill fill;
1615 Colour fillColour = getFillColor();
1616 if (isFloating()) {
1617 // TODO experiment with adding alpha when picking up filled
1618 // items... Slows things down quite alot!!
1619 // TODO: Does nothing as it stands... cts16
1620 fillColour = new Colour(fillColour.getRed(), fillColour.getGreen(),
1621 fillColour.getBlue(), fillColour.getAlpha());
1622 }
1623 Colour gradientColor = getGradientColor();
1624 PolygonBounds poly = getEnclosedShape();
1625 if (gradientColor != null && poly != null) {
1626 /*
1627 * It is slow when painting gradients... modify so this is only done
1628 * once unless it is resized...
1629 */
1630 AxisAlignedBoxBounds b = AxisAlignedBoxBounds.getEnclosing(poly);
1631 double rads = getGradientAngle();
1632 double cos = Math.cos(rads);
1633 double sin = Math.sin(rads);
1634
1635 Point fromPoint = new Point((int) (b.getMinX() + b.getWidth() * (0.2 * cos + 0.5)), (int) (b.getMinY() + b.getHeight() * (0.2 * sin + 0.5)));
1636 Point toPoint = new Point((int) (b.getMinX() + b.getWidth() * (-0.8 * cos + 0.5)), (int) (b.getMinY() + b.getHeight() * (-0.8 * sin + 0.5)));
1637
1638 fill = new GradientFill(fillColour, fromPoint, gradientColor, toPoint);
1639 } else {
1640 fill = new Fill(fillColour);
1641 }
1642
1643 return fill;
1644 }
1645
1646 /**
1647 * This method performs all the actions in an items list. If it contains a
1648 * link as well the link is used as the source frame for all actions.
1649 */
1650 public void performActions() {
1651 Frame sourceFrame = null;
1652 Item sourceItem = FreeItems.getItemAttachedToCursor();
1653
1654 if (sourceItem == null) {
1655 sourceItem = this;
1656 } else {
1657 for (Item i : sourceItem.getAllConnected()) {
1658 if (i instanceof Text) {
1659 sourceItem = i;
1660 break;
1661 }
1662 }
1663 }
1664
1665 // TODO decide whether to have items or
1666 // if a link exists make it the source frame for this action
1667 if (getLink() != null) {
1668 sourceFrame = FrameUtils.getFrame(getAbsoluteLink());
1669 }
1670 // if no link exists or the link is bad then use the
1671 // currently displayed frame as the source frame for the
1672 // action
1673 if (sourceFrame == null) {
1674 // For actions like format they rely on this being set to the
1675 // current frame incase the item being activated is on an overlay
1676 sourceFrame = DisplayController.getCurrentFrame();
1677 }
1678
1679 for (String s : getAction()) {
1680 Object returnValue;
1681 if (LegacyFeatures.UseLegacyActionArgumentMapping.get()) {
1682 returnValue = Actions.LegacyPerformActionCatchErrors(sourceFrame, sourceItem, s);
1683 } else {
1684 returnValue = Actions.PerformActionCatchErrors(sourceFrame, sourceItem, s, this);
1685 }
1686
1687 if (returnValue != null) {
1688 FreeItems.getInstance().clear();
1689 if (returnValue instanceof Item) {
1690 Misc.attachToCursor(((Item) returnValue).getAllConnected());
1691 } else if (returnValue instanceof Collection) {
1692 try {
1693 Misc.attachToCursor((Collection) returnValue);
1694 } catch (Exception e) {
1695 e.printStackTrace();
1696 }
1697 } else {
1698 Misc.attachStatsToCursor(returnValue.toString());
1699 }
1700 }
1701 }
1702 }
1703
1704 /**
1705 * Removes all constraints that this item has.
1706 *
1707 */
1708 public void removeAllConstraints() {
1709 while (_constraints.size() > 0) {
1710 Constraint c = _constraints.get(0);
1711 c.getEnd().removeConstraint(c);
1712 c.getStart().removeConstraint(c);
1713 }
1714 }
1715
1716 /**
1717 * Clears the list of Lines that this Dot is an end of. Note: This only
1718 * clears this Dot's list and does not have any affect on the Lines or other
1719 * Dots.
1720 */
1721 public void removeAllLines() {
1722 for (Line l : _lines) {
1723 l.invalidateAll();
1724 }
1725 _lines.clear();
1726 }
1727
1728 /**
1729 * Removes the given Constraint from the list of constraints that this Dot
1730 * is a part of.
1731 *
1732 * @param c
1733 * The Constraint that this Dot is no longer a part of.
1734 */
1735 public void removeConstraint(Constraint c) {
1736 _constraints.remove(c);
1737 }
1738
1739 /**
1740 * Removes the given Line from the list of lines that this Dot is an end
1741 * for.
1742 *
1743 * @param line
1744 * The Line that this Dot is no longer an end of.
1745 */
1746 public void removeLine(Line line) {
1747 if (_lines.remove(line))
1748 line.invalidateAll();
1749 }
1750
1751 public void run() {
1752 try {
1753
1754 List<String> action = this.getAction();
1755 if (action != null) {
1756 String action_name = action.get(0);
1757 if (action_name.equalsIgnoreCase("RunJavascriptFrame")){
1758 // Associate a new Context with this thread
1759 org.mozilla.javascript.Context javascript_context = org.mozilla.javascript.Context.enter();
1760 try {
1761 Scriptable javascript_scope = javascript_context.initStandardObjects();
1762 Context simple_context = new Context();
1763
1764
1765 //Object jsDisplayIO = org.mozilla.javascript.Context.javaToJS(org.expeditee.gui.DisplayIO, javascript_scope);
1766 //ScriptableObject.putProperty(javascript_scope, "displayIO", jsDisplayIO);
1767
1768
1769 Object jsSimpleContext = org.mozilla.javascript.Context.javaToJS(simple_context, javascript_scope);
1770 ScriptableObject.putProperty(javascript_scope, "simpleContext", jsSimpleContext);
1771
1772 Object jsErr = org.mozilla.javascript.Context.javaToJS(System.err, javascript_scope);
1773 ScriptableObject.putProperty(javascript_scope, "err", jsErr);
1774
1775 Object jsOut = org.mozilla.javascript.Context.javaToJS(System.out, javascript_scope);
1776 ScriptableObject.putProperty(javascript_scope, "out", jsOut);
1777
1778 Javascript.ProgramStarted();
1779 Javascript.RunFrameAndReportError(this, javascript_context,javascript_scope);
1780 MessageBay.displayMessage(AgentStats.getStats(), GREEN);
1781 }
1782 finally {
1783 org.mozilla.javascript.Context.exit();
1784 }
1785 }
1786 }
1787 else {
1788
1789 // assume it is a simple program that is to be run
1790 Simple.ProgramStarted();
1791 Context simple_context = new Context();
1792 Simple.RunFrameAndReportError(this, simple_context);
1793 MessageBay.displayMessage(AgentStats.getStats(), GREEN);
1794 }
1795 } catch (ConcurrentModificationException ce) {
1796 ce.printStackTrace();
1797 } catch (IncorrectUseOfStatementException ise) {
1798 MessageBay.linkedErrorMessage(ise.getMessage());
1799 MessageBay.displayMessage("See SIMPLE doc for ["
1800 + ise.getStatement() + "] statement", ise.getStatement()
1801 + "1", Colour.CYAN.darker(), true, null);
1802 } catch (Exception e) {
1803 MessageBay.linkedErrorMessage(e.getMessage());
1804 }
1805 Simple.ProgramFinished();
1806 // Need to repaint any highlights etc
1807 DisplayController.requestRefresh(true);
1808 }
1809
1810 /**
1811 * Check if it has a relative link if so make it absolute.
1812 *
1813 */
1814 public void setAbsoluteLink() {
1815 String link = getLink();
1816 if (link == null)
1817 return;
1818 // Check if all the characters are digits and hence it is a relative
1819 // link
1820 if (!FrameIO.isPositiveInteger(link))
1821 return;
1822
1823 // Make it an absolute link
1824 String framesetName;
1825
1826 if (_parent == null)
1827 framesetName = DisplayController.getCurrentFrame().getFramesetName();
1828 else
1829 framesetName = _parent.getFramesetName();
1830
1831 setLink(framesetName + link);
1832 }
1833
1834 /**
1835 * Sets any action code that should be associated with this Item Each entry
1836 * in the list is one line of code
1837 *
1838 * @param actions
1839 * The lines of code to associate with this Item
1840 */
1841 public void setActions(List<String> actions) {
1842 if (actions == null || actions.size() == 0) {
1843 invalidateCommonTrait(ItemAppearence.LinkChanged);
1844 _actions = null;
1845 } else {
1846 _actions = new LinkedList<String>(actions);
1847 }
1848
1849 // Want to resize the highlight box for text items if actions have been added
1850 invalidateBounds();
1851 invalidateCommonTrait(ItemAppearence.LinkChanged);
1852
1853 if (isSurrogate()) {
1854 surrogatePropertyInheritance.put(DefaultFrameWriter.ACTION_STR, false);
1855 Item primary = getPrimary();
1856 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.ACTION_STR)) {
1857 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
1858 primary.primaryPropertyEncryption.put(DefaultFrameWriter.ACTION_STR, inheritanceCheckOnSave);
1859 }
1860 }
1861 }
1862
1863 public void setData(List<String> data) {
1864 _data.setData(data);
1865 }
1866
1867 public void setData(String data) {
1868 _data.setData(data);
1869 }
1870
1871 public void addToData(String dataItem) {
1872 _data.addToData(dataItem);
1873
1874 if (isSurrogate()) {
1875 surrogatePropertyInheritance.put(DefaultFrameWriter.DATA_STR, false);
1876 Item primary = getPrimary();
1877 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.DATA_STR)) {
1878 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
1879 primary.primaryPropertyEncryption.put(DefaultFrameWriter.DATA_STR, inheritanceCheckOnSave);
1880 }
1881 }
1882 }
1883
1884 public boolean hasData(String dataItem) {
1885 return _data.hasData(dataItem);
1886 }
1887
1888 public void setActionCursorEnter(List<String> enter) {
1889 _actionCursorEnter = enter;
1890
1891 if (isSurrogate()) {
1892 surrogatePropertyInheritance.put(DefaultFrameWriter.ACTION_CURSOR_ENTER_STR, false);
1893 Item primary = getPrimary();
1894 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.ACTION_CURSOR_ENTER_STR)) {
1895 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
1896 primary.primaryPropertyEncryption.put(DefaultFrameWriter.ACTION_CURSOR_ENTER_STR, inheritanceCheckOnSave);
1897 }
1898 }
1899 }
1900
1901 public void setActionCursorLeave(List<String> leave) {
1902 _actionCursorLeave = leave;
1903
1904 if (isSurrogate()) {
1905 surrogatePropertyInheritance.put(DefaultFrameWriter.ACTION_CURSOR_LEAVE_STR, false);
1906 Item primary = getPrimary();
1907 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.ACTION_CURSOR_LEAVE_STR)) {
1908 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
1909 primary.primaryPropertyEncryption.put(DefaultFrameWriter.ACTION_CURSOR_LEAVE_STR, inheritanceCheckOnSave);
1910 }
1911 }
1912 }
1913
1914 public void setActionEnterFrame(List<String> enter) {
1915 _actionEnterFrame = enter;
1916
1917 if (isSurrogate()) {
1918 surrogatePropertyInheritance.put(DefaultFrameWriter.ACTION_ENTER_FRAME_STR, false);
1919 Item primary = getPrimary();
1920 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.ACTION_ENTER_FRAME_STR)) {
1921 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
1922 primary.primaryPropertyEncryption.put(DefaultFrameWriter.ACTION_ENTER_FRAME_STR, inheritanceCheckOnSave);
1923 }
1924 }
1925 }
1926
1927 public void setActionLeaveFrame(List<String> leave) {
1928 _actionLeaveFrame = leave;
1929
1930 if (isSurrogate()) {
1931 surrogatePropertyInheritance.put(DefaultFrameWriter.ACTION_LEAVE_FRAME_STR, false);
1932 Item primary = getPrimary();
1933 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.ACTION_LEAVE_FRAME_STR)) {
1934 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
1935 primary.primaryPropertyEncryption.put(DefaultFrameWriter.ACTION_LEAVE_FRAME_STR, inheritanceCheckOnSave);
1936 }
1937 }
1938 }
1939
1940 public void setActionMark(boolean val) {
1941 if (!val) invalidateCommonTrait(ItemAppearence.LinkChanged);
1942 invalidateBounds();
1943 _actionMark = val;
1944 if (val) invalidateCommonTrait(ItemAppearence.LinkChanged);
1945
1946 if (isSurrogate()) {
1947 surrogatePropertyInheritance.put(DefaultFrameWriter.ACTION_MARK_STR, false);
1948 Item primary = getPrimary();
1949 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.ACTION_MARK_STR)) {
1950 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
1951 primary.primaryPropertyEncryption.put(DefaultFrameWriter.ACTION_MARK_STR, inheritanceCheckOnSave);
1952 }
1953 }
1954 }
1955
1956 /**
1957 * Sets whether this Item is an Annotation.
1958 *
1959 * @param val
1960 * True if this Item is an Annotation, False otherwise.
1961 */
1962 public abstract void setAnnotation(boolean val);
1963
1964 /**
1965 * Used to set this Line as an Arrow. If length and ratio are 0, no arrow is
1966 * shown.
1967 *
1968 * @param length
1969 * The how far down the shaft of the line the arrowhead should
1970 * come.
1971 * @param ratio
1972 * The ratio of the arrow's length to its width.
1973 */
1974 public void setArrow(float length, double ratio, double nib_perc) {
1975 _arrowheadLength = length;
1976 _arrowheadRatio = ratio;
1977 _arrowheadNibPerc = nib_perc;
1978 updateArrowPolygon();
1979
1980 if (isSurrogate()) {
1981 surrogatePropertyInheritance.put(DefaultFrameWriter.ARROW_STR, false);
1982 Item primary = getPrimary();
1983 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.ARROW_STR)) {
1984 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
1985 primary.primaryPropertyEncryption.put(DefaultFrameWriter.ARROW_STR, inheritanceCheckOnSave);
1986 }
1987 }
1988 }
1989
1990 public void setArrow(float length, double ratio) {
1991 setArrow(length,ratio,DEFAULT_ARROWHEAD_NIB_PERC);
1992 }
1993
1994 public void setArrowhead(PolygonBounds arrow) {
1995 _arrowhead = arrow;
1996 }
1997
1998 public void setArrowheadLength(float length) {
1999 _arrowheadLength = length;
2000 updateArrowPolygon();
2001 }
2002
2003 public void setArrowheadRatio(double ratio) {
2004 _arrowheadRatio = ratio;
2005 updateArrowPolygon();
2006 }
2007
2008 public void setArrowheadNibPerc(double perc) {
2009 _arrowheadNibPerc = perc;
2010 updateArrowPolygon();
2011 }
2012
2013 public void setBackgroundColor(Colour c) {
2014 if (c != _backgroundColour) {
2015 _backgroundColour = c;
2016 invalidateCommonTrait(ItemAppearence.BackgroundColorChanged);
2017 }
2018
2019 if (isSurrogate()) {
2020 surrogatePropertyInheritance.put(DefaultFrameWriter.BACKGROUND_COLOR_STR, false);
2021 Item primary = getPrimary();
2022 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.BACKGROUND_COLOR_STR)) {
2023 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
2024 primary.primaryPropertyEncryption.put(DefaultFrameWriter.BACKGROUND_COLOR_STR, inheritanceCheckOnSave);
2025 }
2026 }
2027 }
2028
2029 public void setBorderColor(Colour c) {
2030 if (c != _colorBorder) {
2031 _colorBorder = c;
2032 invalidateCommonTrait(ItemAppearence.BorderColorChanged);
2033 }
2034
2035 if (isSurrogate()) {
2036 surrogatePropertyInheritance.put(DefaultFrameWriter.BORDER_COLOR_STR, false);
2037 Item primary = getPrimary();
2038 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.BORDER_COLOR_STR)) {
2039 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
2040 primary.primaryPropertyEncryption.put(DefaultFrameWriter.BORDER_COLOR_STR, inheritanceCheckOnSave);
2041 }
2042 }
2043 }
2044
2045 /**
2046 * Sets the Color to use on the bottom and right sections of this Item's
2047 * border. If top is NULL, then the Item's background Color will be used.
2048 *
2049 * @param top
2050 * The Color to display in the bottom and right sections of this
2051 * Item's border.
2052 */
2053 public void setBottomShadowColor(Colour bottom) {
2054 _colorBottomShadow = bottom;
2055 }
2056
2057 /**
2058 * Sets the foreground Color of this Item to the given Color.
2059 *
2060 * @param c
2061 */
2062 public void setColor(Colour c) {
2063 if (c != _foregroundColour) {
2064 _foregroundColour = c;
2065 invalidateCommonTrait(ItemAppearence.ForegroundColorChanged);
2066 if (hasVector()) {
2067 // TODO make this more efficient so it only repaints the items
2068 // for this vector
2069 StandardGestureActions.Refresh();
2070 }
2071 }
2072 }
2073
2074 public void setConstraintIDs(String IDs) {
2075 if (isSurrogate()) {
2076 surrogatePropertyInheritance.put(DefaultFrameWriter.CONSTRAINT_IDS_STR, false);
2077 Item primary = getPrimary();
2078 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.CONSTRAINT_IDS_STR)) {
2079 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
2080 primary.primaryPropertyEncryption.put(DefaultFrameWriter.CONSTRAINT_IDS_STR, inheritanceCheckOnSave);
2081 }
2082 }
2083 }
2084
2085 public void setConstraints(List<Constraint> constraints) {
2086 _constraints = constraints;
2087 }
2088
2089 public void setTag(String newData) {
2090 if (newData != null)
2091 _tag = new StringBuffer(newData);
2092 else
2093 _tag = null;
2094 }
2095
2096 /**
2097 * Sets the created date of this Frame to the given String.
2098 *
2099 * @param date
2100 * The date to use for this Frame.
2101 */
2102 public void setDateCreated(String date) {
2103 _creationDate = date;
2104
2105 if (isSurrogate()) {
2106 surrogatePropertyInheritance.put(DefaultFrameWriter.DATE_CREATED_STR, false);
2107 Item primary = getPrimary();
2108 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.DATE_CREATED_STR)) {
2109 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
2110 primary.primaryPropertyEncryption.put(DefaultFrameWriter.DATE_CREATED_STR, inheritanceCheckOnSave);
2111 }
2112 }
2113 }
2114
2115 public void setFillColor(Colour c) {
2116
2117 _fillColour = c;
2118
2119 for (Line line : _lines) {
2120 Item other = line.getOppositeEnd(this);
2121 if (other.getFillColor() != c) {
2122 other.setFillColor(c);
2123 }
2124 }
2125
2126 invalidateCommonTrait(ItemAppearence.FillColor);
2127 invalidateFill();
2128
2129 if (isSurrogate()) {
2130 surrogatePropertyInheritance.put(DefaultFrameWriter.FILL_COLOR_STR, false);
2131 Item primary = getPrimary();
2132 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.FILL_COLOR_STR)) {
2133 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
2134 primary.primaryPropertyEncryption.put(DefaultFrameWriter.FILL_COLOR_STR, inheritanceCheckOnSave);
2135 }
2136 }
2137 }
2138
2139 public void setGradientColor(Colour c) {
2140 _gradientColour = c;
2141
2142 for (Line line : _lines) {
2143 Item other = line.getOppositeEnd(this);
2144 if (other.getGradientColor() != c)
2145 other.setGradientColor(c);
2146 }
2147
2148 invalidateCommonTrait(ItemAppearence.GradientColor);
2149 invalidateFill();
2150
2151 if (isSurrogate()) {
2152 surrogatePropertyInheritance.put(DefaultFrameWriter.GRADIENT_COLOR_STR, false);
2153 Item primary = getPrimary();
2154 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.GRADIENT_COLOR_STR)) {
2155 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
2156 primary.primaryPropertyEncryption.put(DefaultFrameWriter.GRADIENT_COLOR_STR, inheritanceCheckOnSave);
2157 }
2158 }
2159 }
2160
2161 public Colour getGradientColor() {
2162 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.GRADIENT_COLOR_STR)) {
2163 return this.getPrimary().getGradientColor();
2164 } else {
2165 return _gradientColour;
2166 }
2167 }
2168
2169 public void setFillPattern(String patternLink) {
2170 _fillPattern = patternLink;
2171 invalidateCommonTrait(ItemAppearence.FillPattern);
2172 invalidateFill();
2173
2174 if (isSurrogate()) {
2175 surrogatePropertyInheritance.put(DefaultFrameWriter.FILL_PATTERN_STR, false);
2176 Item primary = getPrimary();
2177 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.FILL_PATTERN_STR)) {
2178 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
2179 primary.primaryPropertyEncryption.put(DefaultFrameWriter.FILL_PATTERN_STR, inheritanceCheckOnSave);
2180 }
2181 }
2182 }
2183
2184 public void setFloating(boolean val) {
2185 _floating = val;
2186 }
2187
2188 /**
2189 * Sets the value <code>_highlight</code> for this item.
2190 * TODO: Appears unused? cts16
2191 *
2192 * @param val The new value for <code>_highlight</code>.
2193 */
2194 public void setHighlight(boolean val) {
2195 _highlight = val;
2196
2197 if (isSurrogate()) {
2198 surrogatePropertyInheritance.put(DefaultFrameWriter.HIGHLIGHT_STR, false);
2199 Item primary = getPrimary();
2200 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.HIGHLIGHT_STR)) {
2201 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
2202 primary.primaryPropertyEncryption.put(DefaultFrameWriter.HIGHLIGHT_STR, inheritanceCheckOnSave);
2203 }
2204 }
2205 }
2206
2207 /**
2208 * Sets the ID of this Item to the given Integer. Note: Items with ID's < 0
2209 * are not saved
2210 *
2211 * @param newID
2212 * The new ID to assign this Item.
2213 */
2214 public void setID(int newID) {
2215 _id = newID;
2216
2217 if (isSurrogate()) {
2218 surrogatePropertyInheritance.put(DefaultFrameWriter.TYPE_AND_ID_STR, false);
2219 Item primary = getPrimary();
2220 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.TYPE_AND_ID_STR)) {
2221 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
2222 primary.primaryPropertyEncryption.put(DefaultFrameWriter.TYPE_AND_ID_STR, inheritanceCheckOnSave);
2223 }
2224 }
2225 }
2226
2227 /**
2228 * Sets the list of lines that this point is part of (may be set to null).
2229 *
2230 * @param lineID
2231 * A String of line ID numbers separated by spaces.
2232 */
2233 public void setLineIDs(String lineID) {
2234 if (isSurrogate()) {
2235 surrogatePropertyInheritance.put(DefaultFrameWriter.LINE_IDS_STR, false);
2236 Item primary = getPrimary();
2237 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.LINE_IDS_STR)) {
2238 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
2239 primary.primaryPropertyEncryption.put(DefaultFrameWriter.LINE_IDS_STR, inheritanceCheckOnSave);
2240 }
2241 }
2242 }
2243
2244 public void setLinePattern(int[] pattern) {
2245 _linePattern = pattern;
2246
2247 for (Line line : getLines())
2248 line.setLinePattern(pattern);
2249
2250 if (isSurrogate()) {
2251 surrogatePropertyInheritance.put(DefaultFrameWriter.LINE_PATTERN_STR, false);
2252 Item primary = getPrimary();
2253 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.LINE_PATTERN_STR)) {
2254 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
2255 primary.primaryPropertyEncryption.put(DefaultFrameWriter.LINE_PATTERN_STR, inheritanceCheckOnSave);
2256 }
2257 }
2258 }
2259
2260 public void setLines(List<Line> lines) {
2261 _lines = lines;
2262
2263 for (Line line : lines)
2264 line.setLinePattern(getLinePattern());
2265
2266 }
2267
2268 /**
2269 * Links this item to the given Frame, this may be set to null to remove a
2270 * link.
2271 *
2272 * @param frameName
2273 * The name of the Frame to link this item to.
2274 */
2275 public void setLink(String frameName) {
2276 if (frameName == null) invalidateCommonTrait(ItemAppearence.LinkChanged);
2277
2278 // If a link is being removed or set then need to reset _bounds so the
2279 // highlighting is drawn with the correct width
2280 if (frameName == null || getLink() == null) invalidateBounds();
2281
2282 if (FrameIO.isValidLink(frameName)) {
2283 _link = frameName;
2284 } else {
2285 MessageBay.errorMessage("[" + frameName + "] is not a valid frame name");
2286 }
2287 // TODO make this throw exceptions etc...
2288
2289 invalidateCommonTrait(ItemAppearence.LinkChanged);
2290
2291 if (isSurrogate()) {
2292 surrogatePropertyInheritance.put(DefaultFrameWriter.LINK_STR, false);
2293 Item primary = getPrimary();
2294 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.LINK_STR)) {
2295 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
2296 primary.primaryPropertyEncryption.put(DefaultFrameWriter.LINK_STR, inheritanceCheckOnSave);
2297 }
2298 }
2299 }
2300
2301 public void setLinkHistory(boolean value) {
2302 _linkHistory = value;
2303
2304 if (isSurrogate()) {
2305 surrogatePropertyInheritance.put(DefaultFrameWriter.LINK_HISTORY_STR, false);
2306 Item primary = getPrimary();
2307 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.LINK_HISTORY_STR)) {
2308 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
2309 primary.primaryPropertyEncryption.put(DefaultFrameWriter.LINK_HISTORY_STR, inheritanceCheckOnSave);
2310 }
2311 }
2312 }
2313
2314 public boolean getLinkHistory() {
2315 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.LINK_HISTORY_STR)) {
2316 return this.getPrimary().getLinkHistory();
2317 } else {
2318 return _linkHistory;
2319 }
2320 }
2321
2322 public void setLinkFrameset(String frameset)
2323 {
2324 if (frameset == null || FrameIO.isValidFramesetName(frameset)) {
2325 _link_frameset = frameset;
2326 } else {
2327 MessageBay.errorMessage("[" + frameset + "] is not a valid frameset name");
2328 }
2329 // TODO make this throw exceptions etc...
2330
2331 if (isSurrogate()) {
2332 surrogatePropertyInheritance.put(DefaultFrameWriter.LINK_FRAMESET_STR, false);
2333 Item primary = getPrimary();
2334 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.LINK_FRAMESET_STR)) {
2335 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
2336 primary.primaryPropertyEncryption.put(DefaultFrameWriter.LINK_FRAMESET_STR, inheritanceCheckOnSave);
2337 }
2338 }
2339 }
2340
2341 public void setLinkMark(boolean val) {
2342 if (!val) invalidateCommonTrait(ItemAppearence.LinkChanged);
2343 invalidateBounds();
2344 _linkMark = val;
2345 if (val) invalidateCommonTrait(ItemAppearence.LinkChanged);
2346
2347 if (isSurrogate()) {
2348 surrogatePropertyInheritance.put(DefaultFrameWriter.LINK_MARK_STR, false);
2349 Item primary = getPrimary();
2350 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.LINK_MARK_STR)) {
2351 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
2352 primary.primaryPropertyEncryption.put(DefaultFrameWriter.LINK_MARK_STR, inheritanceCheckOnSave);
2353 }
2354 }
2355 }
2356
2357 public void setLinkTemplate(String template) {
2358 if (FrameIO.isValidLink(template)) {
2359 _link_template = template;
2360 } else {
2361 MessageBay.errorMessage("[" + template + "] is not a valid frame name");
2362 }
2363 // TODO make this throw exceptions etc...
2364
2365 if (isSurrogate()) {
2366 surrogatePropertyInheritance.put(DefaultFrameWriter.LINK_TEMPLATE_STR, false);
2367 Item primary = getPrimary();
2368 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.LINK_TEMPLATE_STR)) {
2369 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
2370 primary.primaryPropertyEncryption.put(DefaultFrameWriter.LINK_TEMPLATE_STR, inheritanceCheckOnSave);
2371 }
2372 }
2373 }
2374
2375 // /**
2376 // * Sets the maximum coordinates on the screen that this item may occupy.
2377 // * This is used by Text items to compute word-wrapping lengths.
2378 // *
2379 // * @param d
2380 // * The Maximum size of the Frame containing this Item.
2381 // */
2382 // public void setMaxWidth(int width) {
2383 // if (width > 0) {
2384 // _maxWidth = width;
2385 // updatePolygon();
2386 // }
2387 // }
2388
2389 public void setOffset(int x, int y) {
2390 _offset.set(x, y);
2391 }
2392
2393 public void setOffset(Point p) {
2394 _offset.set(p);
2395 }
2396
2397 public void setOwner(String own) {
2398 _owner = own;
2399
2400 if (isSurrogate()) {
2401 surrogatePropertyInheritance.put(DefaultFrameWriter.OWNER_STR, false);
2402 Item primary = getPrimary();
2403 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.OWNER_STR)) {
2404 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
2405 primary.primaryPropertyEncryption.put(DefaultFrameWriter.OWNER_STR, inheritanceCheckOnSave);
2406 }
2407 }
2408 }
2409
2410 public void setParent(Frame frame) {
2411 _oldParent = _parent;
2412 _parent = frame;
2413
2414 if (_parent == null) { return; }
2415
2416 final String currentUser = UserSettings.UserName.get();
2417 final String existingOwner = _parent.getOwner();
2418 if (currentUser != null && (existingOwner == null || currentUser.compareTo(existingOwner) != 0)) {
2419 setOwner(currentUser);
2420 }
2421 }
2422
2423 /**
2424 * Invalidates this, connected lines and fill
2425 *
2426 * @param trait
2427 */
2428 private void invalidateCommonTraitForAll(ItemAppearence trait) {
2429 invalidateCommonTrait(trait);
2430 if (isLineEnd()) {
2431 boolean hasLinePattern = getLines().get(0).getLinePattern() != null;
2432 if (hasLinePattern) {
2433 for (Item i : getAllConnected()) {
2434 if (i instanceof Line) {
2435 ((Line) i).invalidateCommonTrait(trait);
2436 }
2437 }
2438 } else {
2439 for (Line line : getLines()) {
2440 line.invalidateCommonTrait(trait);
2441 }
2442 }
2443 }
2444 if (_fillColour != null) {
2445 invalidateFill(); // only invalidates if has fill
2446 }
2447 for (XRayable x : getEnclosures()) {
2448 x.invalidateCommonTrait(trait);
2449 }
2450
2451 }
2452
2453 protected void anchorConstraints()
2454 {
2455 // update the position of any dots that are constrained by this one
2456 for (Constraint c : _constraints) {
2457 Item other = c.getOppositeEnd(this);
2458
2459 // only set position if the other dot is still fixed to the
2460 // frame
2461 if (/* this.isFloating() && */!other.isFloating()) {
2462 if (c.getType() == Constraint.HORIZONTAL) {
2463 if (isAnchoredY()) {
2464 // Make the 'other' item have the same anchor top/bottom values as this
2465 other._anchoring.setYAnchor(this._anchoring);
2466 }
2467 } else if (c.getType() == Constraint.VERTICAL) {
2468 if (isAnchoredX()) {
2469 // Make the 'other' item have the same anchor left/right values as this
2470 other._anchoring.setXAnchor(this._anchoring);
2471 }
2472 } else if (c.isDiagonal()) {
2473
2474 System.err.println("Warning: anchorConstraints() not implement for Diagonal setting");
2475 }
2476 }
2477 }
2478 }
2479
2480 /**
2481 * Sets the position of this item on the screen
2482 *
2483 * @param x
2484 * The new X coordinate
2485 * @param y
2486 * The new Y coordinate
2487 */
2488 public void setPosition(float x, float y) {
2489 float deltaX = x - _x;
2490 float deltaY = y - _y;
2491
2492 if (deltaX == 0 && deltaY == 0) return;
2493
2494 invalidateCommonTraitForAll(ItemAppearence.PreMoved);
2495
2496 _x = x;
2497 _y = y;
2498
2499 for (Item i : getEnclosures()) {
2500 i.invalidateBounds();
2501 }
2502 invalidateBounds();
2503
2504 // update the position of any dots that are constrained by this one
2505 for (Constraint c : _constraints) {
2506 Item other = c.getOppositeEnd(this);
2507
2508 // only set position if the other dot is still fixed to the
2509 // frame
2510 if (/* this.isFloating() && */!other.isFloating()) {
2511 if (c.getType() == Constraint.HORIZONTAL) {
2512 if (other._y != y) {
2513 other.setY(y);
2514 }
2515 } else if (c.getType() == Constraint.VERTICAL) {
2516 if (other._x != x) {
2517 other.setX(x);
2518 }
2519 } else if (c.isDiagonal()) {
2520 if (Math.abs(other._x - x) != Math.abs(other._y - y)) {
2521
2522 float m1 = c.getGradient();
2523 float c1 = y - m1 * x;
2524 // Now work out the equation for the second line
2525 // Get the first line the other end is attached to that
2526 // is not the diagonal line
2527 List<Line> lines = other.getLines();
2528 // If there is only one line...
2529 if (lines.size() == 1) {
2530 if (m1 != 0) {
2531 if (Math.abs(deltaX) > Math.abs(deltaY)) {
2532 other.setX((other._y - c1) / m1);
2533 } else {
2534 other.setY(m1 * other._x + c1);
2535 }
2536 }
2537 } else if (lines.size() > 1) {
2538 Line otherLine = lines.get(0);
2539 Item end = otherLine.getOppositeEnd(other);
2540 if (end.equals(this)) {
2541 otherLine = lines.get(1);
2542 end = otherLine.getOppositeEnd(other);
2543 assert (!end.equals(this));
2544 }
2545
2546 float xDiff = end._x - other._x;
2547 float yDiff = end._y - other._y;
2548 if (xDiff == 0) {
2549 other.setY(m1 * other._x + c1);
2550 } else if (Math.abs(xDiff) == Math.abs(yDiff)
2551 && !this.isFloating() && deltaX == 0
2552 && deltaY == 0) {
2553 if (deltaX == 0) {
2554 _x = (_y - other._y) * m1 + other._x;
2555 } else {
2556 _y = (_x - other._x) * m1 + other._y;
2557 }
2558 } else {
2559 float m2 = yDiff / xDiff;
2560 float c2 = end._y - m2 * end._x;
2561 float mDiff = m1 - m2;
2562 if (Math.abs(mDiff) < 0.000001) {
2563 assert (false);
2564 // TODO how do I handle this case!!
2565 } else {
2566 float newX = (c2 - c1) / mDiff;
2567 float newY = m1 * newX + c1;
2568 if (other._x != newX
2569 /* && other._y != newY */) {
2570 other.setPosition(newX, newY);
2571 }
2572 }
2573 }
2574 }
2575 // Do simultaneous equations to get the new postion for
2576 // the other end of the diagonal line
2577 }
2578 }
2579 }
2580 }
2581
2582 for (Line line : getLines()) {
2583 line.invalidateBounds();
2584 }
2585
2586 // for (Item item : getAllConnected()) {
2587 // item.updatePolygon();
2588 // }
2589
2590 invalidateCommonTraitForAll(ItemAppearence.PostMoved);
2591
2592 if (isSurrogate()) {
2593 surrogatePropertyInheritance.put(DefaultFrameWriter.POSITION_STR, false);
2594 Item primary = getPrimary();
2595 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.POSITION_STR)) {
2596 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
2597 primary.primaryPropertyEncryption.put(DefaultFrameWriter.POSITION_STR, inheritanceCheckOnSave);
2598 }
2599 }
2600 }
2601
2602 public void setPosition(Point position) {
2603 setPosition(position.getX(), position.getY());
2604 }
2605
2606 public void setRelativeLink() {
2607 String link = getLink();
2608 if (link == null)
2609 return;
2610 assert (_parent != null);
2611
2612 if (FrameIO.isPositiveInteger(link))
2613 return;
2614
2615 // Check if the link is for the current frameset
2616 if (_parent.getFramesetName().equalsIgnoreCase(
2617 Conversion.getFramesetName(link))) {
2618 setLink("" + Conversion.getFrameNumber(link));
2619 }
2620 }
2621
2622 /**
2623 * Sets the size of this Item. For Text this is the Font size. For Lines and
2624 * Dots this is the thickness.
2625 */
2626 public void setSize(float size) {
2627 }
2628
2629 /**
2630 * Sets the thickness of the item.
2631 *
2632 * @param thick
2633 */
2634 public final void setThickness(float thick) {
2635 setThickness(thick, true);
2636
2637 if (isSurrogate()) {
2638 surrogatePropertyInheritance.put(DefaultFrameWriter.THICKNESS_STR, false);
2639 Item primary = getPrimary();
2640 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.THICKNESS_STR)) {
2641 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
2642 primary.primaryPropertyEncryption.put(DefaultFrameWriter.THICKNESS_STR, inheritanceCheckOnSave);
2643 }
2644 }
2645 }
2646
2647 /**
2648 * Sets the thickness of this item.
2649 *
2650 * @param thick
2651 * the new thickness for the item
2652 * @param setConnectedThickness
2653 * true if all items connected to this item should also have
2654 * their thickness set
2655 */
2656 public void setThickness(float thick, boolean setConnectedThickness)
2657 {
2658 if (thick == _thickness) return;
2659
2660 boolean bigger = thick > _thickness;
2661
2662 if (!bigger) {
2663 if (setConnectedThickness) {
2664 // TODO is there a more efficient way of doing this?
2665 for (Item i : getConnected()) i.invalidateCommonTrait(ItemAppearence.Thickness);
2666 } else {
2667 invalidateCommonTrait(ItemAppearence.Thickness);
2668 }
2669 }
2670
2671 _thickness = thick;
2672 // update the size of any lines
2673 /*
2674 * TODO: Revise the way line thickness is set to make it more efficient
2675 * etc...
2676 */
2677 for (Line line : getLines()) line.setThickness(thick, setConnectedThickness);
2678
2679 if (setConnectedThickness) invalidateBounds();
2680
2681 if (bigger) {
2682 if (setConnectedThickness) {
2683 for (Item i : getConnected()) i.invalidateCommonTrait(ItemAppearence.Thickness);
2684 } else {
2685 invalidateCommonTrait(ItemAppearence.Thickness);
2686 }
2687 }
2688 }
2689
2690 /**
2691 * Returns the thickness (in pixels) of this Dot.
2692 *
2693 * @return The 'thickness' of this Dot. (returns -1 if the thickness is not
2694 * set).
2695 */
2696 public float getThickness() {
2697 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.THICKNESS_STR)) {
2698 return this.getPrimary().getThickness();
2699 } else {
2700 return _thickness;
2701 }
2702 }
2703
2704 /**
2705 * Sets the Color to use on the top and left sections of this Item's border.
2706 * If top is NULL, then the Item's background Color will be used.
2707 *
2708 * @param top
2709 * The Color to display in the top and left sections of this
2710 * Item's border.
2711 */
2712 public void setTopShadowColor(Colour top) {
2713 _colorTopShadow = top;
2714 }
2715
2716 public void setWidth(Integer width) throws UnsupportedOperationException
2717 {
2718 throw new UnsupportedOperationException("Item type does not support width attribute!");
2719 }
2720
2721 public void setMinWidth(final Integer width) throws UnsupportedOperationException {
2722 throw new UnsupportedOperationException("Item type does not support minwidth attribute.");
2723 }
2724
2725 public void setMaxWidth(Integer width) throws UnsupportedOperationException {
2726 throw new UnsupportedOperationException("Item type does not support maxwidth attribute");
2727 }
2728
2729 public void setRightMargin(int i, boolean fixWidth)
2730 {
2731 int newWidth = i - getX() - Item.MARGIN_LEFT;
2732 if (newWidth < 0) newWidth = 0;
2733
2734 if (!fixWidth) {
2735 newWidth *= -1;
2736 }
2737
2738 setWidth(newWidth);
2739 }
2740
2741 /**
2742 * Sets the position of this Item on the X axis
2743 *
2744 * @param newX
2745 * The position on the X axis to assign to this Item
2746 */
2747 public void setX(float newX) {
2748 setPosition(newX, getY());
2749
2750// if (isSurrogate()) {
2751// surrogatePropertyInheritance.put(DefaultFrameWriter.POSITION_STR, false);
2752// Item primary = getPrimary();
2753// if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.POSITION_STR)) {
2754// EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
2755// primary.primaryPropertyEncryption.put(DefaultFrameWriter.POSITION_STR, inheritanceCheckOnSave);
2756// }
2757// }
2758 }
2759
2760 /**
2761 * Sets the position of this Item on the Y axis
2762 *
2763 * @param newY
2764 * The position on the Y axis to assign to this Item
2765 */
2766 public void setY(float newY) {
2767 setPosition(getX(), newY);
2768
2769// if (isSurrogate()) {
2770// surrogatePropertyInheritance.put(DefaultFrameWriter.POSITION_STR, false);
2771// Item primary = getPrimary();
2772// if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.POSITION_STR)) {
2773// EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
2774// primary.primaryPropertyEncryption.put(DefaultFrameWriter.POSITION_STR, inheritanceCheckOnSave);
2775// }
2776// }
2777 }
2778
2779 /**
2780 * Paints any highlighting of this Item. This may include changing the
2781 * thickness (lines) or painting a box around the item (Text, Images). If
2782 * val is True then the Graphics Color is changed to the highlight Color, if
2783 * False then the Graphics Color is left unchanged (for clearing of
2784 * highlighting).
2785 *
2786 * @param val
2787 * True if this Item should be highlighted, false if the
2788 * highlighting is being cleared.
2789 * @return The desired mouse cursor when this Item is highlighted (negative
2790 * means no change)
2791 */
2792
2793 /**
2794 *
2795 *
2796 * @return
2797 */
2798 public void setHighlightColorToDefault() {
2799 setHighlightColor(DEFAULT_HIGHLIGHT);
2800 }
2801
2802 public void setHighlightColor(Colour c) {
2803 if (c == null) return;
2804
2805 if (!this.isVisible() && this.hasVector()) {
2806 for (Item i : this.getParentOrCurrentFrame().getVectorItems()) {
2807 if (i.getEditTarget() == this) {
2808 i.setHighlightColor(c);
2809 }
2810 }
2811 }
2812
2813 _highlightThickness = DEFAULT_HIGHLIGHT_THICKNESS;
2814
2815 Colour selColor = (c != null) ? c : DEFAULT_HIGHLIGHT;
2816 if (_highlightColour != c) {
2817 _highlightColour = selColor;
2818 this.invalidateCommonTrait(ItemAppearence.HighlightColorChanged);
2819 }
2820
2821 }
2822
2823 private void updateArrowPolygon() {
2824 if (getArrowheadLength() < 0 || getArrowheadRatio() < 0 || getArrowheadNibPerc() < 0)
2825 _arrowhead = null;
2826 else {
2827 _arrowhead = Line.createArrowheadPolygon(getX(),getY(),getArrowheadLength(),getArrowheadRatio(),getArrowheadNibPerc());
2828 }
2829 }
2830
2831 /** Returns a Bounds which represents the area covered by the item (including its gravity). */
2832 public abstract Bounds updateBounds();
2833
2834 public void setHidden(boolean state) {
2835 this._visible = !state;
2836 }
2837
2838 public void setVisible(boolean state) {
2839 this._visible = state;
2840 }
2841
2842 public boolean isVisible() {
2843 return _visible && !_deleted;
2844 }
2845
2846 /**
2847 * Raised whenever the item is removed, added, no longer in view (That is,
2848 * when it is not on any of the current frames, of overlays of the current
2849 * frames) or has become visible. That is, when it is either on a current
2850 * frame, or an overlay of a current frame.
2851 *
2852 * @param e
2853 * The event
2854 */
2855 public void onParentStateChanged(ItemParentStateChangedEvent e) {
2856 }
2857
2858 /**
2859 * Sets the highlight mode and colour at the same time.
2860 *
2861 * @param mode The new highlight mode.
2862 * @param colour The new highlight colour.
2863 */
2864 public void setHighlightModeAndColour(HighlightMode mode, Colour colour)
2865 {
2866 setHighlightMode(mode);
2867 setHighlightColor(colour);
2868 }
2869
2870 public HighlightMode getHighlightMode() {
2871 return _highlightMode;
2872 }
2873
2874 public void anchor() {
2875 Frame current = getParentOrCurrentFrame();
2876 // only set the id if we've moved to a different frame, or if the frame already has an item with that id
2877 if(!current.equals(_oldParent) || current.getItemWithID(getID()) != null) {
2878 setID(current.getNextItemID());
2879 } else {
2880 // System.out.println(this + " - Kept old ID of " + _id);
2881 }
2882 setOffset(0, 0);
2883 setParent(current);
2884
2885 current.addItem(this, false);
2886 current.invalidateSorted();
2887 setRelativeLink();
2888 setFloating(false);
2889
2890 // // If its an unconstrained line end check if we should add a
2891 // constraint
2892 // if (isLineEnd() && getLines().size() <= 2
2893 // && getConstraints().size() <= 1) {
2894 // Constraint existingConstraint = null;
2895 // List<Constraint> constraints = getConstraints();
2896 // // Get the existing constraint
2897 // if (constraints.size() > 0) {
2898 // existingConstraint = constraints.get(0);
2899 // }
2900 // for (Line line : getLines()) {
2901 // Integer constraintType = line.getPossibleConstraint();
2902 // if (constraintType != null) {
2903 // Item oppositeEnd = line.getOppositeEnd(this);
2904 // if (existingConstraint == null
2905 // || !existingConstraint.contains(oppositeEnd)) {
2906 // new Constraint(this, oppositeEnd,
2907 // getParentOrCurrentFrame().getNextItemID(),
2908 // constraintType);
2909 // }
2910 // }
2911 // }
2912 // }
2913 }
2914
2915 /**
2916 * Gets the parent frame if it is set or the current frame if this item does
2917 * not have a parent set.
2918 *
2919 * @return
2920 */
2921 public Frame getParentOrCurrentFrame() {
2922 // if the item is from an overlay the parent will NOT be null
2923 if (getParent() == null) {
2924 return DisplayController.getCurrentFrame();
2925 }
2926 return getParent();
2927 }
2928
2929 /**
2930 * Sets the list of Dots (including this one) that form a closed shape.
2931 * Passing null sets this dot back to its normal (non-enclosed) state.
2932 *
2933 * @param enclosed
2934 * The List of Dots including this one that form a closed shape,
2935 * or null.
2936 */
2937 public void setEnclosedList(Collection<Item> enclosed) {
2938
2939 boolean changed = (_enclosure == null && enclosed != null);
2940
2941 if (_enclosure != null && enclosed == null) {
2942 invalidateFill();
2943 }
2944
2945 _enclosure = enclosed;
2946
2947 if (changed) {
2948 invalidateFill();
2949 ;
2950 }
2951 }
2952
2953 /**
2954 * Returns the polygon that represents the shape created by all the Dots in
2955 * this Dot's enclosed list. If the list is null, then null is returned.
2956 *
2957 * @return A Polygon the same shape and position as created by the Dots in
2958 * the enclosed list.
2959 */
2960 public PolygonBounds getEnclosedShape()
2961 {
2962 if (_enclosure == null) return null;
2963
2964 PolygonBounds poly = new PolygonBounds();
2965 for (Item d : _enclosure) {
2966 poly.addPoint(new Point(d.getX(), d.getY()));
2967 }
2968
2969 return poly;
2970 }
2971
2972 /**
2973 * Returns the list of Dots that, along with this Dot, form an enclosed
2974 * polygon. If this Dot is not part of an enclosure null may be returned.
2975 *
2976 * @return The List of Dots that form an enclosed shape with this Dot, or
2977 * null if this Dot is not part of an enclosure.
2978 */
2979 public Collection<Item> getEnclosingDots() {
2980 return _enclosure;
2981 }
2982
2983 /**
2984 * Returns whether this Dot has an assigned enclosure list of other Dots.
2985 * The result is the same as getEnclosedShape() != null.
2986 *
2987 * @return True if this Dot has an enclosure list of other Dots, false
2988 * otherwise.
2989 */
2990 public boolean isEnclosed() {
2991 return _enclosure != null;
2992 }
2993
2994 /**
2995 * True if this item is the end of a line.
2996 *
2997 * @return
2998 */
2999 public boolean isLineEnd() {
3000 // TODO this will need to be redone when enclosure class is added...
3001 // At the moment enclosures are only circles...we don't want circle
3002 // centres to be lineEnds
3003 return _lines.size() > 0;
3004 }
3005
3006 public boolean hasEnclosures() {
3007 return _enclosures.size() > 0;
3008 }
3009
3010 /**
3011 * Method that is called to notify an item that is on the end of a line that
3012 * its line has changed color.
3013 *
3014 * @param c
3015 * the new color for the line
3016 */
3017 protected void lineColorChanged(Colour c) {
3018 for (Line l : getLines()) {
3019 if (l.getColor() != c)
3020 l.setColor(c);
3021 }
3022 }
3023
3024 /**
3025 * Checks if this item is off the left or top of the screen
3026 *
3027 * @return
3028 */
3029 public boolean offScreenTopOrLeft() {
3030 Bounds bounds = getBoundingBox();
3031
3032 // Check that the bottom right corner of this item is on the screen
3033 if (bounds.getMaxX() >= 0 && bounds.getMaxY() >= 0) {
3034 return false;
3035 }
3036
3037 // Check if all the items it is connected to are offscreen
3038 for (Item i : getAllConnected()) {
3039 bounds = i.getBoundingBox();
3040 // Check that the bottom right corner of this item is on the screen
3041 if (bounds.getMaxX() >= 0 && bounds.getMaxY() >= 0) {
3042 return false;
3043 }
3044 }
3045
3046 return true;
3047 }
3048
3049 public void setConnectedToAnnotation(boolean val) {
3050 _connectedToAnnotation = val;
3051 }
3052
3053 public boolean isConnectedToAnnotation() {
3054 return _connectedToAnnotation;
3055 }
3056
3057 public boolean hasAction() {
3058 List<String> actions = getAction();
3059 return actions != null && actions.size() > 0;
3060 }
3061
3062 public void setAction(String action)
3063 {
3064 // Want to resize the highlight box for text items if actions are been added
3065 if (action == null || action.length() == 0) {
3066 invalidateCommonTrait(ItemAppearence.LinkChanged);
3067 }
3068
3069 if (_actions == null || _actions.size() == 0) {
3070 invalidateBounds();
3071 _actions = new LinkedList<String>();
3072 } else {
3073 _actions.clear();
3074 }
3075
3076 if (action != null && action.length() > 0) _actions.add(action);
3077
3078 invalidateCommonTrait(ItemAppearence.LinkChanged);
3079 }
3080
3081 protected int getLinkYOffset() {
3082 return 0;
3083 }
3084
3085 protected AxisAlignedBoxBounds getLinkDrawArea() {
3086 return getLinkDrawArea(getX() - LEFT_MARGIN, getY() + getLinkYOffset());
3087 }
3088
3089 /**
3090 * TODO: Revise - it would be good to have a member that defines the link
3091 * dimensions.
3092 *
3093 * @param x
3094 * Left of graphic (i.e not centered)
3095 * @param y
3096 * Above graphic (i.e not centered)
3097 *
3098 * @return The drawing area of the link at the given coordinates.
3099 */
3100 public AxisAlignedBoxBounds getLinkDrawArea(int x, int y) {
3101 return new AxisAlignedBoxBounds(x + 2, y - 1, 8, 8);
3102 }
3103
3104 /**
3105 * Paint the link symbol for the item if it is a
3106 *
3107 * @param g
3108 */
3109 protected void paintLink() {
3110 paintLinkGraphic(getX() - LEFT_MARGIN, getY() + getLinkYOffset());
3111 }
3112
3113 /**
3114 * Paint the link symbol for the item at a given position.
3115 *
3116 * @see #paintLink
3117 *
3118 * @param g
3119 * The graphics to paint with
3120 *
3121 * @param x
3122 * The x position of the link. Left of graphic (i.e not centered)
3123 *
3124 * @param y
3125 * The y position of the link. Above of graphic (i.e not
3126 * centered)
3127 */
3128 public void paintLinkGraphic(int x, int y) {
3129
3130 boolean hasLink = hasLink();
3131 boolean hasAction = hasAction();
3132
3133 if (hasLink || hasAction) {
3134 GraphicsManager g = EcosystemManager.getGraphicsManager();
3135 Fill fill = new Fill();
3136 Colour colour = null;
3137 Point offset = new Point(x, y);
3138
3139 if (hasLink && hasAction) {
3140 colour = LINK_ACTION_COLOR;
3141 } else if (hasLink) {
3142 colour = LINK_COLOR;
3143 } else if (hasAction) {
3144 colour = ACTION_COLOR;
3145 }
3146 fill.setColour(colour);
3147
3148 // Small circles look rubbish without AA. cts16
3149 g.setAntialiasing(true);
3150
3151 if (hasLink && getLinkMark()) {
3152 g.drawOval(offset, getLinkBounds().getDiameters(), 0.0f, null, colour, HIGHLIGHT_STROKE);
3153
3154 // if the link is not valid, cross out the circle
3155 if (!isLinkValid()) {
3156 g.drawPolygon(getCircleCross(), offset, null, 0.0f, null, colour, HIGHLIGHT_STROKE);
3157 }
3158 }
3159
3160 if (hasAction && getActionMark()) {
3161 g.drawOval(offset, getLinkBounds().getDiameters(), 0.0f, fill, colour, HIGHLIGHT_STROKE);
3162
3163 // if the link is not valid, cross out the circle
3164 if (!isLinkValid() && getLink() != null) {
3165 g.drawPolygon(getCircleCross(), offset, null, 0.0f, null, getParent().getPaintBackgroundColor(), HIGHLIGHT_STROKE);
3166 }
3167 }
3168
3169 g.setAntialiasing(false);
3170 }
3171 }
3172
3173 /**
3174 * Gets the distance between the start of the text and the left border of
3175 * the item. This distance changes depending on whether or not the item is
3176 * linked or has an associated action.
3177 *
3178 * @return the gap size in pixels
3179 */
3180 protected int getLeftMargin() {
3181 return ((getLinkMark() && getLink() != null)
3182 || (getActionMark() && getAction() != null) ? MARGIN_LEFT
3183 - MARGIN_RIGHT : MARGIN_RIGHT);
3184 }
3185
3186 public String getName() {
3187 return getText();
3188 }
3189
3190 final public String getAbsoluteLinkTemplate() {
3191 return getAbsoluteLink(getLinkTemplate());
3192 }
3193
3194 final public String getAbsoluteLinkFrameset() {
3195 return getAbsoluteLink(getLinkFrameset());
3196 }
3197
3198 final public String getAbsoluteLink() {
3199 return getAbsoluteLink(getLink());
3200 }
3201
3202 /**
3203 * @param link
3204 * @return
3205 */
3206 private String getAbsoluteLink(String link) {
3207 if (link == null)
3208 return null;
3209 // assert (_parent!= null);
3210 Frame parent = getParentOrCurrentFrame();
3211 if (_parent == null) {
3212 // if parent is null it is an item on the message box
3213 // so it must already be absolute
3214 // assert (!FrameIO.isPositiveInteger(link));
3215 // return link;
3216
3217 }
3218
3219 // if its a relative link then return absolute
3220 if (FrameIO.isPositiveInteger(link)) {
3221 return parent.getFramesetName() + link;
3222 }
3223 return link;
3224 }
3225
3226 public static String convertToAbsoluteLink(String link) {
3227 if (link == null)
3228 return null;
3229 // assert (_parent!= null);
3230 Frame parent = DisplayController.getCurrentFrame();
3231 assert (parent != null);
3232
3233 // if its a relative link then return absolute
3234 if (FrameIO.isPositiveInteger(link)) {
3235 return parent.getFramesetName() + link;
3236 }
3237 return link;
3238 }
3239
3240 /**
3241 * Sets the x and y values of this item ignoring constraints.
3242 *
3243 * @param x
3244 * new x position
3245 * @param y
3246 * new y position
3247 */
3248 public void setXY(float x, float y) {
3249 _x = x;
3250 _y = y;
3251 }
3252
3253 /**
3254 * Recursive function for getting the path around a shape. This is used to
3255 * get the path that is painted on the screen.
3256 *
3257 * @param visited
3258 * @param points
3259 * @param addToEnd
3260 * @param toExplore
3261 */
3262 public void appendPath(Collection<Line> visited, LinkedList<Point> points,
3263 boolean addToEnd, Collection<Line> toExplore) {
3264
3265 if (addToEnd) {
3266 // put the start item points into our list
3267 points.addLast(getPosition());
3268 } else {
3269 points.addFirst(getPosition());
3270 }
3271
3272 // Find the line that has not been added yet
3273 LinkedList<Line> lines = new LinkedList<Line>();
3274 lines.addAll(getLines());
3275
3276 while (!lines.isEmpty()) {
3277 Line l = lines.remove();
3278 // if we haven't visited the line yet visit it
3279 if (!visited.contains(l)) {
3280 visited.add(l);
3281 Item otherEnd = l.getOppositeEnd(this);
3282 // Add all the unexplored lines to our list
3283 while (!lines.isEmpty()) {
3284 l = lines.remove();
3285 // Get the paths for the rest of the lines to be explored
3286 // later
3287 if (!toExplore.contains(l) && !visited.contains(l)) {
3288 toExplore.add(l);
3289 }
3290 }
3291 otherEnd.appendPath(visited, points, addToEnd, toExplore);
3292 }
3293 }
3294 }
3295
3296 /**
3297 * Gets the size of the enclosure that this item is part of. Used to
3298 * determine the paint order of items, with smaller items being painted
3299 * first.
3300 *
3301 * @return the area of the box surrounding the enclosed shape that this item
3302 * is part of
3303 */
3304 public double getEnclosedArea()
3305 {
3306 AxisAlignedBoxBounds box = getEnclosedBox();
3307 if (box == null) return 0.0;
3308 return box.getWidth() * box.getHeight();
3309 }
3310
3311 /**
3312 * Gets the box encompassing all points that form an enclosure with this item.
3313 *
3314 * @return An axis-aligned box around all enclosure points.
3315 */
3316 public AxisAlignedBoxBounds getEnclosedBox()
3317 {
3318 if (_enclosure == null) return null;
3319
3320 return AxisAlignedBoxBounds.getEnclosing(getEnclosedShape());
3321 }
3322
3323 public int getEnclosureID()
3324 {
3325 return _enclosure == null ? 0 : _enclosure.hashCode();
3326 }
3327
3328 /**
3329 * Returns the Bounds that surrounds this Item representing this Item's
3330 * 'gravity'.
3331 *
3332 * @return The Bounds surrounding this Item, which represents
3333 * this Items 'gravity'.
3334 */
3335 public final Bounds getBounds()
3336 {
3337 if (_bounds == null) _bounds = updateBounds();
3338
3339 // DEBUG
3340 if (_bounds == null) {
3341 //System.out.println("updateBounds failed!");
3342 }
3343
3344 return _bounds;
3345 }
3346
3347 public final Bounds getOldBounds()
3348 {
3349 return _oldBounds;
3350 }
3351
3352 public final void invalidateBounds()
3353 {
3354 if (_bounds != null) _oldBounds = _bounds;
3355 _bounds = null;
3356 }
3357
3358 public final AxisAlignedBoxBounds getBoundingBox()
3359 {
3360 return AxisAlignedBoxBounds.getEnclosing(getBounds());
3361 }
3362
3363 /**
3364 * Shifts the position of the item along the line between this items
3365 * location and a specified point.
3366 *
3367 * @param origin
3368 * @param ratio
3369 */
3370 public void translate(Point origin, double ratio) {
3371
3372 invalidateCommonTraitForAll(ItemAppearence.PreMoved);
3373
3374 _x = (float) (origin.getX() + ratio * (_x - origin.getX()));
3375 _y = (float) (origin.getY() + ratio * (_y - origin.getY()));
3376 invalidateBounds();
3377 for (Line line : getLines())
3378 line.invalidateBounds();
3379
3380 invalidateCommonTraitForAll(ItemAppearence.PostMoved);
3381
3382 }
3383
3384 private static int[] LinePatterns = new int[] { 0, 10, 20 };
3385
3386 /**
3387 * The rotates through a wheel of dashed lines.
3388 *
3389 * @param amount
3390 * number of rotations around the wheel to toggle by.
3391 */
3392 public void toggleDashed(int amount) {
3393 // find the index of the current line pattern
3394 int[] currentPattern = getLinePattern();
3395
3396 // Find the current pattern and move to the next pattern in the wheel
3397 for (int i = 0; i < LinePatterns.length; i++) {
3398 if (currentPattern == null || currentPattern[0] == LinePatterns[i]) {
3399 i += LinePatterns.length + amount;
3400 i %= LinePatterns.length;
3401
3402 // if we are at the start of the wheel make it 'null' (solid
3403 // line)
3404 if (i == 0) {
3405 setLinePattern(null);
3406 } else {
3407 setLinePattern(new int[] { LinePatterns[i], LinePatterns[i] });
3408 }
3409
3410 invalidateCommonTrait(ItemAppearence.ToggleDashed);
3411 return;
3412 }
3413 }
3414
3415 }
3416
3417 /**
3418 * For now there can only be one enclosure per item
3419 *
3420 * @param enclosure
3421 */
3422 public void addEnclosure(XRayable enclosure) {
3423 _enclosures.clear();
3424 _enclosures.add(enclosure);
3425 }
3426
3427 /**
3428 * Gets any XRayable items that have this item as a source.
3429 *
3430 * @return the collection of items that are linked to this item as source.
3431 * Guaranteed not to be null.
3432 */
3433 public Collection<? extends XRayable> getEnclosures() {
3434 return _enclosures;
3435 }
3436
3437 public void removeEnclosure(Item i) {
3438 _enclosures.remove(i);
3439
3440 }
3441
3442 public boolean isDeleted() {
3443 return _deleted;
3444 }
3445
3446 /**
3447 * @return The full canvas that this item draws to. Must include
3448 * highlighting bounds
3449 */
3450 public AxisAlignedBoxBounds getDrawingArea() {
3451
3452 final AxisAlignedBoxBounds boundingBox = getBoundingBox();
3453 return ItemUtils.expandRectangle(
3454 boundingBox,
3455 (int) Math.ceil(Math.max(_highlightThickness, getThickness())) + 1 // + 1 to make sure
3456 );
3457 }
3458
3459 /**
3460 *
3461 * @param area
3462 * @return True if area intersects with this items drawing area.
3463 */
3464 public final boolean isInDrawingArea(AxisAlignedBoxBounds area)
3465 {
3466 AxisAlignedBoxBounds drawingArea = getDrawingArea();
3467
3468 if (drawingArea == null) return false;
3469
3470 return drawingArea.intersects(area);
3471 }
3472
3473 /**
3474 * Completely invalidates the item - so that it should be redrawn. Note:
3475 * This is handled internally, it should be rare to invoke this externally
3476 */
3477 public final void invalidateAll()
3478 {
3479 invalidate(getDrawingArea());
3480 }
3481
3482 /**
3483 * Invalidates areas on the parent frame. Purpose: to be called on specific
3484 * areas of the item that needs redrawing.
3485 *
3486 * @param damagedAreas
3487 */
3488 protected final void invalidate(Bounds[] damagedAreas)
3489 {
3490 if (damagedAreas != null) for (Bounds b : damagedAreas) invalidate(b);
3491 }
3492
3493 /**
3494 * Invalidates areas on the parent frame. Purpose: to be called on specific
3495 * areas of the item that needs redrawing.
3496 *
3497 * @param damagedAreas
3498 */
3499 protected final void invalidate(Bounds damagedArea)
3500 {
3501 if (damagedArea != null) DisplayController.invalidateItem(this, damagedArea);
3502 }
3503
3504 /**
3505 * Used to invalidate visual traits commonly shared by all items.
3506 *
3507 * @param trait
3508 */
3509 public final void invalidateCommonTrait(ItemAppearence trait)
3510 {
3511 invalidate(getDamagedArea(trait));
3512
3513 if (_fillColour != null && (trait == ItemAppearence.Added || trait == ItemAppearence.Removed)) {
3514 invalidateFill();
3515 }
3516 }
3517
3518 /**
3519 * Invalidates fill if has one, even if no color is set.
3520 */
3521 public void invalidateFill()
3522 {
3523 if (isLineEnd() && _enclosure != null) {
3524 invalidate(getEnclosedBox());
3525 }
3526 }
3527
3528 /**
3529 * Default implementation always uses drawing area except for links, where
3530 * the link drawing area is used. Override to make item drawing more
3531 * efficient - defining only parts of the item that needs redrawing.
3532 *
3533 * @see Item.getDrawingArea
3534 *
3535 * @param trait
3536 * The visual trait that has changed.
3537 *
3538 * @return The damaged area according to the visual trait that has changed.
3539 */
3540 protected AxisAlignedBoxBounds getDamagedArea(ItemAppearence trait)
3541 {
3542 if (trait == ItemAppearence.LinkChanged)
3543 return getLinkDrawArea(); // Invalidate area where link is drawn
3544
3545 return getDrawingArea();
3546 }
3547
3548 public boolean hasVector() {
3549 return _overlay instanceof Vector;
3550 }
3551
3552 public boolean hasOverlay() {
3553 return _overlay != null;
3554 }
3555
3556 public Vector getVector() {
3557 if (_overlay instanceof Vector)
3558 return (Vector) _overlay;
3559 return null;
3560 }
3561
3562 public void setOverlay(Overlay overlay) {
3563 _overlay = overlay;
3564 }
3565
3566 public boolean dontSave() {
3567 /*
3568 * TODO Mike says: checkout if the ID check is still needed- When will
3569 * ID still be -1 when saving a frame? assert (i != null);
3570 */
3571 // make it save stuff that's off the screen so stuff isn't deleted by panning - jts21
3572 return !_save || !isVisible() || getID() < 0; // || offScreenTopOrLeft();
3573 }
3574
3575 public void setAnchorLeft(Integer anchor) {
3576 this._anchoring.setLeftAnchor(anchor);
3577 if (anchor != null) {
3578 anchorConstraints();
3579 setX(anchor);
3580 }
3581
3582 if (isSurrogate()) {
3583 surrogatePropertyInheritance.put(DefaultFrameWriter.ANCHOR_LEFT_STR, false);
3584 Item primary = getPrimary();
3585 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.ANCHOR_LEFT_STR)) {
3586 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
3587 primary.primaryPropertyEncryption.put(DefaultFrameWriter.ANCHOR_LEFT_STR, inheritanceCheckOnSave);
3588 }
3589 }
3590 }
3591
3592 public void setAnchorRight(Integer anchor) {
3593 this._anchoring.setRightAnchor(anchor);
3594 if (anchor != null) {
3595 anchorConstraints();
3596 setX(DisplayController.getFramePaintArea().getMaxX() - anchor - getBoundsWidth());
3597 }
3598
3599 if (isSurrogate()) {
3600 surrogatePropertyInheritance.put(DefaultFrameWriter.ANCHOR_RIGHT_STR, false);
3601 Item primary = getPrimary();
3602 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.ANCHOR_RIGHT_STR)) {
3603 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
3604 primary.primaryPropertyEncryption.put(DefaultFrameWriter.ANCHOR_RIGHT_STR, inheritanceCheckOnSave);
3605 }
3606 }
3607 }
3608
3609 public void setAnchorTop(Integer anchor) {
3610 this._anchoring.setTopAnchor(anchor);
3611 if (anchor != null) {
3612 anchorConstraints();
3613 setY(anchor);
3614 }
3615
3616 if (isSurrogate()) {
3617 surrogatePropertyInheritance.put(DefaultFrameWriter.ANCHOR_TOP_STR, false);
3618 Item primary = getPrimary();
3619 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.ANCHOR_TOP_STR)) {
3620 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
3621 primary.primaryPropertyEncryption.put(DefaultFrameWriter.ANCHOR_TOP_STR, inheritanceCheckOnSave);
3622 }
3623 }
3624 }
3625
3626
3627 public void setAnchorBottom(Integer anchor) {
3628 this._anchoring.setBottomAnchor(anchor);
3629 if (anchor != null) {
3630 anchorConstraints();
3631 setY(DisplayController.getFramePaintArea().getMaxY() - anchor);
3632 }
3633
3634 if (isSurrogate()) {
3635 surrogatePropertyInheritance.put(DefaultFrameWriter.ANCHOR_BOTTOM_STR, false);
3636 Item primary = getPrimary();
3637 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.ANCHOR_BOTTOM_STR)) {
3638 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
3639 primary.primaryPropertyEncryption.put(DefaultFrameWriter.ANCHOR_BOTTOM_STR, inheritanceCheckOnSave);
3640 }
3641 }
3642 }
3643
3644 public boolean isAnchored()
3645 {
3646 return _anchoring.isAnchored();
3647 }
3648
3649 public boolean isAnchoredX() {
3650 return _anchoring.isXAnchored();
3651 }
3652
3653 public boolean isAnchoredY() {
3654 return _anchoring.isYAnchored();
3655 }
3656
3657 public Integer getAnchorLeft() {
3658 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.ANCHOR_LEFT_STR)) {
3659 return this.getPrimary().getAnchorLeft();
3660 } else {
3661 return _anchoring.getLeftAnchor();
3662 }
3663 }
3664
3665 public Integer getAnchorRight() {
3666 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.ANCHOR_RIGHT_STR)) {
3667 return this.getPrimary().getAnchorRight();
3668 } else {
3669 return _anchoring.getRightAnchor();
3670 }
3671 }
3672
3673 public Integer getAnchorTop() {
3674 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.ANCHOR_TOP_STR)) {
3675 return this.getPrimary().getAnchorTop();
3676 } else {
3677 return _anchoring.getTopAnchor();
3678 }
3679 }
3680
3681 public Integer getAnchorBottom() {
3682 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.ANCHOR_BOTTOM_STR)) {
3683 return this.getPrimary().getAnchorBottom();
3684 } else {
3685 return _anchoring.getBottomAnchor();
3686 }
3687 }
3688
3689 public String getText() {
3690 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.TEXT_STR)) {
3691 return this.getPrimary().getText();
3692 } else {
3693 return "@" + getClass().getSimpleName() + ":" + getID();
3694 }
3695 }
3696
3697 public void setText(String text) {
3698 }
3699
3700 public boolean recalculateWhenChanged() {
3701 return false;
3702 }
3703
3704 public boolean update() {
3705 return calculate(getText());
3706 }
3707
3708 public Collection<Item> getEnclosedItems() {
3709 return FrameUtils.getItemsEnclosedBy(this.getParentOrCurrentFrame(),
3710 this.getEnclosedShape());
3711 }
3712
3713 public Collection<Text> getEnclosedNonAnnotationText() {
3714 Collection<Text> items = new LinkedHashSet<Text>();
3715 for (Item t : getEnclosedItems()) {
3716 if (t instanceof Text && !t.isAnnotation())
3717 items.add((Text) t);
3718 }
3719
3720 return items;
3721 }
3722
3723 public void dispose() {
3724 setParent(null);
3725 }
3726
3727 /**
3728 * @return
3729 */
3730 protected boolean hasVisibleBorder() {
3731 return getThickness() > 0 && !isLineEnd() && getBorderColor() != null;
3732 }
3733
3734 public Frame getChild() {
3735 String childName = getAbsoluteLink();
3736 if (childName != null) {
3737 return FrameIO.LoadFrame(childName);
3738 }
3739 return null;
3740 }
3741
3742 public boolean hasLink() {
3743 return _link != null;
3744 }
3745
3746 protected void anchorConnectedOLD(AnchorEdgeType anchorEdgeType, Float delta) {
3747 // Check for a more efficient way to do this!!
3748 // Invalidate all the items
3749 for (Item i : this.getAllConnected()) {
3750 i.invalidateAll();
3751 }
3752 // Move the items
3753 for (Item i : this.getAllConnected()) {
3754 if (i.isLineEnd()) {
3755 if (delta != null) {
3756 if ((anchorEdgeType == AnchorEdgeType.Left) || (anchorEdgeType == AnchorEdgeType.Right)) {
3757 // 'delta' encodes a horizontal (x) move
3758 if (anchorEdgeType == AnchorEdgeType.Left) {
3759 i.setAnchorLeft(null);
3760 }
3761 else {
3762 // must be Right
3763 i.setAnchorRight(null);
3764 }
3765
3766 i.setXY(i.getX() + delta, i.getY());
3767 }
3768 if ((anchorEdgeType == AnchorEdgeType.Top) || (anchorEdgeType == AnchorEdgeType.Bottom)) {
3769 // 'delta; encodes a vertical (y) move
3770 if (anchorEdgeType == AnchorEdgeType.Top) {
3771 i.setAnchorTop(null);
3772 }
3773 else {
3774 // must be Bottom
3775 i.setAnchorBottom(null);
3776 }
3777 i.setXY(i.getX(), i.getY() + delta);
3778 }
3779
3780 }
3781 }
3782 }
3783 // Invalidate them again!!
3784 for (Item i : this.getAllConnected()) {
3785 i.invalidateBounds();
3786 i.invalidateAll();
3787 }
3788 }
3789
3790 protected void anchorConnected(AnchorEdgeType anchorEdgeType, Float delta) {
3791
3792 // Check for a more efficient way to do this!!
3793 // Invalidate all the items
3794 for (Item i : this.getAllConnected()) {
3795 i.invalidateAll();
3796 }
3797
3798 // Move the items
3799 for (Item i : this.getAllConnected()) {
3800 if (i.isLineEnd()) {
3801 if (delta != null) {
3802 if ((anchorEdgeType == AnchorEdgeType.Left) || (anchorEdgeType == AnchorEdgeType.Right)) {
3803 // 'delta' encodes a horizontal (x) move
3804 if (anchorEdgeType == AnchorEdgeType.Left) {
3805 // Processing a Left anchor
3806 // => Anything connected that is *not* anchored to the right should be moved by 'delta'
3807 if (i.getAnchorRight()==null) {
3808 i.setXY(i.getX() + delta, i.getY());
3809 }
3810 }
3811 else {
3812 // Processing a Right anchor
3813 // => Anything connected that is *not* anchored to the left should be moved by 'delta'
3814 if (i.getAnchorLeft()==null) {
3815 i.setXY(i.getX() + delta, i.getY());
3816 }
3817 }
3818
3819 }
3820 if ((anchorEdgeType == AnchorEdgeType.Top) || (anchorEdgeType == AnchorEdgeType.Bottom)) {
3821 // 'delta; encodes a vertical (y) move
3822 if (anchorEdgeType == AnchorEdgeType.Top) {
3823 // Processing a Top anchor
3824 // => Anything connected that is *not* anchored to the bottom should be moved by 'delta'
3825 if (i.getAnchorBottom()==null) {
3826 i.setXY(i.getX(), i.getY() + delta);
3827 }
3828 }
3829 else {
3830 // Processing a Bottom anchor
3831 // => Anything connected that is *not* anchored to the top should be moved by 'delta'
3832 if (i.getAnchorTop()==null) {
3833 // must be Bottom
3834 //i.setAnchorBottom(null);
3835 i.setXY(i.getX(), i.getY() + delta);
3836 }
3837 }
3838 }
3839 }
3840 }
3841 }
3842
3843 anchorConstraints();
3844
3845 // Invalidate them again!!
3846 for (Item i : this.getAllConnected()) {
3847 i.invalidateBounds();
3848 i.invalidateAll();
3849 }
3850 }
3851 /**
3852 * Sets the item to pickup when the user attempts to pick this item up.
3853 * EditTarget has a value of 'this' by default but may be set to other
3854 * values if this item is on a vector.
3855 *
3856 * @param target
3857 * the item to be copied or picked up when the user attempts to
3858 * edit this item.
3859 */
3860 public void setEditTarget(Item target) {
3861 _editTarget = target;
3862 }
3863
3864 /**
3865 * Gets the item to pickup when the user attempts to pick this item up.
3866 * EditTarget has a value of 'this' by default but may be set to other
3867 * values if this item is on a vector.
3868 */
3869 public Item getEditTarget() {
3870 return _editTarget;
3871 }
3872
3873 public void scale(Float scale, int originX, int originY) {
3874 setXY((getX() - originX) * scale + originX, (getY() - originY) * scale + originY);
3875 setArrowheadLength(getArrowheadLength() * scale);
3876
3877 float thickness = getThickness();
3878 if (thickness > 0)
3879 setThickness(thickness * scale, false);
3880
3881 // DONT PUT SIZE IN HERE CAUSE IT STUFFS UP CIRCLES
3882
3883 invalidateBounds();
3884 }
3885
3886 protected boolean isVectorItem() {
3887 return _editTarget != this;
3888 }
3889
3890 public AttributeValuePair getAttributeValuePair() {
3891 if (_attributeValuePair == null) {
3892 _attributeValuePair = new AttributeValuePair(getText());
3893 }
3894 return _attributeValuePair;
3895 }
3896
3897 /*
3898 * private static Set<Object> _locks = new HashSet<Object>();
3899 *
3900 * public static void lock(Object itemToLock) { _locks.add(itemToLock); }
3901 *
3902 * public static void unlock(Object itemToUnlock) {
3903 * _locks.remove(itemToUnlock); }
3904 *
3905 * public static boolean isLocked(Object item) { return
3906 * _locks.contains(item); }
3907 */
3908
3909 public void setSave(boolean state) {
3910 _save = state;
3911 }
3912
3913 public boolean getSave() {
3914 return _save;
3915 }
3916
3917 public void setAutoStamp(Float rate) {
3918 _autoStamp = rate;
3919 }
3920
3921 public Float getAutoStamp() {
3922 return _autoStamp;
3923 }
3924
3925 public boolean isAutoStamp() {
3926 return _autoStamp != null && _autoStamp >= 0.0;
3927 }
3928
3929 public int getMagnetizedItemLeft() {
3930 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.MAGNETIZED_ITEM_LEFT_STR)) {
3931 return this.getPrimary().getMagnetizedItemLeft();
3932 } else {
3933 if(_magnetizedItemLeft != null) return _magnetizedItemLeft.getID();
3934 else return -1;
3935 }
3936 }
3937
3938 public void setMagnetizedItemLeft(final Item item) {
3939 _magnetizedItemLeft = item;
3940 }
3941
3942 public void setMagnetizedItemLeft(final int id) {
3943 setMagnetizedItemLeft(this.getParent().getItemWithID(id));
3944
3945 if (isSurrogate()) {
3946 surrogatePropertyInheritance.put(DefaultFrameWriter.MAGNETIZED_ITEM_LEFT_STR, false);
3947 Item primary = getPrimary();
3948 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.MAGNETIZED_ITEM_LEFT_STR)) {
3949 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
3950 primary.primaryPropertyEncryption.put(DefaultFrameWriter.MAGNETIZED_ITEM_LEFT_STR, inheritanceCheckOnSave);
3951 }
3952 }
3953 }
3954
3955 public int getMagnetizedItemRight() {
3956 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.MAGNETIZED_ITEM_RIGHT_STR)) {
3957 return this.getPrimary().getMagnetizedItemRight();
3958 } else {
3959 if(_magnetizedItemRight != null) return _magnetizedItemRight.getID();
3960 else return -1;
3961 }
3962 }
3963
3964 public void setMagnetizedItemRight(final Item item) {
3965 _magnetizedItemRight = item;
3966 }
3967
3968 public void setMagnetizedItemRight(final int id) {
3969 setMagnetizedItemRight(this.getParent().getItemWithID(id));
3970
3971 if (isSurrogate()) {
3972 surrogatePropertyInheritance.put(DefaultFrameWriter.MAGNETIZED_ITEM_RIGHT_STR, false);
3973 Item primary = getPrimary();
3974 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.MAGNETIZED_ITEM_RIGHT_STR)) {
3975 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
3976 primary.primaryPropertyEncryption.put(DefaultFrameWriter.MAGNETIZED_ITEM_RIGHT_STR, inheritanceCheckOnSave);
3977 }
3978 }
3979 }
3980
3981 public int getMagnetizedItemTop() {
3982 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.MAGNETIZED_ITEM_TOP_STR)) {
3983 return this.getPrimary().getMagnetizedItemTop();
3984 } else {
3985 if(_magnetizedItemTop != null) return _magnetizedItemTop.getID();
3986 else return -1;
3987 }
3988 }
3989
3990 public void setMagnetizedItemTop(final Item item) {
3991 _magnetizedItemTop = item;
3992 }
3993
3994 public void setMagnetizedItemTop(final int id) {
3995 setMagnetizedItemTop(this.getParent().getItemWithID(id));
3996
3997 if (isSurrogate()) {
3998 surrogatePropertyInheritance.put(DefaultFrameWriter.MAGNETIZED_ITEM_TOP_STR, false);
3999 Item primary = getPrimary();
4000 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.MAGNETIZED_ITEM_TOP_STR)) {
4001 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
4002 primary.primaryPropertyEncryption.put(DefaultFrameWriter.MAGNETIZED_ITEM_TOP_STR, inheritanceCheckOnSave);
4003 }
4004 }
4005 }
4006
4007 public int getMagnetizedItemBottom() {
4008 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.MAGNETIZED_ITEM_BOTTOM_STR)) {
4009 return this.getPrimary().getMagnetizedItemBottom();
4010 } else {
4011 if(_magnetizedItemBottom != null) return _magnetizedItemBottom.getID();
4012 else return -1;
4013 }
4014 }
4015
4016 public void setMagnetizedItemBottom(final Item item) {
4017 _magnetizedItemBottom = item;
4018 }
4019
4020 public void setMagnetizedItemBottom(final int id) {
4021 setMagnetizedItemBottom(this.getParent().getItemWithID(id));
4022
4023 if (isSurrogate()) {
4024 surrogatePropertyInheritance.put(DefaultFrameWriter.MAGNETIZED_ITEM_BOTTOM_STR, false);
4025 Item primary = getPrimary();
4026 if (subjectToInheritanceCheckOnSave(DefaultFrameWriter.MAGNETIZED_ITEM_BOTTOM_STR)) {
4027 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
4028 primary.primaryPropertyEncryption.put(DefaultFrameWriter.MAGNETIZED_ITEM_BOTTOM_STR, inheritanceCheckOnSave);
4029 }
4030 }
4031 }
4032
4033 public String getEncryptionLabel() {
4034 if (isSurrogate() && surrogatePropertyInheritance.get(DefaultFrameWriter.ENCRYPTION_LABEL_STR)) {
4035 return this.getPrimary().getEncryptionLabel();
4036 } else {
4037 return _encryptionLabel;
4038 }
4039 }
4040
4041 public void setEncryptionLabel(String label) {
4042 if (this.getParent().getEncryptionLabel() == null) {
4043 MessageBay.displayMessage("Items can only be entrypted if the frame they are on is.");
4044 return;
4045 }
4046 LabelResult labelResult = Label.getLabel(label);
4047 if (labelResult != LabelResult.SuccessResolveLabelToKey) {
4048 MessageBay.displayMessage(labelResult.toString());
4049 return;
4050 }
4051
4052 this._encryptionLabel = label;
4053 this.getSurrogates().clear();
4054 Item copy = this.copy();
4055 if (copy instanceof Text) { copy.setText("Encrypted"); }
4056 this.addToSurrogates(copy);
4057 }
4058
4059 public void setEncryptionLabelOnLoad(String label) {
4060 this._encryptionLabel = label;
4061 }
4062
4063 /**
4064 * Replaces the given dot item with a text item displaying the given character.
4065 *
4066 * @param dot
4067 * The Dot item to replace.
4068 *
4069 * @param ch
4070 * The character to display as the text for the created Text item.
4071 *
4072 * @return
4073 * The created Text item.
4074 */
4075 public static Text replaceDot(Item dot, char ch) {
4076 // TODO: Should this make sure 'dot' is actually a Dot and not some other item? cts16
4077 Text text = Text.createText(ch);
4078 Item.DuplicateItem(dot, text);
4079 FrameUtils.setLastEdited(text);
4080
4081 // Copy the lines list so it can be modified
4082 List<Line> lines = new LinkedList<Line>(dot.getLines());
4083 for (Line line : lines)
4084 line.replaceLineEnd(dot, text);
4085 Frame current = dot.getParentOrCurrentFrame();
4086 current.removeItem(dot);
4087 ItemUtils.EnclosedCheck(current.getSortedItems());
4088 return text;
4089 // TODO: Should this add the newly-created Text item to the frame? cts16
4090 }
4091
4092 /**
4093 * Replaces the given text item with a dot
4094 */
4095 public static Item replaceText(Item text) {
4096 Item dot = new Dot(text.getX(), text.getY(), text.getID());
4097 Item.DuplicateItem(text, dot);
4098
4099 List<Line> lines = new LinkedList<Line>();
4100 lines.addAll(text.getLines());
4101 if (lines.size() > 0)
4102 dot.setColor(lines.get(0).getColor());
4103 for (Line line : lines) {
4104 line.replaceLineEnd(text, dot);
4105 }
4106 text.delete();
4107 Frame current = text.getParentOrCurrentFrame();
4108 current.addItem(dot);
4109 DisplayController.setCursor(Item.DEFAULT_CURSOR);
4110 ItemUtils.EnclosedCheck(current.getSortedItems());
4111 return dot;
4112 }
4113
4114 public Set<Item> getSurrogates() {
4115 return surrogateItems;
4116 }
4117
4118 private void setAsSurrogateFor(Item primary) {
4119 this.surrogateFor = primary;
4120 }
4121
4122 public void addToSurrogates(Item surrogate) {
4123 this.surrogateItems.add(surrogate);
4124 surrogate.setAsSurrogateFor(this);
4125 this.getParent().addItem(surrogate);
4126
4127 EncryptionDetail reencryptOnSave = new EncryptionDetail(EncryptionDetail.Type.ReencryptOnSave);
4128 EncryptionDetail unencryptedOnSave = new EncryptionDetail(EncryptionDetail.Type.UnencryptedOnSave);
4129 EncryptionDetail inheritanceCheckOnSave = new EncryptionDetail(EncryptionDetail.Type.InheritanceCheckOnSave);
4130
4131 for (Character tag: DefaultFrameWriter.getItemTags().keySet()) {
4132 if (tag == 'T') {
4133 primaryPropertyEncryption.put(tag + "", reencryptOnSave.clone());
4134 } else {
4135 primaryPropertyEncryption.put(tag + "", unencryptedOnSave.clone());
4136 }
4137
4138 if (tag == 'T' || tag == 'S') {
4139 surrogate.surrogatePropertyInheritance.put(tag + "", false);
4140 } else {
4141 surrogate.surrogatePropertyInheritance.put(tag + "", true);
4142 }
4143 }
4144
4145 for (String tag: DefaultFrameWriter.getItemTagsExt().keySet()) {
4146 primaryPropertyEncryption.put(tag, inheritanceCheckOnSave.clone());
4147 surrogate.surrogatePropertyInheritance.put(tag + "", true);
4148 }
4149 }
4150
4151 public boolean isSurrogate() {
4152 return this.surrogateFor != null;
4153 }
4154
4155 public Item getPrimary() {
4156 return this.surrogateFor;
4157 }
4158
4159 public EncryptionDetail getEncryptionDetailForTag(String tag) {
4160 EncryptionDetail encryptionDetail = primaryPropertyEncryption.get(tag);
4161
4162 if (encryptionDetail == null) {
4163 EncryptionDetail unencryptedOnSave = new EncryptionDetail(EncryptionDetail.Type.UnencryptedOnSave);
4164 return unencryptedOnSave;
4165 } else {
4166 return encryptionDetail;
4167 }
4168 }
4169
4170 public void setEncryptionDetailForTag(String tag, EncryptionDetail encryptionDetail) {
4171 primaryPropertyEncryption.put(tag, encryptionDetail);
4172 }
4173
4174 public boolean isTagInherited(String tag) {
4175 return surrogatePropertyInheritance.get(tag);
4176 }
4177
4178 public void setTagNotInherited(String tag) {
4179 surrogatePropertyInheritance.put(tag, false);
4180 }
4181
4182 public boolean hasAccessToItemAsPrimary() {
4183 String label = this.getEncryptionLabel();
4184 if (this.isSurrogate() || label == null || label.length() == 0) {
4185 return true;
4186 }
4187
4188 return Label.getLabel(label) == LabelResult.SuccessResolveLabelToKey;
4189 }
4190
4191
4192 /**
4193 * If when setting a property, we find that the primary has a undeciphered value, when we must continue using that undeciphered value
4194 * when eventually saving.
4195 * @return
4196 */
4197 protected boolean subjectToInheritanceCheckOnSave(String tag) {
4198 Item primary = getPrimary();
4199 if (primary == null) return false;
4200 EncryptionDetail primaryItemTagEncryptionDetail = primary.primaryPropertyEncryption.get(tag);
4201 Type primaryItemTagEncryptionDetailType = primaryItemTagEncryptionDetail.getEncryptionDetailType();
4202 return primaryItemTagEncryptionDetailType != EncryptionDetail.Type.UseUndecipheredValueOnSave;
4203 }
4204
4205 public boolean acceptsKeyboardEnter() {
4206 return _acceptsKeyboardEnter;
4207 }
4208
4209 public void setAcceptsEnter(boolean value) {
4210 if (this.getText() != null && this.getText().equals("Beep")) {
4211 System.err.println();
4212 }
4213 _acceptsKeyboardEnter = value;
4214 }
4215}
Note: See TracBrowser for help on using the repository browser.