Package com.jcloisterzone.ui.controls

Source Code of com.jcloisterzone.ui.controls.PlayerPanel

package com.jcloisterzone.ui.controls;

import static com.jcloisterzone.ui.I18nUtils._;
import static com.jcloisterzone.ui.controls.ControlPanel.CORNER_DIAMETER;
import static com.jcloisterzone.ui.controls.ControlPanel.PANEL_WIDTH;
import static com.jcloisterzone.ui.controls.ControlPanel.PLAYER_BG_COLOR;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.swing.JOptionPane;

import com.google.common.collect.Iterables;
import com.jcloisterzone.LittleBuilding;
import com.jcloisterzone.Player;
import com.jcloisterzone.TradeResource;
import com.jcloisterzone.figure.Follower;
import com.jcloisterzone.figure.SmallFollower;
import com.jcloisterzone.figure.Special;
import com.jcloisterzone.figure.predicate.MeeplePredicates;
import com.jcloisterzone.game.Game;
import com.jcloisterzone.game.PlayerSlot.SlotState;
import com.jcloisterzone.game.capability.AbbeyCapability;
import com.jcloisterzone.game.capability.BridgeCapability;
import com.jcloisterzone.game.capability.CastleCapability;
import com.jcloisterzone.game.capability.ClothWineGrainCapability;
import com.jcloisterzone.game.capability.KingAndRobberBaronCapability;
import com.jcloisterzone.game.capability.LittleBuildingsCapability;
import com.jcloisterzone.game.capability.TowerCapability;
import com.jcloisterzone.ui.Client;
import com.jcloisterzone.ui.UiUtils;

public class PlayerPanel extends FakeComponent implements RegionMouseListener {

    private static final Color DELIM_TOP_COLOR = new Color(250,250,250);
    private static final Color DELIM_BOTTOM_COLOR = new Color(220,220,220);
    private static final Color KING_ROBBER_OVERLAY = new Color(0f,0f,0f,0.4f);
    //private static final Color ACTIVE_TOWER_BG = new Color(255, 255, 70);

    private static Font FONT_POINTS = new Font("Georgia", Font.BOLD, 30);
    private static Font FONT_MEEPLE = new Font("Georgia", Font.BOLD, 18);
    private static Font FONT_KING_ROBBER_OVERLAY = new Font("Georgia", Font.BOLD, 22);
    private static Font FONT_NICKNAME = new Font(null, Font.BOLD, 18);

    private static final int PADDING_L = 9;
    private static final int PADDING_R = 11;
    private static final int LINE_HEIGHT = 32;
    private static final int DELIMITER_Y = 34;

    private final Game game;
    private final Player player;
    private Color color, fontColor;

    private final PlayerPanelImageCache cache;

    private int centerY;

    //paint context variables
    private Graphics2D g2;
    private int bx, by;

    private String mouseOverKey = null;

    public PlayerPanel(Client client, Game game, Player player, PlayerPanelImageCache cache) {
        super(client);
        this.player = player;
        this.game = game;
        this.cache = cache;
        this.color = player.getColors().getMeepleColor();
        this.fontColor = player.getColors().getFontColor();
    }

    private void drawDelimiter(int y) {
        g2.setColor(DELIM_TOP_COLOR);
        g2.drawLine(PADDING_L, y, PANEL_WIDTH /*-PADDING_R*/, y);
        g2.setColor(DELIM_BOTTOM_COLOR);
        g2.drawLine(PADDING_L, y+1, PANEL_WIDTH /*-PADDING_R*/, y+1);
    }

    private void drawTextShadow(String text, int x, int y) {
        //TODO shadow color based on color ??
        /*g2.setColor(Color.DARK_GRAY);
        g2.drawString(text, x+0.8f, y+0.7f);*/
        g2.setColor(ControlPanel.FONT_SHADOW_COLOR);
        g2.drawString(text, x+0.6f, y+0.5f);
        g2.setColor(fontColor);
        g2.drawString(text, x, y);
    }

