net.rptools.tokentool.ui.TokenCompositionPanel.java Source code

Java tutorial

Introduction

Here is the source code for net.rptools.tokentool.ui.TokenCompositionPanel.java

Source

/* The MIT License
 * 
 * Copyright (c) 2005 David Rice, Trevor Croft
 * 
 * Permission is hereby granted, free of charge, to any person 
 * obtaining a copy of this software and associated documentation files 
 * (the "Software"), to deal in the Software without restriction, 
 * including without limitation the rights to use, copy, modify, merge, 
 * publish, distribute, sublicense, and/or sell copies of the Software, 
 * and to permit persons to whom the Software is furnished to do so, 
 * subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be 
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
 * SOFTWARE.
 */

package net.rptools.tokentool.ui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

import javax.swing.JPanel;

import org.apache.commons.io.FilenameUtils;

import net.rptools.lib.image.ImageUtil;
import net.rptools.lib.swing.PositionalLayout;
import net.rptools.lib.swing.SwingUtil;
import net.rptools.lib.transferable.FileTransferableHandler;
import net.rptools.lib.transferable.ImageTransferableHandler;
import net.rptools.tokentool.AppState;
import net.rptools.tokentool.TokenCompositor;
import net.rptools.tokentool.TokenTool;

public class TokenCompositionPanel extends JPanel
        implements DropTargetListener, MouseListener, MouseMotionListener, MouseWheelListener, KeyListener {

    private BufferedImage overlayImage;
    private BufferedImage tokenImage;

    private int tokenOffsetX;

    private int tokenOffsetY;

    private int dragStartX;

    private int dragStartY;

    private Rectangle overlayBounds;

    private double tokenScale;

    private BufferedImage composedOverlayImage;

    private ChangeObservable changeObservers;

    // AppActions.SAVE_TOKEN needs to know these values
    // so it can set the token metadata correctly.

    public int getTokenOffsetX() {
        return tokenOffsetX;
    }

    public int getTokenOffsetY() {
        return tokenOffsetY;
    }

    public int getOverlayWidth() {
        return (int) overlayBounds.getWidth();
    }

    public int getOverlayHeight() {
        return (int) overlayBounds.getHeight();
    }

    public TokenCompositionPanel() {
        setLayout(new PositionalLayout());
        setFocusable(true);

        // DnD
        new DropTarget(this, this);

        addMouseListener(this);
        addMouseMotionListener(this);
        addMouseWheelListener(this);
        addKeyListener(this);

        changeObservers = new ChangeObservable();
    }

    public void addChangeObserver(Observer observer) {
        changeObservers.addObserver(observer);
    }

    public void removeChangeObserver(Observer observer) {
        changeObservers.deleteObserver(observer);
    }

    private void paintOverlay(Graphics g, Dimension size) {
        if (composedOverlayImage == null) {
            composedOverlayImage = TokenCompositor.translateOverlay(overlayImage, 1);
            fireCompositionChanged();
        }
        if (composedOverlayImage != null) {
            int width = (Integer) TokenTool.getFrame().getControlPanel().getWidthSpinner().getValue();
            int height = (Integer) TokenTool.getFrame().getControlPanel().getHeightSpinner().getValue();
            int x = (size.width - width) / 2;
            int y = (size.height - height) / 2;

            if (overlayBounds != null) {
                if (overlayBounds.width != width || overlayBounds.height != height) {
                    fireCompositionChanged();
                }
            }

            g.drawImage(composedOverlayImage, x, y, width, height, this);

            overlayBounds = new Rectangle(x, y, width, height);
        }
    }

    @Override
    protected void paintComponent(Graphics g) {

        Dimension size = getSize();
        g.setColor(Color.black);
        g.fillRect(0, 0, size.width, size.height);

        int messageY = 15;
        int messageX = 5;

        // BASE
        if (AppState.compositionProperties.isBase()) {
            paintOverlay(g, size);
        }

        // TOKEN
        if (tokenImage != null) {
            int width = (int) (tokenImage.getWidth() * tokenScale);
            int height = (int) (tokenImage.getHeight() * tokenScale);
            g.drawImage(tokenImage, tokenOffsetX, tokenOffsetY, width, height, this);
        } else {
            g.setColor(Color.white);
            g.drawString("Drag an image onto this pane", messageX, messageY);
            messageY += 15;
        }

        if (!AppState.compositionProperties.isBase()) {
            paintOverlay(g, size);
        }
    }

    public void setToken(BufferedImage tokenImage) {
        this.tokenImage = tokenImage;
        tokenOffsetX = 0;
        tokenOffsetY = 0;

        tokenScale = 1;

        repaint();
        fireCompositionChanged();
    }

    public BufferedImage getBaseImage() {
        return tokenImage;
    }

    public void setOverlay(BufferedImage overlayImage) {
        this.overlayImage = overlayImage;
        composedOverlayImage = null;
        repaint();
        fireCompositionChanged();
    }

    public void zoomIn() {
        setScale(tokenScale + .01);
    }

    public void zoomInFast() {
        setScale(tokenScale + .1);
    }

    public void zoomOut() {
        setScale(tokenScale - .01);
    }

    public void zoomOutFast() {
        setScale(tokenScale - .1);
    }

    public void setScale(double scale) {

        if (scale * tokenImage.getWidth() < 10) {
            return;
        }

        tokenScale = scale;

        repaint();
        fireCompositionChanged();
    }

    public void fireCompositionChanged() {
        changeObservers.fireChangeEvent();
    }

    // //
    // KEY LISTENER
    public void keyTyped(KeyEvent e) {
    }

    public void keyPressed(KeyEvent e) {
    }

    public void keyReleased(KeyEvent e) {
        switch (e.getKeyCode()) {
        case java.awt.event.KeyEvent.VK_UP:
            tokenOffsetY += -1;
            repaint();
            fireCompositionChanged();
            break;
        case java.awt.event.KeyEvent.VK_DOWN:
            tokenOffsetY += 1;
            repaint();
            fireCompositionChanged();
            break;
        case java.awt.event.KeyEvent.VK_LEFT:
            tokenOffsetX += -1;
            repaint();
            fireCompositionChanged();
            break;
        case java.awt.event.KeyEvent.VK_RIGHT:
            tokenOffsetX += 1;
            repaint();
            fireCompositionChanged();
        }

    }

    // //
    // DROP TARGET LISTNER

    public void dragEnter(DropTargetDragEvent dtde) {
    }

    public void dragExit(DropTargetEvent dte) {
    }

    public void dragOver(DropTargetDragEvent dtde) {
    }

    public void drop(DropTargetDropEvent dtde) {

        Transferable transferable = dtde.getTransferable();
        dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);

        try {
            if (transferable != null && transferable.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
                List<URL> urls = new FileTransferableHandler().getTransferObject(transferable);

                for (URL url : urls) {
                    String baseName = java.net.URLDecoder.decode(FilenameUtils.getBaseName(url.getFile()), "UTF-8");
                    TokenTool.getFrame().getControlPanel().setNamePrefixField(baseName);
                }
            }
        } catch (UnsupportedFlavorException | IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        try {
            Image image = new ImageTransferableHandler().getTransferObject(transferable);
            if (!(image instanceof BufferedImage)) {
                // Convert to buffered image
                image = ImageUtil.createCompatibleImage(image);
            }

            setToken((BufferedImage) image);
        } catch (UnsupportedFlavorException ufe) {
            ufe.printStackTrace();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }

        fireCompositionChanged();
    }

    public void dropActionChanged(DropTargetDragEvent dtde) {
    }

    // //
    // MOUSE LISTENER
    public void mouseClicked(MouseEvent e) {
        requestFocus();
    }

    public void mouseEntered(MouseEvent e) {
    }

    public void mouseExited(MouseEvent e) {
    }

    public void mousePressed(MouseEvent e) {

        dragStartX = e.getX();
        dragStartY = e.getY();

    }

    public void mouseReleased(MouseEvent e) {
    }

    // //
    // MOUSE MOTION LISTENEr
    public void mouseDragged(MouseEvent e) {

        int dx = e.getX() - dragStartX;
        int dy = e.getY() - dragStartY;

        dragStartX = e.getX();
        dragStartY = e.getY();

        tokenOffsetX += dx;
        tokenOffsetY += dy;

        repaint();
        fireCompositionChanged();
    }

    public void mouseMoved(MouseEvent e) {
    }

    // //
    // Mouse Wheel
    public void mouseWheelMoved(MouseWheelEvent e) {

        if (tokenImage == null) {
            return;
        }

        double delta = SwingUtil.isControlDown(e) ? .1 : .01;

        double newScale = 0;
        if (e.getWheelRotation() > 0) {
            newScale = tokenScale - delta;
        } else {
            newScale = tokenScale + delta;
        }

        setScale(newScale);
    }

    public BufferedImage getComposedToken() {
        if (overlayBounds == null) {
            return null;
        }
        return TokenCompositor.composeToken(overlayImage, tokenImage, overlayBounds.x - tokenOffsetX,
                overlayBounds.y - tokenOffsetY, overlayBounds.width, overlayBounds.height, tokenScale,
                AppState.compositionProperties);

    }

    private static class ChangeObservable extends Observable {

        public void fireChangeEvent() {
            setChanged();
            notifyObservers();
        }
    }
}