All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gov.nasa.worldwind.render.AnnotationAttributes Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2012 United States Government as represented by the Administrator of the
 * National Aeronautics and Space Administration.
 * All Rights Reserved.
 */
package gov.nasa.worldwind.render;

import gov.nasa.worldwind.Restorable;
import gov.nasa.worldwind.avlist.AVKey;
import gov.nasa.worldwind.util.*;

import java.awt.*;
import java.util.*;

/**
 * {@link Annotation} attributes set. All {@link AbstractAnnotation} objects start life referencing a new instance of
 * this object. 

This class also defines a static default attributes bundle containing default values for all * attributes. New AnnotationAttributes refer this static bundle as their default values source when an * attribute has not been set.

New AnnotationAttributes set have all their attributes pointing to * the default values until they are set by the application. Most attributes refer to the default value by using minus * one (-1) for numerics and null for objects.

The default attributes set can be * changed for a non static one under the application control. The process can be extended or cascaded to handle * multiple levels of inheritance for default attributes.

* * @author Patrick Murris * @version $Id: AnnotationAttributes.java 1171 2013-02-11 21:45:02Z dcollins $ * @see AbstractAnnotation * @see MultiLineTextRenderer */ public class AnnotationAttributes implements Restorable { private static final AnnotationAttributes defaults = new AnnotationAttributes(); static { defaults.setFrameShape(AVKey.SHAPE_RECTANGLE); defaults.setSize(new Dimension(160, 0)); defaults.setScale(1); defaults.setOpacity(1); defaults.setLeader(AVKey.SHAPE_TRIANGLE); defaults.setLeaderGapWidth(40); defaults.setCornerRadius(20); defaults.setAdjustWidthToText(AVKey.SIZE_FIT_TEXT); defaults.setDrawOffset(new Point(40, 60)); defaults.setHighlightScale(1.2); defaults.setInsets(new Insets(20, 15, 15, 15)); defaults.setFont(Font.decode("Arial-PLAIN-12")); defaults.setTextAlign(AVKey.LEFT); defaults.setTextColor(Color.BLACK); defaults.setBackgroundColor(Color.WHITE); defaults.setBorderColor(new Color(171, 171, 171)); defaults.setBorderWidth(1); defaults.setBorderStippleFactor(0); defaults.setBorderStipplePattern((short) 0xAAAA); defaults.setAntiAliasHint(Annotation.ANTIALIAS_NICEST); defaults.setImageScale(1); defaults.setImageOffset(new Point(0, 0)); defaults.setImageOpacity(1); defaults.setImageRepeat(AVKey.REPEAT_XY); defaults.setDistanceMinScale(1); defaults.setDistanceMaxScale(1); defaults.setDistanceMinOpacity(.3); defaults.setEffect(AVKey.TEXT_EFFECT_NONE); } private AnnotationAttributes defaultAttributes = defaults; private String frameShape; // Use default (null) private Dimension size; // Use default (null) private double scale = -1; // Use default (-1) private double opacity = -1; // Use default (-1) private String leader; // Use default (null) private int leaderGapWidth = -1; // Use default (-1) private int cornerRadius = -1; // Use default (-1) private String adjustWidthToText; // Use default (null) private Point drawOffset; // Use default (null) private boolean isHighlighted = false; private boolean isVisible = true; private double highlightScale = -1; // Use default (-1) private Font font; // Use default (null) private String textAlign; // Use default (null) private Color textColor; // Use default (null) private Color backgroundColor; // Use default (null) private Color borderColor; // Use default (null) private double borderWidth = -1; // Use default (-1) private int borderStippleFactor = -1; // Use default (-1) private short borderStipplePattern = (short) 0x0000; // Use default (zero) private int antiAliasHint = -1; // Use default (-1) private Insets insets; // Use default (null) private WWTexture backgroundTexture; private WWTexture previousBackgroundTexture; private double imageScale = -1; // Use default (-1) private Point imageOffset; // Use default (null) private double imageOpacity = -1; // Use default (-1) private String imageRepeat; // Use default (null) private double distanceMinScale = -1; // Use default (-1) private double distanceMaxScale = -1; // Use default (-1) private double distanceMinOpacity = -1; // Use default (-1) private String effect; // Use default (null) protected boolean unresolved; //** Public properties ********************************************************************** /** * Set the fallback default attributes set. * * @param attr the default attributes set. */ public void setDefaults(AnnotationAttributes attr) { if (attr == null) { String message = Logging.getMessage("nullValue.AnnotationAttributesIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } this.defaultAttributes = attr; } /** * Get the callout frame shape. Can be one of AVKey.SHAPE_RECTANGLE (default), * AVKey.SHAPE_ELLIPSE or AVKey.SHAPE_NONE. * * @return the callout frame shape. */ public String getFrameShape() { return this.frameShape != null ? this.frameShape : defaultAttributes.getFrameShape(); } /** * Set the callout frame shape. Can be one of AVKey.SHAPE_RECTANGLE (default), * AVKey.SHAPE_ELLIPSE or AVKey.SHAPE_NONE. Set to null to use the default * shape.

Note that AVKey.SHAPE_ELLIPSE draws an ellipse inside the callout bounding * rectangle set by its size (see setSize()) or its text bounding rectangle (see setAdjustWidthToText() and * setSize() with height set to zero). It is often necessary to have larger Insets dimensions (see setInsets()) to * avoid having the text drawn outside the shape border.

* * @param shape the callout frame shape. */ public void setFrameShape(String shape) { this.frameShape = shape; } /** * Get whether the Annotation is highlighted and should be drawn bigger - see setHighlightScale(). * * @return true if highlighted. */ public boolean isHighlighted() { return isHighlighted; } /** * Set whether the Annotation is highlighted and should be drawn bigger - see setHighlightScale(). * * @param highlighted true if highlighted. */ public void setHighlighted(boolean highlighted) { isHighlighted = highlighted; } /** * Get the scaling factor applied to highlighted Annotations. * * @return the scaling factor applied to highlighted Annotations. */ public double getHighlightScale() { return highlightScale > 0 ? this.highlightScale : defaultAttributes.getHighlightScale(); } /** * Set the scaling factor applied to highlighted Annotations. Set to minus one (-1) to use * the default value. * * @param highlightScale the scaling factor applied to highlighted Annotations. */ public void setHighlightScale(double highlightScale) { this.highlightScale = highlightScale; } /** * Get the annotation callout preferred total dimension in pixels. * * @return the callout preferred total dimension in pixels. */ public Dimension getSize() { return this.size != null ? this.size : defaultAttributes.getSize(); } /** * Set the annotation callout preferred total dimension in pixels.

If necessary, the text will be wrapped into * several lines so as not to exceed the callout preferred width (minus the Insets * left and right dimensions - see {@link #setInsets(java.awt.Insets) setInsets}). * However, if {@link #setAdjustWidthToText(String) setAdjustWidthToText} is set to AVKey.SIZE_FIT_TEXT, the final * callout width will follow that of the final text bounding rectangle.

If necessary, the text will also be * truncated so as not to exceed the given height. A zero value (default) will have * the callout follow the final text bounding rectangle height (including the Insets top * and bottom).

Set to null to use the default size. * * @param size the callout preferred total dimension in pixels. */ public void setSize(Dimension size) { this.size = size; } /** * Get the scaling factor applied to the annotation. Default is 1. * * @return the scaling factor applied to the annotation */ public double getScale() { return this.scale >= 0 ? this.scale : defaultAttributes.getScale(); } /** * Set the scaling factor to apply to the annotation. Default is 1. Set to minus one (-1) to use the * default value. * * @param scale the scaling factor to apply to the annotation */ public void setScale(double scale) { this.scale = scale; } /** * Get the opacity factor applied to the annotation. Default is 1. * * @return the opacity factor applied to the annotation */ public double getOpacity() { return this.opacity >= 0 ? this.opacity : defaultAttributes.getOpacity(); } /** * Set the opacity factor to apply to the annotation. Default is 1. Set to minus one (-1) to use the * default value. * * @param opacity the opacity factor to apply to the annotation */ public void setOpacity(double opacity) { this.opacity = opacity; } /** * Get the callout shape leader type. Can be one of AVKey.SHAPE_TRIANGLE (default) or * AVKey.SHAPE_NONE. * * @return the callout shape leader type. */ public String getLeader() { return this.leader != null ? this.leader : defaultAttributes.getLeader(); } /** * Set the callout shape leader type. Can be one of AVKey.SHAPE_TRIANGLE (default) or * AVKey.SHAPE_NONE. * * @param leader the callout shape leader type. */ public void setLeader(String leader) { this.leader = leader; } /** * Get the callout shape leader gap width in pixels. Default is 40. * * @return the callout shape leader gap width. */ public int getLeaderGapWidth() { return this.leaderGapWidth >= 0 ? this.leaderGapWidth : defaultAttributes.getLeaderGapWidth(); } /** * Set the callout shape leader gap width in pixels. Set this attribute to minus one (-1) to use the * default value. * * @param width the callout shape leader gap width in pixels. */ public void setLeaderGapWidth(int width) { this.leaderGapWidth = width; } /** * Get the callout shape rounded corners radius in pixels. A value of zero means no rounded corners. * * @return the callout shape rounded corners radius in pixels. */ public int getCornerRadius() { return this.cornerRadius >= 0 ? this.cornerRadius : defaultAttributes.getCornerRadius(); } /** * Set the callout shape rounded corners radius in pixels. A value of zero means no rounded corners. * Set this attribute to minus one (-1) to use the default value. * * @param radius the callout shape rounded corners radius in pixels. */ public void setCornerRadius(int radius) { this.cornerRadius = radius; } /** * Get whether the callout width should adjust to follow the wrapped text bounding rectangle width, which may be * smaller or larger then the preferred size depending on the text. Can be one of {@link AVKey#SIZE_FIXED} or {@link * AVKey#SIZE_FIT_TEXT}. * * @return whether the callout width is adjusted to follow the text bounding rectangle width. */ public String getAdjustWidthToText() { return this.adjustWidthToText != null ? this.adjustWidthToText : defaultAttributes.getAdjustWidthToText(); } /** * Set whether the callout width should adjust to follow the wrapped text bounding rectangle width which may be * smaller or larger then the preferred size depending on the text. Can be one of {@link AVKey#SIZE_FIXED} (default) * or {@link AVKey#SIZE_FIT_TEXT}. Setting this attribute to SIZE_FIT_TEXT would have the callout drawn * at its exact width (see setSize()). * * @param state whether the callout width should adjust to follow the text bounding rectangle width. */ public void setAdjustWidthToText(String state) { this.adjustWidthToText = state; } /** * Get the callout displacement offset in pixels from the globe Position or screen point at which it is associated. * When the callout has a leader (see setLeader(String leader)), it will lead to the original point. In the actual * implementation, the callout is drawn above its associated point and the leader connects at the bottom of the * frame, in the middle. Positive X increases toward the right and positive Y in the up direction. * * @return the callout displacement offset in pixels */ public Point getDrawOffset() { return this.drawOffset != null ? this.drawOffset : defaultAttributes.getDrawOffset(); } /** * Set the callout displacement offset in pixels from the globe Position or screen point at which it is associated. * When the callout has a leader (see setLeader(String leader)), it will lead to the original point. In the actual * implementation, the callout is drawn above its associated point and the leader connects at the bottom of the * frame, in the middle. Positive X increases toward the right and positive Y in the up direction. Set to * null to use the default offset. * * @param offset the callout displacement offset in pixels */ public void setDrawOffset(Point offset) { this.drawOffset = offset; } /** * Get the callout Insets dimensions in pixels. The text is drawn inside the callout frame while * keeping a distance from the callout border defined in the Insets. * * @return the callout Insets dimensions in pixels. */ public Insets getInsets() { return this.insets != null ? this.insets : defaultAttributes.getInsets(); } /** * Set the callout Insets dimensions in pixels. The text will be drawn inside the callout frame while * keeping a distance from the callout border defined in the Insets. Set to null to use the default * Insets. * * @param insets the callout Insets dimensions in pixels. */ public void setInsets(Insets insets) { this.insets = insets; } /** * Get the callout border line width. A value of zero means no border is being drawn. * * @return the callout border line width. */ public double getBorderWidth() { return this.borderWidth >= 0 ? this.borderWidth : defaultAttributes.getBorderWidth(); } /** * Set the callout border line width. A value of zero means no border will is drawn. Set to minus one * (-1) to use the default value. * * @param width the callout border line width. */ public void setBorderWidth(double width) { this.borderWidth = width; } /** * Get the stipple factor used for the callout border line. A value of zero (default) means no pattern * is applied. * * @return the stipple factor used for the callout border line. */ public int getBorderStippleFactor() { return this.borderStippleFactor >= 0 ? this.borderStippleFactor : defaultAttributes.getBorderStippleFactor(); } /** * Set the stipple factor used for the callout border line. A value of zero (default) means no pattern * will be applied. Set to minus one (-1) to use the default value. * * @param factor the stipple factor used for the callout border line. */ public void setBorderStippleFactor(int factor) { this.borderStippleFactor = factor; } /** * Get the stipple pattern used for the callout border line. * * @return the stipple pattern used for the callout border line. */ public short getBorderStipplePattern() { return this.borderStipplePattern != 0x0000 ? this.borderStipplePattern : defaultAttributes.getBorderStipplePattern(); } /** * Set the stipple pattern used for the callout border line. Set to 0x0000 to use the default value. * * @param pattern the stipple pattern used for the callout border line. */ public void setBorderStipplePattern(short pattern) { this.borderStipplePattern = pattern; } /** * Get the GL antialias hint used for rendering the callout border line. Can be one of {@link * Annotation}.ANTIALIAS_DONT_CARE, ANTIALIAS_FASTEST (default) or ANTIALIAS_NICEST. * * @return the GL antialias hint used for rendering the callout border line. */ protected int getAntiAliasHint() { return this.antiAliasHint >= 0 ? this.antiAliasHint : defaultAttributes.getAntiAliasHint(); } /** * Set the GL antialias hint used for rendering the callout border line. Can be one of {@link * Annotation}.ANTIALIAS_DONT_CARE, ANTIALIAS_FASTEST (default) or ANTIALIAS_NICEST. Set to minus one * (-1) to use the default value. * * @param hint the GL antialias hint used for rendering the callout border line. */ protected void setAntiAliasHint(int hint) { this.antiAliasHint = hint; } /** * Get whether the annotation is visible and should be rendered. * * @return true if the annotation is visible and should be rendered. */ public boolean isVisible() { return isVisible; } /** * Set whether the annotation is visible and should be rendered. * * @param visible true if the annotation is visible and should be rendered. */ public void setVisible(boolean visible) { isVisible = visible; } /** * Get the Font used for text rendering. * * @return the Font used for text rendering. */ public Font getFont() { return this.font != null ? this.font : defaultAttributes.getFont(); } /** * Set the Font used for text rendering. Set to null to use the default value. * * @param font the Font used for text rendering. */ public void setFont(Font font) { this.font = font; } /** * Get the text alignement. Can be one of {@link AVKey#LEFT} (default), {@link AVKey#CENTER} or {@link * AVKey#RIGHT}. * * @return align the text alignement. Can be one of MultiLineTextRenderer.ALIGN_LEFT, ALIGN_CENTER or ALIGN_RIGHT. */ public String getTextAlign() { return this.textAlign != null ? this.textAlign : defaultAttributes.getTextAlign(); } /** * Set the text alignement. Can be one of {@link AVKey#LEFT} (default), {@link AVKey#CENTER} or {@link AVKey#RIGHT}. * Set to null to use the default value. * * @param align the text alignement. */ public void setTextAlign(String align) { this.textAlign = align; } /** * Get the text Color. * * @return the text Color. */ public Color getTextColor() { return this.textColor != null ? this.textColor : defaultAttributes.getTextColor(); } /** * Set the text Color. Set to null to use the default value. * * @param color the text Color. */ public void setTextColor(Color color) { this.textColor = color; } /** * Get the callout background Color. * * @return the callout background Color. */ public Color getBackgroundColor() { return this.backgroundColor != null ? this.backgroundColor : defaultAttributes.getBackgroundColor(); } /** * Set the callout background Color. Set to null to use the default value. * * @param color the callout background Color. */ public void setBackgroundColor(Color color) { this.backgroundColor = color; } /** * Get the callout border Color. * * @return the callout border Color. */ public Color getBorderColor() { return this.borderColor != null ? this.borderColor : defaultAttributes.getBorderColor(); } /** * Set the callout border Color. Set to null to use the default value. * * @param color the callout border Color. */ public void setBorderColor(Color color) { this.borderColor = color; } /** * Get the background image source. Can be a String providing the path to a local image, a {@link * java.awt.image.BufferedImage} or null. * * @return the background image source. */ public Object getImageSource() { return (this.backgroundTexture != null) ? this.backgroundTexture.getImageSource() : null; } /** * Set the background image source. Can be a String providing the path to a local image or a {@link * java.awt.image.BufferedImage}. Set to null for no background image rendering. * * @param imageSource the background image source. */ public void setImageSource(Object imageSource) { this.previousBackgroundTexture = this.backgroundTexture; this.backgroundTexture = null; if (imageSource != null) { this.backgroundTexture = new BasicWWTexture(imageSource, true); } } /** * Get the background image as a {@link WWTexture} for the specified draw context. This returns null if the * background image source returned by {@link #getImageSource()} is null. * * @param dc the current draw context. * * @return the background image as a WWTexture, or null if this AnnotationAttributes has no background image * source. */ public WWTexture getBackgroundTexture(DrawContext dc) { if (this.previousBackgroundTexture != null) { dc.getTextureCache().remove(this.previousBackgroundTexture.getImageSource()); this.previousBackgroundTexture = null; } return this.backgroundTexture; } /** * Get the background image scaling factor. * * @return the background image scaling factor. */ public double getImageScale() { return this.imageScale >= 0 ? this.imageScale : defaultAttributes.getImageScale(); } /** * Set the background image scaling factor. Set to minus one (-1) to use the default value. * * @param scale the background image scaling factor. */ public void setImageScale(double scale) { this.imageScale = scale; } /** * Get the background image offset in pixels (before background scaling). * * @return the background image offset in pixels */ public Point getImageOffset() { return this.imageOffset != null ? this.imageOffset : defaultAttributes.getImageOffset(); } /** * Set the background image offset in pixels (before background scaling). Set to null to use the * default value. * * @param offset the background image offset in pixels */ public void setImageOffset(Point offset) { this.imageOffset = offset; } /** * Get the opacity of the background image (0 to 1). * * @return the opacity of the background image (0 to 1). */ public double getImageOpacity() { return this.imageOpacity >= 0 ? this.imageOpacity : defaultAttributes.getImageOpacity(); } /** * Set the opacity of the background image (0 to 1). Set to minus one (-1) to use the default value. * * @param opacity the opacity of the background image (0 to 1). */ public void setImageOpacity(double opacity) { this.imageOpacity = opacity; } /** * Get the repeat behavior or the background image. Can be one of {@link Annotation}.IMAGE_REPEAT_X, IMAGE_REPEAT_Y, * IMAGE_REPEAT_XY (default) or IMAGE_REPEAT_NONE. * * @return the repeat behavior or the background image. */ public String getImageRepeat() { return this.imageRepeat != null ? this.imageRepeat : defaultAttributes.getImageRepeat(); } /** * Set the repeat behavior or the background image. Can be one of {@link Annotation}.IMAGE_REPEAT_X, IMAGE_REPEAT_Y, * IMAGE_REPEAT_XY (default) or IMAGE_REPEAT_NONE. Set to null to use the default value. * * @param repeat the repeat behavior or the background image. */ public void setImageRepeat(String repeat) { this.imageRepeat = repeat; } /** * Get the path to the image used for background image. Returns null if the image source is null or a * memory BufferedImage. * * @return the path to the image used for background image. */ public String getPath() { Object imageSource = this.getImageSource(); return (imageSource instanceof String) ? (String) imageSource : null; } /** * Get the minimum scale that can be applied to an annotation when it gets farther away from the eye than the view * lookat point. * * @return the minimum scale that can be applied to an annotation when it gets away from the eye */ public double getDistanceMinScale() { return this.distanceMinScale >= 0 ? this.distanceMinScale : defaultAttributes.getDistanceMinScale(); } /** * Set the minimum scale that can be applied to an annotation when it gets farther away from the eye than the view * lookat point. Set to minus one (-1) to use the default value. * * @param scale the minimum scale that can be applied to an annotation when it gets away from the eye */ public void setDistanceMinScale(double scale) { this.distanceMinScale = scale; } /** * Get the maximum scale that can be applied to an annotation when it gets closer to the eye than the view lookat * point. * * @return the maximum scale that can be applied to an annotation when it gets closer to the eye */ public double getDistanceMaxScale() { return this.distanceMaxScale >= 0 ? this.distanceMaxScale : defaultAttributes.getDistanceMaxScale(); } /** * Set the maximum scale that can be applied to an annotation when it gets closer to the eye than the view lookat * point. Set to minus one (-1) to use the default value. * * @param scale the maximum scale that can be applied to an annotation when it gets closer to the eye */ public void setDistanceMaxScale(double scale) { this.distanceMaxScale = scale; } /** * Get the minimum opacity an annotation can have when fading away from the eye (0 to 1). * * @return the minimum opacity an annotation can have when fading away from the eye. */ public double getDistanceMinOpacity() { return this.distanceMinOpacity >= 0 ? this.distanceMinOpacity : defaultAttributes.getDistanceMinOpacity(); } /** * Set the minimum opacity an annotation can have when fading away from the eye (0 to 1). Set to minus one * (-1) to use the default value. * * @param opacity the minimum opacity an annotation can have when fading away from the eye. */ public void setDistanceMinOpacity(double opacity) { this.distanceMinOpacity = opacity; } /** * Get the effect used to decorate the text. Can be one of {@link AVKey#TEXT_EFFECT_SHADOW}, {@link * AVKey#TEXT_EFFECT_OUTLINE} or {@link AVKey#TEXT_EFFECT_NONE} (default). * * @return the effect used for text rendering */ public String getEffect() { return this.effect != null ? this.effect : defaultAttributes.getEffect(); } /** * Set the effect used to decorate the text. Can be one of {@link AVKey#TEXT_EFFECT_SHADOW}, {@link * AVKey#TEXT_EFFECT_OUTLINE} or {@link AVKey#TEXT_EFFECT_NONE} (default). Set to null to use the * default value. * * @param effect the effect to use for text rendering */ public void setEffect(String effect) { this.effect = effect; } /** * Indicates whether one or more members of this remain unresolved because they must be retrieved from an * external source. * * @return true if there are unresolved fields, false if no fields remain unresolved. */ public boolean isUnresolved() { return unresolved; } /** * Specifies whether one or more fields of this remain unresolved because they must be retrieved from an * external source. * * @param unresolved true if there are unresolved fields, false if no fields remain unresolved. */ public void setUnresolved(boolean unresolved) { this.unresolved = unresolved; } /** * Returns an XML state document String describing attributes that have been set by the application (attributes not * pointing to their default value). * * @return XML state document string describing this AnnotationAttributes. */ public String getRestorableState() { RestorableSupport restorableSupport = RestorableSupport.newRestorableSupport(); // Creating a new RestorableSupport failed. RestorableSupport logged the problem, so just return null. if (restorableSupport == null) return null; // Save application set attributes to the document root. saveAttributes(this, restorableSupport, null); // We only save this AnnotationAttributes' defaultAttributes when the application has set them to // something other than the static member "defaults". if (this.defaultAttributes != AnnotationAttributes.defaults) { RestorableSupport.StateObject defaultAttributesStateObj = restorableSupport.addStateObject("defaultAttributes"); saveAttributes(this.defaultAttributes, restorableSupport, defaultAttributesStateObj); } return restorableSupport.getStateAsXml(); } /** * Restores attribute values found in the specified XML state document String. The document specified by * stateInXml must be a well formed XML document String, or this will throw an * IllegalArgumentException. Unknown structures in stateInXml are benign, because they will simply be * ignored. * * @param stateInXml an XML document String describing an AnnotationAttributes. * * @throws IllegalArgumentException If stateInXml is null, or if stateInXml is not a well * formed XML document String. */ public void restoreState(String stateInXml) { if (stateInXml == null) { String message = Logging.getMessage("nullValue.StringIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } RestorableSupport restorableSupport; try { restorableSupport = RestorableSupport.parse(stateInXml); } catch (Exception e) { // Parsing the document specified by stateInXml failed. String message = Logging.getMessage("generic.ExceptionAttemptingToParseStateXml", stateInXml); Logging.logger().severe(message); throw new IllegalArgumentException(message, e); } // Restore application set attributes from under the document root. restoreAttributes(restorableSupport, null, this); // Restore application set default attributes from under the "defaultAttributes" state element. RestorableSupport.StateObject defaultAttributesStateObj = restorableSupport.getStateObject("defaultAttributes"); if (defaultAttributesStateObj != null) { AnnotationAttributes newDefaultAttributes = this.defaultAttributes; // We do not want to write to the static member "defaults". So if this AnnotationAttributes' does not // have it's own defaultAttributes instance, we create one for it if (newDefaultAttributes == AnnotationAttributes.defaults) newDefaultAttributes = new AnnotationAttributes(); restoreAttributes(restorableSupport, defaultAttributesStateObj, newDefaultAttributes); setDefaults(newDefaultAttributes); } } /** * Save the attributes specified by source in the specified restorableSupport. Only * attributes that have been set by the application (attributes not pointing to their default value) will be saved. * If context is not null, attributes will be saved beneath it. Otherwise, they will be saved at the * document root. * * @param source the AnnotationAttriubutes to save. * @param restorableSupport RestorableSupport to write attribute values to. * @param context RestorableSupport.StateObject that attributes will be saved under, if not null. * * @throws IllegalArgumentException If either source or restorableSupport is null. */ private static void saveAttributes(AnnotationAttributes source, RestorableSupport restorableSupport, RestorableSupport.StateObject context) { if (source == null || restorableSupport == null) throw new IllegalArgumentException(); if (source.frameShape != null) restorableSupport.addStateValueAsString(context, "frameShape", source.frameShape); restorableSupport.addStateValueAsBoolean(context, "highlighted", source.isHighlighted); if (source.highlightScale >= 0) restorableSupport.addStateValueAsDouble(context, "highlightScale", source.highlightScale); if (source.size != null) { RestorableSupport.StateObject sizeStateObj = restorableSupport.addStateObject(context, "size"); if (sizeStateObj != null) { restorableSupport.addStateValueAsDouble(sizeStateObj, "width", source.size.getWidth()); restorableSupport.addStateValueAsDouble(sizeStateObj, "height", source.size.getHeight()); } } if (source.scale >= 0) restorableSupport.addStateValueAsDouble(context, "scale", source.scale); if (source.opacity >= 0) restorableSupport.addStateValueAsDouble(context, "opacity", source.opacity); if (source.leader != null) restorableSupport.addStateValueAsString(context, "leader", source.leader); if (source.leaderGapWidth >= 0) restorableSupport.addStateValueAsInteger(context, "leaderGapWidth", source.leaderGapWidth); if (source.cornerRadius >= 0) restorableSupport.addStateValueAsInteger(context, "cornerRadius", source.cornerRadius); if (source.adjustWidthToText != null) restorableSupport.addStateValueAsString(context, "adjustWidthToText", source.adjustWidthToText); if (source.drawOffset != null) { RestorableSupport.StateObject drawOffsetStateObj = restorableSupport.addStateObject(context, "drawOffset"); if (drawOffsetStateObj != null) { restorableSupport.addStateValueAsDouble(drawOffsetStateObj, "x", source.drawOffset.getX()); restorableSupport.addStateValueAsDouble(drawOffsetStateObj, "y", source.drawOffset.getY()); } } if (source.insets != null) { RestorableSupport.StateObject insetsStateObj = restorableSupport.addStateObject(context, "insets"); if (insetsStateObj != null) { restorableSupport.addStateValueAsInteger(insetsStateObj, "top", source.insets.top); restorableSupport.addStateValueAsInteger(insetsStateObj, "left", source.insets.left); restorableSupport.addStateValueAsInteger(insetsStateObj, "bottom", source.insets.bottom); restorableSupport.addStateValueAsInteger(insetsStateObj, "right", source.insets.right); } } if (source.borderWidth >= 0) restorableSupport.addStateValueAsDouble(context, "borderWidth", source.borderWidth); if (source.borderStippleFactor >= 0) restorableSupport.addStateValueAsInteger(context, "borderStippleFactor", source.borderStippleFactor); if (source.borderStipplePattern != (short) 0x0000) restorableSupport.addStateValueAsInteger(context, "borderStipplePattern", source.borderStipplePattern); if (source.antiAliasHint >= 0) restorableSupport.addStateValueAsInteger(context, "antiAliasHint", source.antiAliasHint); restorableSupport.addStateValueAsBoolean(context, "visible", source.isVisible); // Save the name, style, and size of the font. These will be used to restore the font using the // constructor: new Font(name, style, size). if (source.font != null) { RestorableSupport.StateObject fontStateObj = restorableSupport.addStateObject(context, "font"); if (fontStateObj != null) { restorableSupport.addStateValueAsString(fontStateObj, "name", source.font.getName()); restorableSupport.addStateValueAsInteger(fontStateObj, "style", source.font.getStyle()); restorableSupport.addStateValueAsInteger(fontStateObj, "size", source.font.getSize()); } } if (source.textAlign != null) restorableSupport.addStateValueAsString(context, "textAlign", source.textAlign); if (source.textColor != null) { String encodedColor = RestorableSupport.encodeColor(source.textColor); if (encodedColor != null) restorableSupport.addStateValueAsString(context, "textColor", encodedColor); } if (source.backgroundColor != null) { String encodedColor = RestorableSupport.encodeColor(source.backgroundColor); if (encodedColor != null) restorableSupport.addStateValueAsString(context, "backgroundColor", encodedColor); } if (source.borderColor != null) { String encodedColor = RestorableSupport.encodeColor(source.borderColor); if (encodedColor != null) restorableSupport.addStateValueAsString(context, "borderColor", encodedColor); } // Save the imagePath property only when the imageSource property is a simple String path. If the imageSource // property is a BufferedImage (or some other object), we make no effort to save that state. We save under // the name "imagePath" to denote that it is a special case of "imageSource". if (source.getPath() != null) restorableSupport.addStateValueAsString(context, "imagePath", source.getPath(), true); if (source.imageScale >= 0) restorableSupport.addStateValueAsDouble(context, "imageScale", source.imageScale); if (source.imageOffset != null) { RestorableSupport.StateObject imageOffsetStateObj = restorableSupport.addStateObject(context, "imageOffset"); if (imageOffsetStateObj != null) { restorableSupport.addStateValueAsDouble(imageOffsetStateObj, "x", source.imageOffset.getX()); restorableSupport.addStateValueAsDouble(imageOffsetStateObj, "y", source.imageOffset.getY()); } } if (source.imageOpacity >= 0) restorableSupport.addStateValueAsDouble(context, "imageOpacity", source.imageOpacity); if (source.imageRepeat != null) restorableSupport.addStateValueAsString(context, "imageRepeat", source.imageRepeat); if (source.distanceMinScale >= 0) restorableSupport.addStateValueAsDouble(context, "distanceMinScale", source.distanceMinScale); if (source.distanceMaxScale >= 0) restorableSupport.addStateValueAsDouble(context, "distanceMaxScale", source.distanceMaxScale); if (source.distanceMinOpacity >= 0) restorableSupport.addStateValueAsDouble(context, "distanceMinOpacity", source.distanceMinOpacity); if (source.effect != null) restorableSupport.addStateValueAsString(context, "effect", source.effect); } /** * Restores the any attributes appearing in the specified restorableSupport. If context is * not null, this will search for attributes beneath it. Otherwise, this will search for attributes beneath the * document root. * * @param restorableSupport RestorableSupport to read attribute values from. * @param context RestorableSupport.StateObject under which attributes will be looked, if not null. * @param dest the AnnotationAttributes to restore. * * @throws IllegalArgumentException If either restorableSupport or dest is null. */ private static void restoreAttributes(RestorableSupport restorableSupport, RestorableSupport.StateObject context, AnnotationAttributes dest) { // Map legacy versions of the Annotation constants and FrameFactory constants to the new AVKey constants. Map legacySupport = new HashMap(); legacySupport.put("render.Annotation.RepeatNone", AVKey.REPEAT_NONE); legacySupport.put("render.Annotation.RepeatX", AVKey.REPEAT_X); legacySupport.put("render.Annotation.RepeatY", AVKey.REPEAT_Y); legacySupport.put("render.Annotation.RepeatXY", AVKey.REPEAT_XY); legacySupport.put("render.Annotation.SizeFixed", AVKey.SIZE_FIXED); legacySupport.put("render.Annotation.SizeFitText", AVKey.SIZE_FIT_TEXT); legacySupport.put("Render.FrameFactory.ShapeRectangle", AVKey.SHAPE_RECTANGLE); legacySupport.put("Render.FrameFactory.ShapeEllipse", AVKey.SHAPE_ELLIPSE); legacySupport.put("Render.FrameFactory.ShapeNone", AVKey.SHAPE_NONE); legacySupport.put("Render.FrameFactory.LeaderTriangle", AVKey.SHAPE_TRIANGLE); legacySupport.put("Render.FrameFactory.LeaderNone", AVKey.SHAPE_NONE); if (restorableSupport == null || dest == null) throw new IllegalArgumentException(); String frameShapeState = restorableSupport.getStateValueAsString(context, "frameShape"); if (frameShapeState != null) { // Map legacy versions using FrameFactory frame shape constants to the new AVKey constants. String updatedValue = legacySupport.get(frameShapeState); if (updatedValue != null) frameShapeState = updatedValue; dest.setFrameShape(frameShapeState); } Boolean highlightedState = restorableSupport.getStateValueAsBoolean(context, "highlighted"); if (highlightedState != null) dest.setHighlighted(highlightedState); Double highlightScaleState = restorableSupport.getStateValueAsDouble(context, "highlightScale"); if (highlightScaleState != null) dest.setHighlightScale(highlightScaleState); // Restore the size property only if all parts are available. // We will not restore a partial size (for example, just the width). RestorableSupport.StateObject sizeStateObj = restorableSupport.getStateObject(context, "size"); if (sizeStateObj != null) { Double widthState = restorableSupport.getStateValueAsDouble(sizeStateObj, "width"); Double heightState = restorableSupport.getStateValueAsDouble(sizeStateObj, "height"); if (widthState != null && heightState != null) dest.setSize(new Dimension(widthState.intValue(), heightState.intValue())); } Double scaleState = restorableSupport.getStateValueAsDouble(context, "scale"); if (scaleState != null) dest.setScale(scaleState); Double opacityState = restorableSupport.getStateValueAsDouble(context, "opacity"); if (opacityState != null) dest.setOpacity(opacityState); String leaderState = restorableSupport.getStateValueAsString(context, "leader"); if (leaderState != null) { // Map legacy versions using FrameFactory leader shape constants to the new AVKey constants. String updatedValue = legacySupport.get(leaderState); if (updatedValue != null) leaderState = updatedValue; dest.setLeader(leaderState); } Integer leaderGapWidthState = restorableSupport.getStateValueAsInteger(context, "leaderGapWidth"); if (leaderGapWidthState != null) dest.setLeaderGapWidth(leaderGapWidthState); Integer cornerRadiusState = restorableSupport.getStateValueAsInteger(context, "cornerRadius"); if (cornerRadiusState != null) dest.setCornerRadius(cornerRadiusState); String adjustWidthToTextState = restorableSupport.getStateValueAsString(context, "adjustWidthToText"); if (adjustWidthToTextState != null) { // Map legacy versions using Annotation size constants to the new AVKey constants. String updatedValue = legacySupport.get(adjustWidthToTextState); if (updatedValue != null) adjustWidthToTextState = updatedValue; dest.setAdjustWidthToText(adjustWidthToTextState); } // Restore the drawOffset property only if all parts are available. // We will not restore a partial drawOffset (for example, just the x value). RestorableSupport.StateObject drawOffsetStateObj = restorableSupport.getStateObject(context, "drawOffset"); if (drawOffsetStateObj != null) { Double xState = restorableSupport.getStateValueAsDouble(drawOffsetStateObj, "x"); Double yState = restorableSupport.getStateValueAsDouble(drawOffsetStateObj, "y"); if (xState != null && yState != null) dest.setDrawOffset(new Point(xState.intValue(), yState.intValue())); } // Restore the insets property only if all parts are available. // We will not restore a partial insets (for example, just the top value). RestorableSupport.StateObject insetsStateObj = restorableSupport.getStateObject(context, "insets"); if (insetsStateObj != null) { Integer topState = restorableSupport.getStateValueAsInteger(insetsStateObj, "top"); Integer leftState = restorableSupport.getStateValueAsInteger(insetsStateObj, "left"); Integer bottomState = restorableSupport.getStateValueAsInteger(insetsStateObj, "bottom"); Integer rightState = restorableSupport.getStateValueAsInteger(insetsStateObj, "right"); if (topState != null && leftState != null && bottomState != null && rightState != null) dest.setInsets(new Insets(topState, leftState, bottomState, rightState)); } Double borderWidthState = restorableSupport.getStateValueAsDouble(context, "borderWidth"); if (borderWidthState != null) dest.setBorderWidth(borderWidthState); Integer borderStippleFactorState = restorableSupport.getStateValueAsInteger(context, "borderStippleFactor"); if (borderStippleFactorState != null) dest.setBorderStippleFactor(borderStippleFactorState); Integer borderStipplePatternState = restorableSupport.getStateValueAsInteger(context, "borderStipplePattern"); if (borderStipplePatternState != null) dest.setBorderStipplePattern(borderStipplePatternState.shortValue()); Integer antiAliasHintState = restorableSupport.getStateValueAsInteger(context, "antiAliasHint"); if (antiAliasHintState != null) dest.setAntiAliasHint(antiAliasHintState); Boolean visibleState = restorableSupport.getStateValueAsBoolean(context, "visible"); if (visibleState != null) dest.setVisible(visibleState); // Restore the font property only if all parts are available. // We will not restore a partial font (for example, just the size). RestorableSupport.StateObject fontStateObj = restorableSupport.getStateObject(context, "font"); if (fontStateObj != null) { // The "font name" of toolTipFont. String nameState = restorableSupport.getStateValueAsString(fontStateObj, "name"); // The style attributes. Integer styleState = restorableSupport.getStateValueAsInteger(fontStateObj, "style"); // The simple font size. Integer sizeState = restorableSupport.getStateValueAsInteger(fontStateObj, "size"); if (nameState != null && styleState != null && sizeState != null) dest.setFont(new Font(nameState, styleState, sizeState)); } String textAlignState = restorableSupport.getStateValueAsString(context, "textAlign"); if (textAlignState != null) { // Attempt to convert the textAlign string to an integer to handle legacy textAlign restorable state. // WWUtil.makeInteger returns null without logging a message if the string cannot be converted to an int. Integer textAlignInt = WWUtil.makeInteger(textAlignState); if (textAlignInt != null) { dest.setTextAlign(textAlignInt == 0 ? AVKey.LEFT : (textAlignInt == 1 ? AVKey.CENTER : AVKey.RIGHT)); } else { dest.setTextAlign(textAlignState); } } String textColorState = restorableSupport.getStateValueAsString(context, "textColor"); if (textColorState != null) { Color color = RestorableSupport.decodeColor(textColorState); if (color != null) dest.setTextColor(color); } String backgroundColorState = restorableSupport.getStateValueAsString(context, "backgroundColor"); if (backgroundColorState != null) { Color color = RestorableSupport.decodeColor(backgroundColorState); if (color != null) dest.setBackgroundColor(color); } String borderColorState = restorableSupport.getStateValueAsString(context, "borderColor"); if (borderColorState != null) { Color color = RestorableSupport.decodeColor(borderColorState); if (color != null) dest.setBorderColor(color); } // The imagePath property should exist only if the imageSource property was a simple String path. // If the imageSource property was a BufferedImage (or some other object), it should not exist in the // state document. We save under the name "imagePath" to denote that it is a special case of "imageSource". String imagePathState = restorableSupport.getStateValueAsString(context, "imagePath"); if (imagePathState != null) dest.setImageSource(imagePathState); Double imageScaleState = restorableSupport.getStateValueAsDouble(context, "imageScale"); if (imageScaleState != null) dest.setImageScale(imageScaleState); // Restore the imageOffset property only if all parts are available. // We will not restore a partial imageOffset (for example, just the x value). RestorableSupport.StateObject imageOffsetStateObj = restorableSupport.getStateObject(context, "imageOffset"); if (imageOffsetStateObj != null) { Double xState = restorableSupport.getStateValueAsDouble(imageOffsetStateObj, "x"); Double yState = restorableSupport.getStateValueAsDouble(imageOffsetStateObj, "y"); if (xState != null && yState != null) dest.setImageOffset(new Point(xState.intValue(), yState.intValue())); } Double imageOpacityState = restorableSupport.getStateValueAsDouble(context, "imageOpacity"); if (imageOpacityState != null) dest.setImageOpacity(imageOpacityState); String imageRepeatState = restorableSupport.getStateValueAsString(context, "imageRepeat"); if (imageRepeatState != null) { // Map legacy versions using Annotation repeat constants to the new AVKey constants. String updatedValue = legacySupport.get(imageRepeatState); if (updatedValue != null) imageRepeatState = updatedValue; dest.setImageRepeat(imageRepeatState); } Double distanceMinScaleState = restorableSupport.getStateValueAsDouble(context, "distanceMinScale"); if (distanceMinScaleState != null) dest.setDistanceMinScale(distanceMinScaleState); Double distanceMaxScaleState = restorableSupport.getStateValueAsDouble(context, "distanceMaxScale"); if (distanceMaxScaleState != null) dest.setDistanceMaxScale(distanceMaxScaleState); Double distanceMinOpacityState = restorableSupport.getStateValueAsDouble(context, "distanceMinOpacity"); if (distanceMinOpacityState != null) dest.setDistanceMinOpacity(distanceMinOpacityState); String effectState = restorableSupport.getStateValueAsString(context, "effect"); if (effectState != null) dest.setEffect(effectState); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy