Package com.jcloisterzone.ui.grid

Source Code of com.jcloisterzone.ui.grid.GridPanel$MoveCenterAnimation

package com.jcloisterzone.ui.grid;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.AffineTransform;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;

import javax.swing.JPanel;
import javax.swing.event.MouseInputListener;

import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import com.jcloisterzone.Player;
import com.jcloisterzone.XmlUtils;
import com.jcloisterzone.board.Position;
import com.jcloisterzone.board.Tile;
import com.jcloisterzone.event.TileEvent;
import com.jcloisterzone.game.Snapshot;
import com.jcloisterzone.ui.Client;
import com.jcloisterzone.ui.animation.AnimationService;
import com.jcloisterzone.ui.animation.RecentPlacement;
import com.jcloisterzone.ui.controls.ChatPanel;
import com.jcloisterzone.ui.controls.ControlPanel;
import com.jcloisterzone.ui.controls.FakeComponent;
import com.jcloisterzone.ui.grid.layer.AbbeyPlacementLayer;
import com.jcloisterzone.ui.grid.layer.AbstractAreaLayer;
import com.jcloisterzone.ui.grid.layer.AbstractTilePlacementLayer;
import com.jcloisterzone.ui.grid.layer.TileActionLayer;
import com.jcloisterzone.ui.grid.layer.TileLayer;

public class GridPanel extends JPanel implements ForwardBackwardListener {

    private static final long serialVersionUID = -7013723613801929324L;

    public static int INITIAL_SQUARE_SIZE = 120;
    private static final int STARTING_GRID_SIZE = 3;

    private static final Color MESSAGE_ERROR = new Color(186, 61, 61, 245);
    private static final Color MESSAGE_HINT = new Color(147, 146, 155, 245);


    final Client client;
    final ControlPanel controlPanel;
    final ChatPanel chatPanel;

    private FakeComponent secondPanel;

    /** current board size */
    private int left, right, top, bottom;
    private int squareSize;

    //focus
    private int offsetX, offsetY;
    private double cx = 0.0, cy = 0.0;
    private MoveCenterAnimation moveAnimation;

    private List<GridLayer> layers = new ArrayList<GridLayer>();
    private String errorMessage;
    //private String hintMessage;

