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

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

Renamed Frame.getItems() to Frame.getSortedItems() to better represent its functionality.

-> org.apollo.ApolloGestureActions
-> org.apollo.ApolloSystem
-> org.expeditee.actions.Actions
-> org.expeditee.actions.Debug
-> org.expeditee.actions.ExploratorySearchActions
-> org.expeditee.actions.JfxBrowserActions
-> org.expeditee.actions.Misc
-> org.expeditee.actions.Navigation
-> org.expeditee.actions.ScriptBase
-> org.expeditee.actions.Simple
-> org.expeditee.agents.ComputeTree
-> org.expeditee.agents.CopyTree
-> org.expeditee.agents.DisplayComet
-> org.expeditee.agents.DisplayTree
-> org.expeditee.agents.DisplayTreeLeaves
-> org.expeditee.agents.GraphFramesetLinks
-> org.expeditee.agents.TreeProcessor
-> org.expeditee.gio.gesture.StandardGestureActions
-> org.expeditee.gui.DisplayController
-> org.expeditee.gui.FrameCreator
-> org.expeditee.gui.FrameIO
-> org.expeditee.io.DefaultTreeWriter
-> org.expeditee.io.JavaWriter
-> org.expeditee.io.PDF2Writer
-> org.expeditee.io.TXTWriter
-> org.expeditee.io.WebParser
-> org.expeditee.io.flowlayout.XGroupItem
-> org.expeditee.items.Dot
-> org.expeditee.items.Item
-> org.expeditee.items.ItemUtils
-> org.expeditee.network.FrameShare
-> org.expeditee.stats.TreeStats


Created ItemsList class to wrap ArrayList<Item>. Frames now use this new class to store its body list (used for display) as well as its primaryBody and surrogateBody.

-> org.expeditee.agents.Format
-> org.expeditee.agents.HFormat
-> org.expeditee.gio.gesture.StandardGestureActions
-> org.expeditee.gui.Frame
-> org.expeditee.gui.FrameUtils


Refactorted Frame.setResort(bool) to Frame.invalidateSorted() to better function how it is intended to with a more accurate name.

-> org.expeditee.agents.Sort


When writing out .exp files and getting attributes to respond to LEFT + RIGHT click, boolean items are by default true. This has always been the case. An ammendment to this is that defaults can now be established.
Also added 'EnterClick' functionality. If cursored over a item with this property and you press enter, it acts as if you have clicked on it instead.

-> org.expeditee.assets.resources-public.framesets.authentication.1.exp to 6.exp
-> org.expeditee.gio.gesture.StandardGestureActions
-> org.expeditee.gio.input.KBMInputEvent
-> org.expeditee.gio.javafx.JavaFXConversions
-> org.expeditee.gio.swing.SwingConversions
-> org.expeditee.gui.AttributeUtils
-> org.expeditee.io.Conversion
-> org.expeditee.io.DefaultFrameWriter
-> org.expeditee.items.Item


Fixed a bug caused by calling Math.abs on Integer.MIN_VALUE returning unexpected result. Due to zero being a thing, you cannot represent Math.abs(Integer.MIN_VALUE) in a Integer object. The solution is to use Integer.MIN_VALUE + 1 instead of Integer.MIN_VALUE.

-> org.expeditee.core.bounds.CombinationBounds
-> org.expeditee.io.flowlayout.DimensionExtent


Recoded the contains function in EllipticalBounds so that intersection tests containing circles work correctly.

-> org.expeditee.core.bounds.EllipticalBounds


Added toString() to PolygonBounds to allow for useful printing during debugging.

-> org.expeditee.core.bounds.PolygonBounds

Implemented Surrogate Mode!

-> org.expeditee.encryption.io.EncryptedExpReader
-> org.expeditee.encryption.io.EncryptedExpWriter
-> org.expeditee.encryption.items.surrogates.EncryptionDetail
-> org.expeditee.encryption.items.surrogates.Label
-> org.expeditee.gui.FrameUtils
-> org.expeditee.gui.ItemsList
-> org.expeditee.items.Item
-> org.expeditee.items.Text


???? Use Integer.MAX_VALUE cast to a float instead of Float.MAX_VALUE. This fixed some bug which I cannot remember.

-> org.expeditee.gio.TextLayoutManager
-> org.expeditee.gio.swing.SwingTextLayoutManager


Improved solution for dealing with the F10 key taking focus away from Expeditee due to it being a assessibility key.

-> org.expeditee.gio.swing.SwingInputManager


Renamed variable visibleItems in FrameGraphics.paintFrame to itemsToPaintCanditates to better represent functional intent.

-> org.expeditee.gui.FrameGraphics


Improved checking for if personal resources exist before recreating them

-> org.expeditee.gui.FrameIO


Repeated messages to message bay now have a visual feedback instead of just a beep. This visual feedback is in the form of a count of the amount of times it has repeated.

-> org.expeditee.gui.MessageBay


Updated comment on the Vector class to explain what vectors are.

-> org.expeditee.gui.Vector


Added constants to represent all of the property keys in DefaultFrameReader and DefaultFrameWriter.

-> org.expeditee.io.DefaultFrameReader
-> org.expeditee.io.DefaultFrameWriter


Updated the KeyList setting to be more heirarcial with how users will store their Secrets.

-> org.expeditee.settings.identity.secrets.KeyList

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