Package de.ailis.xadrian.components

Source Code of de.ailis.xadrian.components.SectorSelector

/*
* Copyright (C) 2010-2012 Klaus Reimer <k@ailis.de>
* See LICENSE.txt file for licensing information.
*/
package de.ailis.xadrian.components;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.Locale;
import java.util.Map;
import java.util.SortedMap;
import java.util.SortedSet;

import javax.swing.JComponent;
import javax.swing.UIManager;

import de.ailis.xadrian.data.Game;
import de.ailis.xadrian.data.Sector;
import de.ailis.xadrian.data.factories.GameFactory;
import de.ailis.xadrian.data.factories.SectorFactory;
import de.ailis.xadrian.listeners.SectorSelectorStateListener;
import de.ailis.xadrian.support.I18N;
import de.ailis.xadrian.support.TextRenderer;
import de.ailis.xadrian.utils.SwingUtils;

/**
* Component which displays the sectors in a graphical way and let the user
* select one.
*
* @author Klaus Reimer (k@ailis.de)
*/
public class SectorSelector extends JComponent implements MouseMotionListener,
    MouseListener
{
    /**
     * View mode
     */
    public enum Mode
    {
        /** Political view mode */
        POLITICAL,

        /** Sun view mode */
        SUNS,

        /** Silicon view mode */
        SILICON,

        /** Ore view mode */
        ORE,

        /** Nividium view mode */
        NIVIDIUM,

        /** Ice view mode */
        ICE;

        /**
         * @see java.lang.Enum#toString()
         */
        @Override
        public String toString()
        {
            return I18N.getString("component.sectorSelector.viewMode."
                + name().toLowerCase(Locale.getDefault()));
        }
    }

    /** Serial version UID */
    private static final long serialVersionUID = 42133575643122689L;

    /** The graphics buffer */
    private transient BufferedImage buffer;

    /** The scale factor of the map */
    private float scale;

    /** The game. */
    private final Game game;

    /** The sector over which the mouse cursor hovers */
    private Sector overSector;

    /** The selected sector */
    private Sector selectedSector;

    /** The filter string */
    private String filter;

    /** The view mode */
    private Mode mode = Mode.POLITICAL;

    /**
     * Constructor
     *
     * @param game
     *            The game.
     */
    public SectorSelector(final Game game)
    {
        this.game = game;
        setPreferredSize(new Dimension(650, 512));
        addMouseMotionListener(this);
        addMouseListener(this);
    }

    /**
     * @see javax.swing.JComponent#paintComponent(java.awt.Graphics)
     */
    @Override
    public void paintComponent(final Graphics graphics)
    {
        super.paintComponent(graphics);
       
        final int maxW = getWidth();
        final int maxH = getHeight();
        final SectorFactory sectorFactory = this.game.getSectorFactory();
        final int uniWidth = sectorFactory.getMaxX() * 100 + 150;
        final int uniHeight = sectorFactory.getMaxY() * 100 + 150;
        final float scaleX = (float) maxW / uniWidth;
        final float scaleY = (float) maxH / uniHeight;
        final float uniAR = (float) uniWidth / uniHeight;
        final float winAR = maxW / (float) maxH;
        final int width, height;

        if (uniAR > winAR)
        {
            width = maxW;
            height = maxW * uniHeight / uniWidth;
            this.scale = scaleX;
        }
        else
        {
            height = maxH;
            width = maxH * uniWidth / uniHeight;
            this.scale = scaleY;
        }
       
        if (width <= 0 || height <= 0) return;

        if (this.buffer == null || this.buffer.getWidth() != width
            || this.buffer.getHeight() != height)
            this.buffer = new BufferedImage(width, height,
                BufferedImage.TYPE_INT_ARGB);
        final Graphics2D g = this.buffer.createGraphics();

        final SortedSet<Sector> sectors = sectorFactory.getSectors();

        g.setColor(Color.BLACK);
        g.fillRect(0, 0, width, height);
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
        g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
            RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g.setStroke(new BasicStroke(1.0f / this.scale));

        g.scale(this.scale, this.scale);
        g.translate(75, 75);
        for (final Sector sector : sectors)
        {
            final int sx = sector.getX();
            final int sy = sector.getY();

            Color sectorColor;
            Color borderColor = new Color(0x606060);
            switch (this.mode)
            {
                case SUNS:
                    sectorColor = sector.getSuns().getColor();
                    break;

                case SILICON:
                    sectorColor = sector.getSiliconColor();
                    break;

                case ORE:
                    sectorColor = sector.getOreColor();
                    break;

                case NIVIDIUM:
                    sectorColor = sector.getNividiumColor();
                    break;

                case ICE:
                    sectorColor = sector.getIceColor();
                    break;

                default:
                    sectorColor = sector.getRace().getColor();
            }

            if (this.filter != null && !this.filter.isEmpty())
            {
                if (sector.getName().toLowerCase(Locale.getDefault()).contains(
                    this.filter.toLowerCase(Locale.getDefault())))
                    borderColor = Color.GREEN;
                else
                    sectorColor = getAlphaColor(sectorColor, 32);
            }

            g.setColor(sectorColor);
            g.fillRect(sx * 100 - 40, sy * 100 - 40, 80, 80);

            g.setColor(new Color(0x606060));
            if (sector.getSouth() != null)
                g.fillRect(sx * 100 - 20, sy * 100 + 40, 40, 11);
            if (sector.getNorth() != null)
                g.fillRect(sx * 100 - 20, sy * 100 - 51, 40, 11);
            if (sector.getWest() != null)
                g.fillRect(sx * 100 - 51, sy * 100 - 20, 11, 40);
            if (sector.getEast() != null)
                g.fillRect(sx * 100 + 40, sy * 100 - 20, 11, 40);

            g.setColor(borderColor);
            g.drawRect(sx * 100 - 40, sy * 100 - 40, 80, 80);
        }

        if (this.selectedSector != null)
        {
            final int sx = this.selectedSector.getX();
            final int sy = this.selectedSector.getY();
            g.setColor(Color.BLACK);
            g.setStroke(new BasicStroke(5.0f / this.scale));
            g.drawRoundRect(sx * 100 - 60, sy * 100 - 60, 120, 120, 20, 20);
            g.setColor(Color.GREEN);
            g.setStroke(new BasicStroke(3.0f / this.scale));
            g.drawRoundRect(sx * 100 - 60, sy * 100 - 60, 120, 120, 20, 20);
        }

        // Emphasize the hovered sector
        if (this.overSector != null)
        {
            final int sx = this.overSector.getX();
            final int sy = this.overSector.getY();
            if (!this.overSector.equals(this.selectedSector))
            {
                g.setColor(Color.BLACK);
                g.setStroke(new BasicStroke(5.0f / this.scale));
                g.drawRoundRect(sx * 100 - 60, sy * 100 - 60, 120, 120, 20, 20);
                g.setColor(Color.RED);
                g.setStroke(new BasicStroke(3.0f / this.scale));
                g.drawRoundRect(sx * 100 - 60, sy * 100 - 60, 120, 120, 20, 20);
            }

            // Create the sector info text
            final Color titleColor = new Color(0x40, 0x40, 0x40);
            final Color detailColor = new Color(0x50, 0x50, 0x50);
            final TextRenderer textRenderer = new TextRenderer();
            Font font = UIManager.getFont("Label.font");
            if (font == null) font = new Font("Arial", Font.PLAIN, 12);
            textRenderer.setFont(font.deriveFont(Font.BOLD, font.getSize2D() * 1.2f / this.scale));
            textRenderer.setColor(titleColor);
            textRenderer.addText(this.overSector.getName());
            textRenderer.newLine();
            textRenderer.setFont(font.deriveFont(Font.PLAIN, font.getSize2D() / this.scale));
            textRenderer.setColor(detailColor);
            textRenderer.addText(String.format("%s: %d; %d", I18N
                .getString("component.sectorSelector.location"), this.overSector.getX(),
                this.overSector.getY()));
            textRenderer.newLine();
            textRenderer.addText(String.format("%s: %s", I18N
                .getString("component.sectorSelector.race"), this.overSector.getRace()
                .toString()));
            textRenderer.newLine();
            textRenderer.addText(String.format("%s: %s", I18N
                .getString("component.sectorSelector.suns"), this.overSector.getSuns()
                .toString()));

            addYieldInfo(textRenderer, this.overSector, "siliconWafers");
            addYieldInfo(textRenderer, this.overSector, "ore");
            addYieldInfo(textRenderer, this.overSector, "nividium");
            addYieldInfo(textRenderer, this.overSector, "ice");

            // Position the sector info text
            final Rectangle2D bounds = textRenderer.getBounds(g
                .getFontRenderContext());
            final int borderX = (int) (10 / this.scale);
            final int borderY = (int) (5 / this.scale);
            final int infoWidth = (int) (bounds.getWidth() + borderX * 2);
            final int infoHeight = (int) (bounds.getHeight() + borderY * 2);
            int infoLeft = sx * 100 - infoWidth / 2;
            int infoTop = sy * 100 + 100;
            if (infoTop + infoHeight > height / this.scale - 100)
                infoTop = sy * 100 - 100 - infoHeight;
            if (infoLeft < -50) infoLeft = -50;
            if (infoLeft + infoWidth > width / this.scale - 100)
                infoLeft = (int) (width / this.scale) - 100 - infoWidth;

            // Render the sector info text
            g.setColor(new Color(255, 255, 255, 200));
            g.fillRoundRect(infoLeft, infoTop, infoWidth, infoHeight, 30, 30);
            textRenderer.render(g, infoLeft + borderX, infoTop + borderY);
        }

        graphics.setColor(Color.BLACK);
        graphics.fillRect(0, 0, getWidth(), getHeight());
        graphics.drawImage(this.buffer, (getWidth() - width) / 2,
            (getHeight() - height) / 2, null);
    }

    /**
     * Outputs the yield info.
     *
     * @param renderer
     *            The text renderer
     * @param sector
     *            The sector
     * @param wareId
     *            The id of the asteroid ware
     */
    private void addYieldInfo(final TextRenderer renderer, final Sector sector,
        final String wareId)
    {
        final SortedMap<Integer, Integer> yields = sector.getYieldsMap(wareId);

        // If yield map is empty then do nothing
        if (yields.isEmpty()) return;

        // Output the title
        renderer.newLine();
        renderer.addText(I18N.getString("component.sectorSelector." + wareId) + ": ");
        renderer.newLine();

        // Output the yields
        String text = "    ";
        for (final Map.Entry<Integer, Integer> entry : yields.entrySet())
        {
            final int yield = entry.getKey();
            final int quantity = entry.getValue();
            if (text.length() > 40)
            {
                renderer.addText(text);
                renderer.newLine();
                text = "    ";

            }
            if (quantity > 1)
                text = text + String.format("%dx%d, ", quantity, yield);
            else
                text = text + yield + ", ";
        }
        renderer.addText(text.substring(0, text.length() - 2));
    }

    /**
     * @see java.awt.event.MouseMotionListener#mouseDragged(MouseEvent)
     */
    @Override
    public void mouseDragged(final MouseEvent e)
    {
        // Ignored
    }

    /**
     * @see java.awt.event.MouseMotionListener#mouseMoved(MouseEvent)
     */
    @Override
    public void mouseMoved(final MouseEvent e)
    {
        if (this.buffer == null) return;
       
        final int x = e.getX() - (this.getWidth() - this.buffer.getWidth()) / 2;
        final int y = e.getY() - (this.getHeight() - this.buffer.getHeight()) / 2;
        final int sx = Math.round(((x / this.scale) - 75) / 100);
        final int sy = Math.round(((y / this.scale) - 75) / 100);

        final Sector sector = this.game.getSectorFactory().getSector(sx, sy);
        if (sector != this.overSector)
        {
            this.overSector = sector;
            repaint();
        }
    }

    /**
     * @see MouseListener#mouseClicked(MouseEvent)
     */
    @Override
    public void mouseClicked(final MouseEvent e)
    {
        // Not used
    }

    /**
     * @see MouseListener#mouseEntered(MouseEvent)
     */
    @Override
    public void mouseEntered(final MouseEvent e)
    {
        // Not used
    }

    /**
     * @see MouseListener#mouseExited(MouseEvent)
     */
    @Override
    public void mouseExited(final MouseEvent e)
    {
        // Not used
    }

    /**
     * @see MouseListener#mousePressed(MouseEvent)
     */
    @Override
    public void mousePressed(final MouseEvent e)
    {
        setSelected(this.overSector);
    }

    /**
     * @see MouseListener#mouseReleased(MouseEvent)
     */
    @Override
    public void mouseReleased(final MouseEvent e)
    {
        // Not used
    }

    /**
     * Sets the filter.
     *
     * @param filter
     *            The filter to set
     */
    public void setFilter(final String filter)
    {
        this.filter = filter;
        repaint();
        fireSectorSelectorState();
    }

    /**
     * Adds alpha to the specified color.
     *
     * @param color
     *            The original color
     * @param alpha
     *            The alpha value
     * @return The color with added alpha
     */
    private Color getAlphaColor(final Color color, final int alpha)
    {
        return new Color(color.getRed(), color.getGreen(), color.getBlue(),
            alpha);
    }

    /**
     * Sets the view mode.
     *
     * @param mode
     *            The view mode to set.
     */
    public void setMode(final Mode mode)
    {
        this.mode = mode;
        repaint();
        fireSectorSelectorState();
    }

    /**
     * Returns the current view mode.
     *
     * @return The view mode
     */
    public Mode getMode()
    {
        return this.mode;
    }

    /**
     * Returns the selected sector.
     *
     * @return The selected sector
     */
    public Sector getSelected()
    {
        return this.selectedSector;
    }

    /**
     * Sets the selected sector. null deselectes the currently selected sector.
     *
     * @param sector
     *            The sector to select
     */
    public void setSelected(final Sector sector)
    {
        if ((sector != null && !sector.equals(this.selectedSector))
            || (sector == null && this.selectedSector != null))
        {
            this.selectedSector = sector;
            repaint();
            fireSectorSelectorState();
        }
    }

    /**
     * Adds a sector selector state listener.
     *
     * @param listener
     *            The listener to add
     */
    public void addSectorSelectorStateListener(
        final SectorSelectorStateListener listener)
    {
        this.listenerList.add(SectorSelectorStateListener.class, listener);
    }

    /**
     * Removes a sector selector state listener.
     *
     * @param listener
     *            The listener to remove
     */
    public void removeSectorSelectorStateListener(
        final SectorSelectorStateListener listener)
    {
        this.listenerList.remove(SectorSelectorStateListener.class, listener);
    }

    /**
     * Fire the sector selector state event.
     */
    private void fireSectorSelectorState()
    {
        final Object[] listeners = this.listenerList.getListenerList();
        for (int i = listeners.length - 2; i >= 0; i -= 2)
            if (listeners[i] == SectorSelectorStateListener.class)
                ((SectorSelectorStateListener) listeners[i + 1])
                    .sectorSelectorChanged(this);
    }

    /**
     * Tests the component.
     *
     * @param args
     *            Command line arguments
     * @throws Exception
     *             When something goes wrong
     */
    public static void main(final String[] args) throws Exception
    {
        SwingUtils.prepareGUI();

        Game game = GameFactory.getInstance().getGame("x3tc");
        final SectorSelector component = new SectorSelector(game);
        SwingUtils.testComponent(component);
    }
}
TOP

Related Classes of de.ailis.xadrian.components.SectorSelector

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.