    public GridPanel(Client client, ControlPanel controlPanel, ChatPanel chatPanel, Snapshot snapshot) {
        setDoubleBuffered(true);
        setOpaque(false);
        setLayout(null);

        this.client = client;
        this.controlPanel = controlPanel;

        boolean networkGame = "true".equals(System.getProperty("forceChat"));
        for (Player p : client.getGame().getAllPlayers()) {
            if (!p.getSlot().isOwn()) {
                networkGame = true;
                break;
            }
        }
        this.chatPanel = networkGame ? chatPanel : null;

        squareSize = INITIAL_SQUARE_SIZE;
        left = 0 - STARTING_GRID_SIZE / 2;
        right = 0 + STARTING_GRID_SIZE / 2;
        top = 0 - STARTING_GRID_SIZE / 2;
        bottom = 0 + STARTING_GRID_SIZE / 2;

        if (snapshot != null) {
            NodeList nl = snapshot.getTileElements();
            for (int i = 0; i < nl.getLength(); i++) {
                Element el = (Element) nl.item(i);
                Position pos = XmlUtils.extractPosition(el);
                if (pos.x <= left) left = pos.x - 1;
                if (pos.x >= right) right = pos.x + 1;
                if (pos.y <= top) top = pos.y - 1;
                if (pos.y >= bottom) bottom = pos.y + 1;
            }
        }
        registerMouseListeners();
        controlPanel.registerSwingComponents(this);
        if (chatPanel != null) {
            this.add(chatPanel.getInput());
            this.add(chatPanel.getMessagesPane());
            chatPanel.setParent(this);
            chatPanel.layoutSwingComponents(this);
        }

        addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent e) {
                GridPanel.this.controlPanel.layoutSwingComponents(GridPanel.this);
                if (GridPanel.this.chatPanel != null) {
                    GridPanel.this.chatPanel.layoutSwingComponents(GridPanel.this);
                }
            }
        });
    }


    @Override
    public void forward() {
        if (secondPanel instanceof ForwardBackwardListener) {
            ((ForwardBackwardListener) secondPanel).forward();
        }
        controlPanel.getActionPanel().forward();
    }

    @Override
    public void backward() {
        if (secondPanel instanceof ForwardBackwardListener) {
            ((ForwardBackwardListener) secondPanel).backward();
        }
        controlPanel.getActionPanel().backward();
    }

    class GridPanelMouseListener extends MouseAdapter implements MouseInputListener {

        private MouseEvent dragSource;
        double sourceCx, sourceCy;

        @Override
        public void mouseClicked(MouseEvent e) {
            switch (e.getButton()) {
            case MouseEvent.BUTTON2:
                int clickX = e.getX()-offsetX;
                int clickY = e.getY()-offsetY;
                moveCenterToAnimated(clickX/(double)squareSize, clickY/(double)squareSize);
                break;
            case MouseEvent.BUTTON3:
            case 5:
                forward();
                break;
            case 4:
                backward();
                break;
            }
        }

        @Override
        public void mousePressed(MouseEvent e) {
            dragSource = e;
            sourceCx = cx;
            sourceCy = cy;
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            dragSource = null;
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            if (dragSource == null) return; //threading issues
            //px values
            int dx = e.getX() - dragSource.getX();
            int dy = e.getY() - dragSource.getY();
            //relative values
            double rdx = dx/(double)squareSize;
            double rdy = dy/(double)squareSize;

            moveCenterTo(sourceCx-rdx, sourceCy-rdy);
        }
    }

    private void registerMouseListeners() {
        DragInsensitiveMouseClickListener listener = new DragInsensitiveMouseClickListener(new GridPanelMouseListener());
        addMouseListener(listener);
        addMouseMotionListener(listener);
        addMouseWheelListener(new MouseWheelListener() {
            @Override
            public void mouseWheelMoved(MouseWheelEvent e) {
                zoom(-e.getWheelRotation());
            }
        });

        MouseAdapter childDelegation = new MouseAdapter() {
            private void dispatch(MouseEvent e) {
                if (secondPanel != null) {
                    secondPanel.dispatchMouseEvent(e);
                    if (e.isConsumed()) return;
                }
                controlPanel.dispatchMouseEvent(e);
            }
            public void mouseClicked(MouseEvent e) {
                dispatch(e);
            }
            public void mouseMoved(MouseEvent e) {
                dispatch(e);
            }
        };
        addMouseListener(childDelegation);
        addMouseMotionListener(childDelegation);

        addComponentListener(new ComponentListener() {
            @Override
            public void componentResized(ComponentEvent e) {
                controlPanel.componentResized(e);
                if (secondPanel != null) secondPanel.componentResized(e);
            }
            @Override
            public void componentMoved(ComponentEvent e) {
                controlPanel.componentMoved(e);
                if (secondPanel != null) secondPanel.componentMoved(e);
            }
            @Override
            public void componentShown(ComponentEvent e) {
                controlPanel.componentShown(e);
                if (secondPanel != null) secondPanel.componentShown(e);
            }
            @Override
            public void componentHidden(ComponentEvent e) {
                controlPanel.componentHidden(e);
                if (secondPanel != null) secondPanel.componentHidden(e);
            }
        });
    }

    public Tile getTile(Position p) {
        return client.getGame().getBoard().get(p);
    }

    public Client getClient() {
        return client;
    }

    public FakeComponent getSecondPanel() {
        return secondPanel;
    }

    public void setSecondPanel(FakeComponent secondPanel) {
        if (this.secondPanel != null && this.secondPanel != secondPanel) {
            //destroy previoud panel
            this.secondPanel.destroySwingComponents(this);
        }
        this.secondPanel = secondPanel;
    }

    public AnimationService getAnimationService() {
        return client.getMainPanel().getAnimationService();
    }

    public int getSquareSize() {
        return squareSize;
    }


    public int getOffsetX() {
        return offsetX;
    }

    public int getOffsetY() {
        return offsetY;
    }


    public String getErrorMessage() {
        return errorMessage;
    }


    public void setErrorMessage(String errorMessage) {
        this.errorMessage = errorMessage;
    }