    private Rectangle drawMeepleBox(Player playerKey, String imgKey, int count, boolean showOne) {
        return drawMeepleBox(playerKey, imgKey, count, showOne, null, false);
    }

    private Rectangle drawMeepleBox(Player playerKey, String imgKey, int count, boolean showOne, Object regionData) {
        return drawMeepleBox(playerKey, imgKey, count, showOne, regionData, false);
    }

    private Rectangle drawMeepleBox(Player playerKey, String imgKey, int count, boolean showOne, Object regionData, boolean active) {
        if (count == 0) return null;

        int w = 30;
        if (count > 1 || (count == 1 && showOne)) {
            w = count < 10 ? 47 : 60;
        }
        int h = 22;
        if (bx+w > PANEL_WIDTH-PADDING_R) {
            bx = PADDING_L;
            by += LINE_HEIGHT;
        }
        g2.setColor(active ? Color.BLACK : Color.WHITE);
        g2.fillRoundRect(bx, by, w, h, 8, 8);
        g2.drawImage(cache.get(playerKey, imgKey), bx, by-4, null);

        Rectangle rect = null;
        if (regionData != null) {
            rect = new Rectangle(bx, by-4, w, h+8);
            getMouseRegions().add(new MouseListeningRegion(rect, this, regionData));
        }

        if (count > 1 || (count == 1 && showOne)) {
            g2.setColor(active ? Color.WHITE : Color.BLACK);
            g2.drawString(""+count, bx+LINE_HEIGHT, by+17);
        }
        bx += w + 8;
        return rect;
    }

