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

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

Created a unioned list for item properties in DefaultFrameWriter. Used it in Item.

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