//    public String getHintMessage() {
//        return hintMessage;
//    }
//
//
//    public void setHintMessage(String hintMessage) {
//        this.hintMessage = hintMessage;
//    }


    public void moveCenter(int xSteps, int ySteps) {
        //step should be 30px
        double dx = xSteps * 30.0f / getSquareSize();
        double dy = ySteps * 30.0f / getSquareSize();
        moveCenterTo(cx + dx, cy + dy);
    }

    public void moveCenterToAnimated(double cx, double cy) {
        if (moveAnimation != null) {
            moveAnimation.setCancel(true);
        }
        moveAnimation = new MoveCenterAnimation(cx, cy);
        moveAnimation.start();
    }

    private void moveCenterTo(double cx, double cy) {
        if (cx < left-0.5f) cx = left-0.5f;
        if (cx > right+0.5f) cx = right+0.5f;
        if (cy < top-0.5f) cy = top-0.5f;
        if (cy > bottom+0.5f) cy = bottom+0.5f;

        this.cx = cx;
        this.cy = cy;
        repaint();
    }

    public void zoom(double steps) {
        int size = (int) (squareSize * Math.pow(1.3, steps));
        if (size < 25) size = 25;
        if (size > 300) size = 300;
        setZoomSize(size);
    }

    private void setZoomSize(int size) {
        if (size == squareSize) return;
        squareSize = size;

        synchronized (layers) {
            for (GridLayer layer : layers) {
                layer.zoomChanged(squareSize);
            }
        }
        moveCenterTo(cx, cy); //re-check center constraints
    }


    void addLayer(GridLayer layer) {
       addLayer(layer, true);
    }

    void addLayer(GridLayer layer, boolean visible) {
        layers.add(layer);
        if (visible) {
            layer.onShow();
        }
    }

    public void showLayer(GridLayer layer) {
        layer.onShow();
        repaint();
    }

    public void showLayer(Class<? extends GridLayer> layerType) {
        for (GridLayer layer : layers) {
            if (layerType.isInstance(layer)) {
                layer.onShow();
            }
        }
        repaint();
    }

    public void hideLayer(GridLayer layer) {
        layer.onHide();
        repaint();
    }

    public void hideLayer(Class<? extends GridLayer> layerType) {
        for (GridLayer layer : layers) {
            if (layerType.isInstance(layer)) {
                layer.onHide();
            }
        }
        repaint();
    }

    @SuppressWarnings("unchecked")
    public <T extends GridLayer> T findLayer(Class<T> type) {
        for (GridLayer layer : layers) {
            if (type.isInstance(layer)) {
                return (T) layer;
            }
        }
        throw new NoSuchElementException("Layer " + type.toString() + " doesn't exist.");
    }

    public boolean isLayerVisible(Class<? extends GridLayer> type) {
        for (GridLayer layer : layers) {
            if (layer.isVisible() && type.isInstance(layer)) {
                return true;
            }
        }
        return false;
    }

    public void clearActionDecorations() {
        hideLayer(AbstractAreaLayer.class);
        hideLayer(TileActionLayer.class);
        hideLayer(AbbeyPlacementLayer.class);
    }

    // delegated UI methods

    public void tileEvent(TileEvent ev, TileLayer tileLayer) {
        Tile tile = ev.getTile();
        Position p = ev.getPosition();

        hideLayer(AbstractTilePlacementLayer.class);

        if (ev.getType() == TileEvent.PLACEMENT) {
            if (p.x == left) --left;
            if (p.x == right) ++right;
            if (p.y == top) --top;
            if (p.y == bottom) ++bottom;

            tileLayer.tilePlaced(tile);

            boolean initialPlacement = ev.getTriggeringPlayer() == null;//if triggering player is null we are placing initial tiles
            if ((!initialPlacement && !ev.getTriggeringPlayer().isLocalHuman()) ||
                (initialPlacement && tile.equals(client.getGame().getCurrentTile()))) {
                getAnimationService().registerAnimation(new RecentPlacement(tile.getPosition()));
            }
        } else if (ev.getType() == TileEvent.REMOVE) {
            tileLayer.tileRemoved(tile);
        }
        repaint();
    }

    private int calculateCenterX() {
        return (getWidth() - ControlPanel.PANEL_WIDTH - squareSize)/2;
    }

    private int calculateCenterY() {
        return (getHeight() - squareSize)/2;
    }

//    //TODO remove profile code
//    long ts, last;
//    public void profile(String msg) {
//        long now = System.currentTimeMillis();
//        System.out.println((now-ts) + " (" + (now-last) +") : " + msg);
//        last = now;
//    }

