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

Last change on this file since 1509 was 1509, checked in by bnemhaus, 4 years ago

ItemEncryptionPermission is now respected.

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