    /*
     * translates parentGraphics, which is not much clean!
     */
    @Override
    public void paintComponent(Graphics2D parentGraphics) {
        super.paintComponent(parentGraphics);

        Game game = client.getGame();

        //TODO better display
//        if (player.getSlot().getState() == SlotState.CLOSED) {
//            this.color = Color.GRAY;
//        }

//    GridPanel gp = client.getGridPanel();

//        boolean isActive = game.getActivePlayer() == player;
//        boolean playerTurn = game.getTurnPlayer() == player;

//    gp.profile(" > get flags");

        BufferedImage bimg = UiUtils.newTransparentImage(PANEL_WIDTH, 200);
        g2 = bimg.createGraphics();
        g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

//    gp.profile(" > create buffer");

        drawDelimiter(DELIMITER_Y);

        g2.setFont(FONT_POINTS);
        drawTextShadow(""+player.getPoints(), PADDING_L, 27);

        g2.setFont(FONT_NICKNAME);
        drawTextShadow(player.getNick(), 78, 27);

//    gp.profile(" > nick & score");

        g2.setFont(FONT_MEEPLE);
        bx = PADDING_L;
        by = 43;

        int small = 0;
        String smallImgKey = SmallFollower.class.getSimpleName();
        for (Follower f : Iterables.filter(player.getFollowers(), MeeplePredicates.inSupply())) {
            //instanceof cannot be used because of Phantom
            if (f.getClass().equals(SmallFollower.class)) {
                small++;
            } else { //all small followers are at beginning of collection
                drawMeepleBox(player, smallImgKey, small, true);
                small = 0;
                drawMeepleBox(player, f.getClass().getSimpleName(), 1, false);
            }
        }
        drawMeepleBox(player, smallImgKey, small, true); //case when only small followers are in collection (not drawn yet)

//    gp.profile(" > followers");

        for (Special meeple : Iterables.filter(player.getSpecialMeeples(), MeeplePredicates.inSupply())) {
            drawMeepleBox(player, meeple.getClass().getSimpleName(), 1, false);
        }

//    gp.profile(" > special");

        AbbeyCapability abbeyCap = game.getCapability(AbbeyCapability.class);
        TowerCapability towerCap = game.getCapability(TowerCapability.class);
        BridgeCapability bridgeCap = game.getCapability(BridgeCapability.class);
        CastleCapability castleCap = game.getCapability(CastleCapability.class);
        KingAndRobberBaronCapability kingRobberCap = game.getCapability(KingAndRobberBaronCapability.class);
        ClothWineGrainCapability cwgCap = game.getCapability(ClothWineGrainCapability.class);
        LittleBuildingsCapability lbCap = game.getCapability(LittleBuildingsCapability.class);

        if (abbeyCap != null) {
            drawMeepleBox(null, "abbey", abbeyCap.hasUnusedAbbey(player) ? 1 : 0, false);
        }

        if (towerCap != null) {
            drawMeepleBox(null, "towerpiece", towerCap.getTowerPieces(player), true);
            getMouseRegions().clear();
        }

        if (bridgeCap != null) {
            drawMeepleBox(null, "bridge", bridgeCap.getPlayerBridges(player), true);
        }
        if (castleCap != null) {
            drawMeepleBox(null, "castle", castleCap.getPlayerCastles(player), true);
        }
        if (lbCap != null) {
            drawMeepleBox(null, "lb-tower", lbCap.getBuildingsCount(player, LittleBuilding.TOWER), true);
            drawMeepleBox(null, "lb-house", lbCap.getBuildingsCount(player, LittleBuilding.HOUSE), true);
            drawMeepleBox(null, "lb-shed", lbCap.getBuildingsCount(player, LittleBuilding.SHED), true);
        }

        if (kingRobberCap != null) {
            if (kingRobberCap.getKing() == player) {
                Rectangle r = drawMeepleBox(null, "king", 1, false, "king");
                if ("king".equals(mouseOverKey)) {
                    g2.setFont(FONT_KING_ROBBER_OVERLAY);
                    g2.setColor(KING_ROBBER_OVERLAY);
                    g2.fillRect(r.x, r.y, r.width, r.height);
                    g2.setColor(Color.WHITE);
                    int size = kingRobberCap.getBiggestCitySize();
                    g2.drawString((size < 10 ? " " : "") + size, r.x+2, r.y+20);
                    g2.setFont(FONT_MEEPLE);
                }
            }
            if (kingRobberCap.getRobberBaron() == player) {
                Rectangle r = drawMeepleBox(null, "robber", 1, false, "robber");
                if ("robber".equals(mouseOverKey)) {
                    g2.setFont(FONT_KING_ROBBER_OVERLAY);
                    g2.setColor(KING_ROBBER_OVERLAY);
                    g2.fillRect(r.x, r.y, r.width, r.height);
                    g2.setColor(Color.WHITE);
                    int size = kingRobberCap.getLongestRoadLength();
                    g2.drawString((size < 10 ? " " : "") + size, r.x+2, r.y+20);
                    g2.setFont(FONT_MEEPLE);
                }
            }
        }
        if (cwgCap != null) {
            drawMeepleBox(null, "cloth", cwgCap.getTradeResources(player, TradeResource.CLOTH), true);
            drawMeepleBox(null, "grain", cwgCap.getTradeResources(player, TradeResource.GRAIN), true);
            drawMeepleBox(null, "wine", cwgCap.getTradeResources(player, TradeResource.WINE), true);
        }
        if (towerCap != null) {
            List<Follower> capturedFigures = towerCap.getPrisoners().get(player);
            Map<Class<? extends Follower>, Integer> groupedByType;
            if (!capturedFigures.isEmpty()) {
                groupedByType = new HashMap<>();
                for (Player opponent : game.getAllPlayers()) {
                    if (opponent == player) continue;
                    boolean isOpponentActive = opponent.equals(game.getActivePlayer()) && opponent.isLocalHuman();
                    boolean clickable = isOpponentActive && !towerCap.isRansomPaidThisTurn();
                    for (Follower f : capturedFigures) {
                        if (f.getPlayer() == opponent) {
                            Integer prevVal = groupedByType.get(f.getClass());
                            groupedByType.put(f.getClass(), prevVal == null ? 1 : prevVal+1);
                        }
                    }
                    for (Entry<Class<? extends Follower>, Integer> entry : groupedByType.entrySet()) {
                        drawMeepleBox(opponent, entry.getKey().getSimpleName(), entry.getValue(), false,
                                clickable ? entry.getKey() : null, clickable
                        );
                    }
                    groupedByType.clear();
                }
            }
        }

//    gp.profile(" > expansions");


        int realHeight = by + (bx > PADDING_L ? LINE_HEIGHT : 0);

//        if (isActive) {
//            //TODO
//            //parentGraphics.setColor(Color.BLACK);
//            //parentGraphics.fillRoundRect(0, -5, PANEL_WIDTH+CORNER_DIAMETER, realHeight+10, CORNER_DIAMETER, CORNER_DIAMETER);
//        }

        parentGraphics.setColor(PLAYER_BG_COLOR);
        parentGraphics.fillRoundRect(0, 0, PANEL_WIDTH+CORNER_DIAMETER, realHeight, CORNER_DIAMETER, CORNER_DIAMETER);

        centerY = (int) parentGraphics.getTransform().getTranslateY() + realHeight/2;

        parentGraphics.drawImage(bimg, 0, 0, PANEL_WIDTH, realHeight, 0, 0, PANEL_WIDTH, realHeight, null);

        if (player.getSlot().isDisconnected()) {
            Composite origComposite = parentGraphics.getComposite();
            parentGraphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .4f));
            parentGraphics.setColor(Color.BLACK);
            parentGraphics.fillRoundRect(0, 0, PANEL_WIDTH+CORNER_DIAMETER, realHeight, CORNER_DIAMETER, CORNER_DIAMETER);
            parentGraphics.setComposite(origComposite);
            parentGraphics.setFont(FONT_NICKNAME);
            parentGraphics.setColor(Color.WHITE);
            parentGraphics.drawString(_("Connection lost").toUpperCase(), 10, 27);
        }

        parentGraphics.translate(0, realHeight); //add also padding
        g2 = null;