//    private void paintGrid(Graphics2D g2) {
//        g2.setColor(UIManager.getColor("Panel.background"));
//        g2.fillRect(left*squareSize, top*squareSize, (right+2)*squareSize-1, (bottom+2)*squareSize-1);
//        g2.setColor(Color.LIGHT_GRAY);
//        for (int i = left; i <= right; i++) {
//            g2.drawLine(i*squareSize, top*squareSize, i*squareSize, (bottom+1)*squareSize);
//            g2.drawLine((i+1)*squareSize-1, top*squareSize, (i+1)*squareSize-1, (bottom+1)*squareSize);
//        }
//        for (int i = top; i <= bottom; i++) {
//            g2.drawLine(left*squareSize, i*squareSize, (right+1)*squareSize, i*squareSize);
//            g2.drawLine(left*squareSize, (i+1)*squareSize-1, (right+1)*squareSize, (i+1)*squareSize-1);
//        }

//        profile("grid");
//    }

    @Override
    protected void paintChildren(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;

        //System.err.println("GP " + g2.getTransform());

//        System.out.println("------------------------");
//        ts = last = System.currentTimeMillis();

        int w = getWidth(), h = getHeight();
//        int w = getWidth(), h = getHeight();
//        if (blurBuffer == null || blurBuffer.getWidth() != w || blurBuffer.getHeight() != h) {
//            blurBuffer = UiUtils.newTransparentImage(w, h);
//        }
//        Graphics2D g2 = blurBuffer.createGraphics();
//        g2.setBackground(TRANSPARENT_COLOR);
//        g2.clearRect(0, 0, w, h);

        AffineTransform origTransform = g2.getTransform();
        offsetX = calculateCenterX() - (int)(cx * squareSize);
        offsetY = calculateCenterY() - (int)(cy * squareSize);
        g2.translate(offsetX, offsetY);
        g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        //paintGrid(g2);

        //paint layers

        for (GridLayer layer : layers) {
            if (layer.isVisible()) {
                layer.paint(g2);
            }
//          profile(layer.getClass().getSimpleName());
        }


        g2.setTransform(origTransform);
        g2.translate(w - ControlPanel.PANEL_WIDTH, 0);

        controlPanel.paintComponent(g2);

        int innerWidth;
        if (secondPanel != null) {
            g2.translate(-secondPanel.getWidth()-60, 0);
            secondPanel.paintComponent(g2);
            innerWidth = (int) g2.getTransform().getTranslateX();
        } else {
            innerWidth = (int) g2.getTransform().getTranslateX() - ControlPanel.LEFT_PADDING - ControlPanel.PANEL_SHADOW_WIDTH;
        }
        g2.setTransform(origTransform);

        if (chatPanel != null) {
            chatPanel.paintComponent(g2);
        }

        paintMessages(g2, innerWidth);
        super.paintChildren(g);
    }

    private void paintMessages(Graphics2D g2, int innerWidth) {
        int y = 0;
//        if (hintMessage != null) {
//            g2.setColor(MESSAGE_HINT);
//            g2.fillRect(0, y, innerWidth, 36);
//            g2.setFont(new Font(null, Font.PLAIN, 16));
//            g2.setColor(Color.WHITE);
//            g2.drawString(hintMessage, 30, y+23);
//            y += 42;
//        }
        if (errorMessage != null) {
            g2.setColor(MESSAGE_ERROR);
            g2.fillRect(0, y, innerWidth, 36);
            g2.setFont(new Font(null, Font.PLAIN, 16));
            g2.setColor(Color.WHITE);
            g2.drawString(errorMessage, 30, y+23);
            y += 42;
        }

    }

    class MoveCenterAnimation extends Thread {
        //TODO easing ?

        private double toCx, toCy, fromCx, fromCy;
        long start, end;
        private boolean cancel;

        public MoveCenterAnimation(double toCx, double toCy) {
            moveTo(toCx, toCy);
        }

        private void moveTo(double toCx, double toCy) {
            this.toCx = toCx;
            this.toCy = toCy;
            fromCx = cx;
            fromCy = cy;
            start = System.currentTimeMillis();
            end = start + 100;
        }

        public void setCancel(boolean cancel) {
            this.cancel = cancel;
        }

        @Override
        public void run() {
            long t;
            while (!cancel && (t = System.currentTimeMillis()) < end) {
                double dx = (double)(t - start)/(end-start)*(toCx-fromCx);
                double dy = (double)(t - start)/(end-start)*(toCy-fromCy);
                moveCenterTo(fromCx+dx, fromCy+dy);
                try {
                    Thread.sleep(15);
                } catch (InterruptedException e) {
                }
            }
            if (!cancel) {
                moveCenterTo(toCx, toCy);
            }
        }

    }

}
TOP

Related Classes of com.jcloisterzone.ui.grid.GridPanel$MoveCenterAnimation

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.