/* Copyright (C) 2001, 2006 United States Government as represented by the Administrator of the National Aeronautics and Space Administration. All Rights Reserved. */ package gov.nasa.worldwind.layers; import gov.nasa.worldwind.render.*; import gov.nasa.worldwind.util.Logging; /** * The <code>IconLayer</code> class manages a collection of {@link gov.nasa.worldwind.render.WWIcon} objects * for rendering and picking. <code>IconLayer</code> delegates to its internal * {@link gov.nasa.worldwind.render.IconRenderer} for rendering and picking operations. * * @author tag * @version $Id: IconLayer.java 4049 2007-12-22 15:59:29Z dcollins $ * @see gov.nasa.worldwind.render.WWIcon * @see gov.nasa.worldwind.render.IconRenderer */ public class IconLayer extends AbstractLayer { private final java.util.Collection<WWIcon> icons = new java.util.concurrent.ConcurrentLinkedQueue<WWIcon>(); private Iterable<WWIcon> iconsOverride; private IconRenderer iconRenderer = new IconRenderer(); private Pedestal pedestal; /** * Creates a new <code>IconLayer</code> with an empty collection of Icons. */ public IconLayer() { } /** * Adds the specified <code>icon</code> to this layer's internal collection. * If this layer's internal collection has been overriden with a call to {@link #setIcons}, * this will throw an exception. * * @param icon Icon to add. * @throws IllegalArgumentException If <code>icon</code> is null. * @throws IllegalStateException If a custom Iterable has been specified by a call to <code>setIcons</code>. */ public void addIcon(WWIcon icon) { if (icon == null) { String msg = Logging.getMessage("nullValue.Icon"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } if (this.iconsOverride != null) { String msg = Logging.getMessage("generic.LayerIsUsingCustomIterable"); Logging.logger().severe(msg); throw new IllegalStateException(msg); } this.icons.add(icon); } /** * Adds the contents of the specified <code>icons</code> to this layer's internal collection. * If this layer's internal collection has been overriden with a call to {@link #setIcons}, * this will throw an exception. * * @param icons Icons to add. * @throws IllegalArgumentException If <code>icons</code> is null. * @throws IllegalStateException If a custom Iterable has been specified by a call to <code>setIcons</code>. */ public void addIcons(Iterable<WWIcon> icons) { if (icons == null) { String msg = Logging.getMessage("nullValue.IterableIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } if (this.iconsOverride != null) { String msg = Logging.getMessage("generic.LayerIsUsingCustomIterable"); Logging.logger().severe(msg); throw new IllegalStateException(msg); } for (WWIcon icon : icons) { // Internal list of icons does not accept null values. if (icon != null) this.icons.add(icon); } } /** * Removes the specified <code>icon</code> from this layer's internal collection, if it exists. * If this layer's internal collection has been overriden with a call to {@link #setIcons}, * this will throw an exception. * * @param icon Icon to remove. * @throws IllegalArgumentException If <code>icon</code> is null. * @throws IllegalStateException If a custom Iterable has been specified by a call to <code>setIcons</code>. */ public void removeIcon(WWIcon icon) { if (icon == null) { String msg = Logging.getMessage("nullValue.Icon"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } if (this.iconsOverride != null) { String msg = Logging.getMessage("generic.LayerIsUsingCustomIterable"); Logging.logger().severe(msg); throw new IllegalStateException(msg); } this.icons.remove(icon); } /** * Clears the contents of this layer's internal Icon collection. * If this layer's internal collection has been overriden with a call to {@link #setIcons}, * this will throw an exception. * * @throws IllegalStateException If a custom Iterable has been specified by a call to <code>setIcons</code>. */ public void removeAllIcons() { if (this.iconsOverride != null) { String msg = Logging.getMessage("generic.LayerIsUsingCustomIterable"); Logging.logger().severe(msg); throw new IllegalStateException(msg); } clearIcons(); } private void clearIcons() { if (this.icons != null && this.icons.size() > 0) this.icons.clear(); } /** * Returns the Iterable of Icons currently in use by this layer. * If the caller has specified a custom Iterable via {@link #setIcons}, this will returns a reference * to that Iterable. If the caller passed <code>setIcons</code> a null parameter, * or if <code>setIcons</code> has not been called, this returns a view of this layer's internal * collection of Icons. * * @return Iterable of currently active Icons. */ public Iterable<WWIcon> getIcons() { return getActiveIcons(); } /** * Returns the Iterable of currently active Icons. * If the caller has specified a custom Iterable via {@link #setIcons}, this will returns a reference * to that Iterable. If the caller passed <code>setIcons</code> a null parameter, * or if <code>setIcons</code> has not been called, this returns a view of this layer's internal * collection of Icons. * * @return Iterable of currently active Icons. */ private Iterable<WWIcon> getActiveIcons() { if (this.iconsOverride != null) { return this.iconsOverride; } else { // Return an unmodifiable reference to the internal list of icons. // This prevents callers from changing this list and invalidating any invariants we have established. return java.util.Collections.unmodifiableCollection(this.icons); } } /** * Overrides the collection of currently active Icons with the specified <code>iconIterable</code>. * This layer will maintain a reference to <code>iconIterable</code> strictly for picking and rendering. * This layer will not modify the Iterable reference. However, this will clear * the internal collection of Icons, and will prevent any modification to its contents via * <code>addIcon, addIcons, or removeIcons</code>. * * If the specified <code>iconIterable</code> is null, this layer will revert to maintaining its internal * collection. * * @param iconIterable Iterable to use instead of this layer's internal collection, or null to use this * layer's internal collection. */ public void setIcons(Iterable<WWIcon> iconIterable) { this.iconsOverride = iconIterable; // Clear the internal collection of Icons. clearIcons(); } /** * Returns the <code>Pedestal</code> used by this layers internal <code>IconRenderer</code>. * * @return <code>Pedestal</code> used by this layers internal <code>IconRenderer</code>. */ public Pedestal getPedestal() { return pedestal; } /** * Sets the <code>Pedestal</code> used by this layers internal <code>IconRenderer</code>. * * @param pedestal <code>Pedestal</code> to be used by this layers internal <code>IconRenderer</code>. */ public void setPedestal(Pedestal pedestal) { this.pedestal = pedestal; } @Override protected void doPick(DrawContext dc, java.awt.Point pickPoint) { this.iconRenderer.setPedestal(this.pedestal); this.iconRenderer.pick(dc, getActiveIcons(), pickPoint, this); } @Override protected void doRender(DrawContext dc) { this.iconRenderer.setPedestal(this.pedestal); this.iconRenderer.render(dc, getActiveIcons()); } @Override public String toString() { return Logging.getMessage("layers.IconLayer.Name"); } }