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

src.gov.nasa.worldwind.render.AbstractAnnotationBalloon Maven / Gradle / Ivy

Go to download

World Wind is a collection of components that interactively display 3D geographic information within Java applications or applets.

There is a newer version: 2.0.0-986
Show 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.avlist.AVKey;

import java.awt.*;
import java.awt.geom.*;

/**
 * Implementation of balloon using {@link Annotation}.
 *
 * @author pabercrombie
 * @version $Id: AbstractAnnotationBalloon.java 1171 2013-02-11 21:45:02Z dcollins $
 */
public abstract class AbstractAnnotationBalloon extends AbstractBalloon
{
    /**
     * Create a new annotation balloon.
     *
     * @param text Balloon text. May not be null.
     */
    public AbstractAnnotationBalloon(String text)
    {
        super(text);
    }

    /** {@inheritDoc} */
    public Rectangle getBounds(DrawContext dc)
    {
        return this.getAnnotation().getBounds(dc);
    }

    /**
     * Create an annotation to render the balloon.
     *
     * @return The new annotation.
     */
    protected abstract Annotation createAnnotation();

    /**
     * Get the annotation used to render the balloon.
     *
     * @return The annotation that renders this balloon.
     */
    protected abstract Annotation getAnnotation();

    /**
     * Compute the annotation position, and set it in the annotation.
     *
     * @param dc Draw context.
     */
    protected abstract void computePosition(DrawContext dc);

    /** {@inheritDoc} */
    public void render(DrawContext dc)
    {
        if (!this.isVisible())
            return;

        this.determineActiveAttributes();
        this.applyAttributesToAnnotation();

        // Set position
        this.computePosition(dc);

        this.computeOffsets(dc);
        this.getAnnotation().render(dc);
    }

