uk.co.modularaudio.service.gui.impl.racktable.back.AbstractLinkImage.java Source code

Java tutorial

Introduction

Here is the source code for uk.co.modularaudio.service.gui.impl.racktable.back.AbstractLinkImage.java

Source

/**
 *
 * Copyright (C) 2015 - Daniel Hams, Modular Audio Limited
 *                      daniel.hams@gmail.com
 *
 * Mad is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Mad is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Mad.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

package uk.co.modularaudio.service.gui.impl.racktable.back;

import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.CubicCurve2D;
import java.awt.image.BufferedImage;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import uk.co.modularaudio.service.bufferedimageallocation.BufferedImageAllocationService;
import uk.co.modularaudio.util.bufferedimage.AllocationBufferType;
import uk.co.modularaudio.util.bufferedimage.AllocationLifetime;
import uk.co.modularaudio.util.bufferedimage.AllocationMatch;
import uk.co.modularaudio.util.bufferedimage.TiledBufferedImage;

public abstract class AbstractLinkImage {
    private static Log log = LogFactory.getLog(RackLinkImage.class.getName());

    private final String allocationSource;
    private final BufferedImageAllocationService bufferImageAllocationService;

    protected Rectangle rectangle = new Rectangle();
    protected BufferedImage bufferedImage;
    protected static final float WIRE_HIGHLIGHT_WIDTH = 3.0f;

    protected static final double WIRE_SHADOW_X_OFFSET = 2.0d;

    protected static final double WIRE_SHADOW_Y_OFFSET = 2.0d;

    protected static final double WIRE_HIGHLIGHT_X_OFFSET = -2.0d;

    protected static final double WIRE_HIGHLIGHT_Y_OFFSET = -2.0d;

    protected static final float WIRE_SHADOW_WIDTH = 3.0f;

    protected static final boolean DRAW_HIGHTLIGHT_AND_SHADOW = false;

    protected final static boolean DRAW_WIRE_BOUNDING_BOX = false;

    //   private static final float WIRE_STROKE_WIDTH = 8.0f;
    protected static final float WIRE_STROKE_WIDTH = 10.0f;

    protected static final int LINK_IMAGE_DIST_TO_CENTER = 10;

    protected static final int LINK_IMAGE_PADDING_FOR_WIRE_RADIUS = LINK_IMAGE_DIST_TO_CENTER * 2;

    protected static final int WIRE_DIP_PIXELS = 30;

    private TiledBufferedImage tiledBufferedImage;
    private final AllocationMatch allocationMatchToUse = new AllocationMatch();

    private static BasicStroke wireBodyStroke = new BasicStroke(WIRE_STROKE_WIDTH, BasicStroke.CAP_ROUND,
            BasicStroke.JOIN_ROUND);
    private static CompositeStroke wireStroke = new CompositeStroke(wireBodyStroke, new BasicStroke(2.0f));
    private static BasicStroke basicStrokeOfOne = new BasicStroke(1.0f);

    public AbstractLinkImage(final String allocationSource,
            final BufferedImageAllocationService bufferImageAllocationService, final Point sourcePoint,
            final Point sinkPoint) {
        this.allocationSource = allocationSource;
        this.bufferImageAllocationService = bufferImageAllocationService;
        if (sourcePoint != null && sinkPoint != null) {
            drawLinkWireIntoImage(sourcePoint, sinkPoint);
        }
    }

    private void drawLinkWireIntoImage(final Point sourcePoint, final Point sinkPoint) {
        //      log.debug("Drawing link from " + sourcePoint + " to " + sinkPoint);

        final int fromX = sourcePoint.x;
        final int fromY = sourcePoint.y;
        final int toX = sinkPoint.x;
        final int toY = sinkPoint.y;

        float f1, f2, f3, f4, f5, f6, f7, f8 = 0.0f;
        f1 = fromX;
        f2 = fromY;
        f3 = fromX;
        f4 = fromY + WIRE_DIP_PIXELS;
        f5 = toX;
        f6 = toY + WIRE_DIP_PIXELS;
        f7 = toX;
        f8 = toY;
        final CubicCurve2D cubicCurve = new CubicCurve2D.Float(f1, f2, f3, f4, f5, f6, f7, f8);
        final Rectangle cubicCurveBounds = cubicCurve.getBounds();

        final int imageWidthToUse = cubicCurveBounds.width + LINK_IMAGE_PADDING_FOR_WIRE_RADIUS;
        //      int imageHeightToUse = cubicCurveBounds.height + WIRE_DIP_PIXELS;
        int imageHeightToUse = cubicCurveBounds.height;
        // If the wire is close to vertical (little Y difference) we make the image a little bigger to account for the wire "dip"
        if (Math.abs(sinkPoint.y - sourcePoint.y) <= WIRE_DIP_PIXELS) {
            imageHeightToUse += (WIRE_DIP_PIXELS / 2);
        }

        //      bufferedImage = new BufferedImage( imageWidthToUse, imageHeightToUse, BufferedImage.TYPE_INT_ARGB );
        try {
            tiledBufferedImage = bufferImageAllocationService.allocateBufferedImage(allocationSource,
                    allocationMatchToUse, AllocationLifetime.SHORT, AllocationBufferType.TYPE_INT_ARGB,
                    imageWidthToUse, imageHeightToUse);

            bufferedImage = tiledBufferedImage.getUnderlyingBufferedImage();
            final Graphics2D g2d = bufferedImage.createGraphics();

            g2d.setComposite(AlphaComposite.Clear);
            g2d.fillRect(0, 0, imageWidthToUse, imageHeightToUse);

            g2d.setComposite(AlphaComposite.SrcOver);

            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

            f1 += LINK_IMAGE_DIST_TO_CENTER - cubicCurveBounds.x;
            f2 += LINK_IMAGE_DIST_TO_CENTER - cubicCurveBounds.y;
            f3 += LINK_IMAGE_DIST_TO_CENTER - cubicCurveBounds.x;
            f4 += LINK_IMAGE_DIST_TO_CENTER - cubicCurveBounds.y;
            f5 += LINK_IMAGE_DIST_TO_CENTER - cubicCurveBounds.x;
            f6 += LINK_IMAGE_DIST_TO_CENTER - cubicCurveBounds.y;
            f7 += LINK_IMAGE_DIST_TO_CENTER - cubicCurveBounds.x;
            f8 += LINK_IMAGE_DIST_TO_CENTER - cubicCurveBounds.y;

            final CubicCurve2D offSetCubicCurve = new CubicCurve2D.Float(f1, f2, f3, f4, f5, f6, f7, f8);

            // Draw the highlight and shadow
            if (DRAW_HIGHTLIGHT_AND_SHADOW) {
                final Graphics2D sG2d = (Graphics2D) g2d.create();
                sG2d.translate(WIRE_SHADOW_X_OFFSET, WIRE_SHADOW_Y_OFFSET);
                sG2d.setColor(Color.BLUE.darker());
                sG2d.setStroke(new BasicStroke(WIRE_SHADOW_WIDTH, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
                sG2d.draw(offSetCubicCurve);

                final Graphics2D hG2d = (Graphics2D) g2d.create();
                hG2d.translate(WIRE_HIGHLIGHT_X_OFFSET, WIRE_HIGHLIGHT_Y_OFFSET);
                hG2d.setColor(Color.WHITE);
                hG2d.setStroke(
                        new BasicStroke(WIRE_HIGHLIGHT_WIDTH, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
                hG2d.draw(offSetCubicCurve);
            }

            g2d.setColor(Color.BLACK);
            g2d.setStroke(wireStroke);
            g2d.draw(offSetCubicCurve);

            g2d.setColor(Color.BLUE);
            g2d.setStroke(wireBodyStroke);
            g2d.draw(offSetCubicCurve);

            // For debugging, draw a green line around the outside of this image.
            if (DRAW_WIRE_BOUNDING_BOX) {
                g2d.setStroke(basicStrokeOfOne);
                g2d.setColor(Color.GREEN);
                g2d.drawRect(0, 0, imageWidthToUse - 1, imageHeightToUse - 1);
            }

            rectangle.x = cubicCurveBounds.x - LINK_IMAGE_DIST_TO_CENTER;
            rectangle.y = cubicCurveBounds.y - LINK_IMAGE_DIST_TO_CENTER;
            rectangle.width = imageWidthToUse;
            rectangle.height = imageHeightToUse;
        } catch (final Exception e) {
            final String msg = "Exception caught allocating buffered image: " + e.toString();
            log.error(msg, e);
        }
    }

    public void redrawWireWithNewPoints(final Point sourcePoint, final Point sinkPoint) {
        try {
            if (tiledBufferedImage != null) {
                bufferImageAllocationService.freeBufferedImage(tiledBufferedImage);
            }
            drawLinkWireIntoImage(sourcePoint, sinkPoint);
        } catch (final Exception e) {
            final String msg = "Exception caught redrawing wire with new points: " + e.toString();
            log.error(msg, e);
        }
    }

    public Rectangle getRectangle() {
        return rectangle;
    }

    public BufferedImage getBufferedImage() {
        return bufferedImage;
    }

    public void destroy() {
        try {
            if (tiledBufferedImage != null) {
                bufferImageAllocationService.freeBufferedImage(tiledBufferedImage);
                tiledBufferedImage = null;
            }
        } catch (final Exception e) {
            final String msg = "Exception caught freeing buffered image: " + e.toString();
            log.error(msg, e);
        }
    }
}