//    gp.profile(" > complete");
    }

    public int getCenterY() {
        return centerY;
    }

    @SuppressWarnings("unchecked")
    @Override
    public void mouseClicked(MouseEvent e, MouseListeningRegion origin) {
        if (!(origin.getData() instanceof Class)) return;
        Class<? extends Follower> followerClass = (Class<? extends Follower>) origin.getData();
        TowerCapability tg = client.getGame().getCapability(TowerCapability.class);
        if (!tg.isRansomPaidThisTurn()) {
            if (client.getConfig().getConfirm().getRansom_payment()) {
                String options[] = {_("Pay ransom"), _("Cancel") };
                int result = JOptionPane.showOptionDialog(client,
                        _("Do you really want to pay 3 points to release prisoner?"),
                        _("Confirm ransom payment"),
                        JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[0]);
                if (JOptionPane.YES_OPTION != result) return;
            }
            client.getServer().payRansom(player.getIndex(), followerClass);
        }
    }

    @Override
    public void mouseEntered(MouseEvent e, MouseListeningRegion origin) {
        if (origin.getData() instanceof String) {
            mouseOverKey = (String) origin.getData();
            client.getGridPanel().repaint();
        } else {
            TowerCapability tg = client.getGame().getCapability(TowerCapability.class);
            if (!tg.isRansomPaidThisTurn()) {
                client.getGridPanel().setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
            }
        }
    }

    @Override
    public void mouseExited(MouseEvent e, MouseListeningRegion origin) {
        if (mouseOverKey != null) {
            mouseOverKey = null;
            client.getGridPanel().repaint();
        } else {
            client.getGridPanel().setCursor(Cursor.getDefaultCursor());
        }
    }

}
TOP

Related Classes of com.jcloisterzone.ui.controls.PlayerPanel

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.