    /** Apply the balloon attributes to the annotation. */
    protected void applyAttributesToAnnotation()
    {
        Annotation annotation = this.getAnnotation();

        Object delegateOwner = this.getDelegateOwner();
        annotation.setDelegateOwner(delegateOwner != null ? delegateOwner : this);

        annotation.setAlwaysOnTop(this.isAlwaysOnTop());
        annotation.setPickEnabled(this.isPickEnabled());

        String text = this.getDecodedText();
        if (text != null)
            annotation.setText(text);

        annotation.setMinActiveAltitude(this.getMinActiveAltitude());
        annotation.setMaxActiveAltitude(this.getMaxActiveAltitude());

        AnnotationAttributes annotationAttrs = annotation.getAttributes();

        annotationAttrs.setHighlighted(this.isHighlighted());
        annotationAttrs.setVisible(this.isVisible());

        BalloonAttributes balloonAttrs = this.getActiveAttributes();

        if (balloonAttrs != null)
        {
            annotationAttrs.setTextColor(balloonAttrs.getTextColor());
            annotationAttrs.setBorderWidth(balloonAttrs.getOutlineWidth());
            annotationAttrs.setBorderStippleFactor(balloonAttrs.getOutlineStippleFactor());
            annotationAttrs.setBorderStipplePattern(balloonAttrs.getOutlineStipplePattern());
            annotationAttrs.setCornerRadius(balloonAttrs.getCornerRadius());
            annotationAttrs.setLeader(balloonAttrs.getLeaderShape());
            annotationAttrs.setLeaderGapWidth(balloonAttrs.getLeaderWidth());
            annotationAttrs.setFont(balloonAttrs.getFont());
            annotationAttrs.setFrameShape(balloonAttrs.getBalloonShape());
            annotationAttrs.setInsets(balloonAttrs.getInsets());

            // Configure the annotation to use the fixed size we compute and specify in computeOffsets(). Otherwise the
            // annotation adjusts its width and height to fit the text, and therefore won't always be the size we've
            // configured it to be.
            annotationAttrs.setAdjustWidthToText(AVKey.SIZE_FIXED);

            // Annotation attributes does not have an antialiasing enable/disable flag. Map the antialiasing flag to the
            // annotation attributes' antialias hint.
            annotationAttrs.setAntiAliasHint(
                balloonAttrs.isEnableAntialiasing() ? Annotation.ANTIALIAS_NICEST : Annotation.ANTIALIAS_FASTEST);

            annotationAttrs.setImageSource(balloonAttrs.getImageSource());
            annotationAttrs.setImageOffset(balloonAttrs.getImageOffset());
            annotationAttrs.setImageOpacity(balloonAttrs.getImageOpacity());
            annotationAttrs.setImageRepeat(balloonAttrs.getImageRepeat());
            annotationAttrs.setImageScale(balloonAttrs.getImageScale());

            // Annotation attributes does not have a separate interior opacity control, and do not have a flag to
            // disable drawing the interior. We use the annotation's background color to accomplish both by storing the
            // interior opacity in the background color alpha channel, and setting the background color to transparent
            // black if interior drawing is disabled.
            if (balloonAttrs.isDrawInterior() && balloonAttrs.getInteriorOpacity() > 0)
            {
                Color color = balloonAttrs.getInteriorMaterial().getDiffuse();
                double opacity = balloonAttrs.getInteriorOpacity();
                annotationAttrs.setBackgroundColor(new Color(color.getRed(), color.getGreen(), color.getBlue(),
                    (opacity < 1 ? (int) (opacity * 255 + 0.5) : 255)));
            }
            else
            {
                annotationAttrs.setBackgroundColor(new Color(0, 0, 0, 0));
            }

            // Annotation attributes does not have a separate outline opacity control, and do not have a flag to disable
            // drawing the outline. We use the annotation's background color to accomplish both by storing the outline
            // opacity in the border color alpha channel, and setting the border color to transparent black if outline
            // drawing is disabled.
            if (balloonAttrs.isDrawOutline() && balloonAttrs.getOutlineOpacity() > 0)
            {
                Color color = balloonAttrs.getOutlineMaterial().getDiffuse();
                double opacity = balloonAttrs.getOutlineOpacity();
                annotationAttrs.setBorderColor(new Color(color.getRed(), color.getGreen(), color.getBlue(),
                    (opacity < 1 ? (int) (opacity * 255 + 0.5) : 255)));
            }
            else
            {
                annotationAttrs.setBorderColor(new Color(0, 0, 0, 0));
            }
        }

        annotation.setAttributes(annotationAttrs);
    }

    /**
     * Compute the position and offsets, and set in them in the annotation.
     *
     * @param dc DrawContext in which the balloon is being rendered.
     */
    protected void computeOffsets(DrawContext dc)
    {
        Annotation annotation = this.getAnnotation();
        BalloonAttributes balloonAttrs = this.getActiveAttributes();
        AnnotationAttributes annotationAttrs = annotation.getAttributes();

        if (balloonAttrs != null)
        {
            // Compute the balloon's preferred size and the current screen viewport size.
            Dimension prefSize = annotation.getPreferredSize(dc);
            Rectangle viewport = dc.getView().getViewport();

            // Compute the balloon's current size on screen, and its offset in screen coordinates.
            Dimension screenSize = balloonAttrs.getSize().compute(prefSize.width, prefSize.height, viewport.width,
                viewport.height);
            Point2D.Double screenOffset = balloonAttrs.getOffset().computeOffset(screenSize.width, screenSize.height,
                1.0, 1.0);

            // Apply the computed balloon size and offset to the internal annotation's attributes. Adjust the screen
            // offset so that an offset of (0, 0) pixels maps to the annotation's lower left corner, and an offset of
            // (1, 1) fractions maps to the annotation's upper right corner. We do this to present a consistent meaning
            // for offset throughout the World Wind SDK. By default, annotation's offset is relative to it's bottom
            // center. We apply an additional offset of width/2 to compensate for this.
            annotationAttrs.setSize(screenSize);
            annotationAttrs.setDrawOffset(
                new Point((int) -screenOffset.x + screenSize.width / 2, (int) -screenOffset.y));
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy