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

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

New piping and functionality implementation to support the encrypting of images.

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