com.josue.tileset.editor.Editor.java Source code

Java tutorial

Introduction

Here is the source code for com.josue.tileset.editor.Editor.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.josue.tileset.editor;

import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import static com.josue.tileset.editor.Tile.TILE_SIZE;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Transparency;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.border.LineBorder;
import javax.swing.filechooser.FileNameExtensionFilter;

/**
 *
 * @author Josue
 */
public class Editor extends javax.swing.JFrame {

    /**
     * Creates new form NewApplication
     */
    JFrame frame;

    public Editor() {
        initComponents();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jFileChooser1 = new javax.swing.JFileChooser();
        jFileChooser2 = new javax.swing.JFileChooser();
        jDialog1 = new javax.swing.JDialog();
        jDialog2 = new javax.swing.JDialog();
        jDialog3 = new javax.swing.JDialog();
        buttonGroup1 = new javax.swing.ButtonGroup();
        jPanel1 = new javax.swing.JPanel();
        previewLabel = new javax.swing.JLabel();
        animatedTb = new javax.swing.JCheckBox();
        lightTb = new javax.swing.JCheckBox();
        solidTb = new javax.swing.JCheckBox();
        jPanel2 = new javax.swing.JPanel();
        jSpinner1 = new javax.swing.JSpinner();
        jLabel1 = new javax.swing.JLabel();
        jPanel3 = new javax.swing.JPanel();
        animatedAction = new javax.swing.JRadioButton();
        lightsourceAction = new javax.swing.JRadioButton();
        jLabel2 = new javax.swing.JLabel();
        jButton1 = new javax.swing.JButton();
        exportBtn = new javax.swing.JButton();
        imagePanel = new javax.swing.JPanel();

        javax.swing.GroupLayout jDialog1Layout = new javax.swing.GroupLayout(jDialog1.getContentPane());
        jDialog1.getContentPane().setLayout(jDialog1Layout);
        jDialog1Layout.setHorizontalGroup(jDialog1Layout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 400, Short.MAX_VALUE));
        jDialog1Layout.setVerticalGroup(jDialog1Layout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 300, Short.MAX_VALUE));

        javax.swing.GroupLayout jDialog2Layout = new javax.swing.GroupLayout(jDialog2.getContentPane());
        jDialog2.getContentPane().setLayout(jDialog2Layout);
        jDialog2Layout.setHorizontalGroup(jDialog2Layout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 400, Short.MAX_VALUE));
        jDialog2Layout.setVerticalGroup(jDialog2Layout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 300, Short.MAX_VALUE));

        javax.swing.GroupLayout jDialog3Layout = new javax.swing.GroupLayout(jDialog3.getContentPane());
        jDialog3.getContentPane().setLayout(jDialog3Layout);
        jDialog3Layout.setHorizontalGroup(jDialog3Layout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 400, Short.MAX_VALUE));
        jDialog3Layout.setVerticalGroup(jDialog3Layout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 300, Short.MAX_VALUE));

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setPreferredSize(new java.awt.Dimension(600, 700));

        jPanel1.setBackground(new java.awt.Color(102, 102, 102));
        jPanel1.setForeground(new java.awt.Color(255, 255, 255));

        previewLabel.setBackground(new java.awt.Color(0, 0, 0));
        previewLabel.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        previewLabel.setMaximumSize(new java.awt.Dimension(32, 32));
        previewLabel.setMinimumSize(new java.awt.Dimension(32, 32));
        previewLabel.setPreferredSize(new java.awt.Dimension(32, 32));

        animatedTb.setText("Animated");
        animatedTb.setEnabled(false);
        animatedTb.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                animatedTbActionPerformed(evt);
            }
        });

        lightTb.setText("Light Source");
        lightTb.setEnabled(false);
        lightTb.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                lightTbActionPerformed(evt);
            }
        });

        solidTb.setText("Solid");
        solidTb.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                solidTbActionPerformed(evt);
            }
        });

        jPanel2.setBackground(new java.awt.Color(153, 153, 255));

        jSpinner1.setModel(new javax.swing.SpinnerNumberModel(Long.valueOf(1000L), Long.valueOf(100L),
                Long.valueOf(60000L), Long.valueOf(100L)));
        jSpinner1.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                jSpinner1StateChanged(evt);
            }
        });

        jLabel1.setText("Interval");

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout
                .setHorizontalGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(jPanel2Layout.createSequentialGroup().addGap(14, 14, 14).addComponent(jLabel1)
                                .addGap(18, 18, 18)
                                .addComponent(jSpinner1, javax.swing.GroupLayout.PREFERRED_SIZE, 51,
                                        javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addContainerGap(109, Short.MAX_VALUE)));
        jPanel2Layout.setVerticalGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jPanel2Layout.createSequentialGroup().addGap(23, 23, 23)
                        .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(jSpinner1, javax.swing.GroupLayout.PREFERRED_SIZE,
                                        javax.swing.GroupLayout.DEFAULT_SIZE,
                                        javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addComponent(jLabel1))
                        .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)));

        buttonGroup1.add(animatedAction);
        animatedAction.setSelected(true);
        animatedAction.setText("Animated");

        buttonGroup1.add(lightsourceAction);
        lightsourceAction.setText("Light Source");
        lightsourceAction.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                lightsourceActionActionPerformed(evt);
            }
        });

        jLabel2.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
        jLabel2.setText("Right button");

        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
        jPanel3.setLayout(jPanel3Layout);
        jPanel3Layout.setHorizontalGroup(jPanel3Layout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jPanel3Layout.createSequentialGroup().addGroup(jPanel3Layout
                        .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(jPanel3Layout.createSequentialGroup().addContainerGap()
                                .addComponent(lightsourceAction))
                        .addGroup(jPanel3Layout.createSequentialGroup().addGap(19, 19, 19).addComponent(jLabel2))
                        .addGroup(jPanel3Layout.createSequentialGroup().addContainerGap()
                                .addComponent(animatedAction)))
                        .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)));
        jPanel3Layout.setVerticalGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jPanel3Layout.createSequentialGroup().addGap(9, 9, 9).addComponent(jLabel2)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(animatedAction)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(lightsourceAction).addContainerGap(32, Short.MAX_VALUE)));

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(jPanel1Layout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                        .addContainerGap()
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                                .addComponent(solidTb, javax.swing.GroupLayout.DEFAULT_SIZE,
                                        javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addComponent(animatedTb, javax.swing.GroupLayout.DEFAULT_SIZE,
                                        javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addComponent(lightTb, javax.swing.GroupLayout.DEFAULT_SIZE,
                                        javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE,
                                        javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addComponent(jPanel2, javax.swing.GroupLayout.Alignment.LEADING,
                                        javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE,
                                        Short.MAX_VALUE))
                        .addContainerGap())
                .addGroup(jPanel1Layout.createSequentialGroup().addGap(91, 91, 91)
                        .addComponent(previewLabel, javax.swing.GroupLayout.PREFERRED_SIZE,
                                javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)));
        jPanel1Layout.setVerticalGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jPanel1Layout.createSequentialGroup().addContainerGap()
                        .addComponent(previewLabel, javax.swing.GroupLayout.PREFERRED_SIZE,
                                javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(18, 18, 18).addComponent(solidTb)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(animatedTb)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED).addComponent(lightTb)
                        .addGap(18, 18, 18)
                        .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE,
                                javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE,
                                javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addContainerGap()));

        jButton1.setText("Load");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        exportBtn.setText("Export");
        exportBtn.setEnabled(false);
        exportBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                exportBtnActionPerformed(evt);
            }
        });

        imagePanel.setBackground(new java.awt.Color(0, 0, 0));
        imagePanel.setPreferredSize(new java.awt.Dimension(350, 448));

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup().addGroup(layout
                        .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(layout.createSequentialGroup().addContainerGap().addComponent(jPanel1,
                                javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE,
                                javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addGroup(layout.createSequentialGroup().addGap(10, 10, 10).addComponent(jButton1)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(exportBtn)))
                        .addGap(29, 29, 29)
                        .addComponent(imagePanel, javax.swing.GroupLayout.DEFAULT_SIZE, 381, Short.MAX_VALUE)
                        .addContainerGap()));
        layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(
                javax.swing.GroupLayout.Alignment.TRAILING,
                layout.createSequentialGroup().addGap(11, 11, 11)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(jButton1).addComponent(exportBtn))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addComponent(imagePanel, javax.swing.GroupLayout.DEFAULT_SIZE,
                                        javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE,
                                        javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                        .addContainerGap()));

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
        JFileChooser fileDialog = new JFileChooser();
        fileDialog.setFileFilter(new FileNameExtensionFilter("Image file", "png"));
        fileDialog.showOpenDialog(null);
        inputFile = fileDialog.getSelectedFile();
        if (inputFile != null) {
            loadFile(inputFile);
        }
    }//GEN-LAST:event_jButton1ActionPerformed

    private void lightTbActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_lightTbActionPerformed
    }//GEN-LAST:event_lightTbActionPerformed

    private void solidTbActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_solidTbActionPerformed
        selectedTile.setSolid(!selectedTile.isSolid());
    }//GEN-LAST:event_solidTbActionPerformed

    private void animatedTbActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_animatedTbActionPerformed
        if (selectedTile.isAnimated()) {
            //            selectAnimatedSequence();
        }

    }//GEN-LAST:event_animatedTbActionPerformed

    private void jSpinner1StateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_jSpinner1StateChanged
        long value = (long) jSpinner1.getValue();
        selectedTile.getAnimation().setAnimationInterval(value);

        animatedPerformer.stop();
        //restart the performer
        animatedPerformer = new Timer((int) (selectedTile.getAnimation().getAnimationInterval()),
                new TileAnimator(selectedTile, previewLabel, loadedTiles));
        animatedPerformer.start();

    }//GEN-LAST:event_jSpinner1StateChanged

    private void lightsourceActionActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_lightsourceActionActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_lightsourceActionActionPerformed

    private void exportBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exportBtnActionPerformed

        JFileChooser fileDialog = new JFileChooser();
        fileDialog.setFileFilter(new FileNameExtensionFilter("Json file", "json"));
        String outputFileName = inputFile.getAbsolutePath().split("\\.")[0] + ".json";
        fileDialog.setSelectedFile(new File(outputFileName));
        if (fileDialog.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) {

            File file = fileDialog.getSelectedFile();
            ObjectMapper mapper = new ObjectMapper();
            mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE);
            mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
            try {
                mapper.writeValue(file, loadedTiles);
            } catch (IOException ex) {
                Logger.getLogger(Editor.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

    }//GEN-LAST:event_exportBtnActionPerformed

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(Editor.class.getName()).log(java.util.logging.Level.SEVERE, null,
                    ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(Editor.class.getName()).log(java.util.logging.Level.SEVERE, null,
                    ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(Editor.class.getName()).log(java.util.logging.Level.SEVERE, null,
                    ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(Editor.class.getName()).log(java.util.logging.Level.SEVERE, null,
                    ex);
        }
        //</editor-fold>
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new Editor().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JRadioButton animatedAction;
    private javax.swing.JCheckBox animatedTb;
    private javax.swing.ButtonGroup buttonGroup1;
    private javax.swing.JButton exportBtn;
    private javax.swing.JPanel imagePanel;
    private javax.swing.JButton jButton1;
    private javax.swing.JDialog jDialog1;
    private javax.swing.JDialog jDialog2;
    private javax.swing.JDialog jDialog3;
    private javax.swing.JFileChooser jFileChooser1;
    private javax.swing.JFileChooser jFileChooser2;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JSpinner jSpinner1;
    private javax.swing.JCheckBox lightTb;
    private javax.swing.JRadioButton lightsourceAction;
    private javax.swing.JLabel previewLabel;
    private javax.swing.JCheckBox solidTb;
    // End of variables declaration//GEN-END:variables

    private File inputFile;
    private Tile selectedTile;
    Map<Tile, JLabel> tileLabels = new LinkedHashMap<>();
    List<Tile> loadedTiles = new LinkedList<>();
    private Timer animatedPerformer;

    private int offsetDirection = 1; //1 or -1
    private int offset = 0;

    private void loadFile(File file) {
        this.revalidate();

        try {
            BufferedImage tilesetImage = ImageIO.read(file);
            if (tilesetImage.getWidth() % TILE_SIZE != 0 || tilesetImage.getHeight() % TILE_SIZE != 0) {
                JOptionPane.showMessageDialog(this, "Image size not compatible with 32px per Tile");
                return;
            }

            loadedTiles = loadTile(tilesetImage, file);
            mountButtons(loadedTiles, tilesetImage.getWidth() / TILE_SIZE, tilesetImage.getHeight() / TILE_SIZE);
            exportBtn.setEnabled(true);

        } catch (IOException ex) {
            Logger.getLogger(Editor.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private List<Tile> loadTile(BufferedImage bi, File file) throws IOException {

        String propFileName = file.getParent() + File.separator + file.getName().split("\\.")[0] + ".json";
        File tilePropFile = new File(propFileName);
        List<Tile> loadedTiles = new LinkedList<>();
        if (tilePropFile.exists()) {
            ObjectMapper objectMapper = new ObjectMapper();
            loadedTiles = objectMapper.readValue(tilePropFile, new TypeReference<LinkedList<Tile>>() {
            });
        }

        List<Tile> tiles = new LinkedList<>();
        int tileId = 1;
        for (int y = 0; y < bi.getHeight() / TILE_SIZE; y++) {
            for (int x = 0; x < bi.getWidth() / TILE_SIZE; x++) {
                Tile tile;
                if (loadedTiles.isEmpty()) {
                    tile = new Tile();
                    tile.setId(tileId);
                    tile.setSolid(false);
                } else {
                    tile = loadedTiles.get(tileId - 1);
                }
                tile.setImage(getTileImage(x, y, bi));
                tiles.add(tile);
                tileId++;
            }
        }
        return tiles;
    }

    private BufferedImage getTileImage(int x, int y, BufferedImage tileSetImage) {

        BufferedImage tileImage;
        Graphics2D tileGraphics;

        float opacity = 1L;
        tileImage = createTileImage();
        tileGraphics = tileImage.createGraphics();
        tileGraphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opacity));

        tileGraphics.drawImage(tileSetImage, 0, // destiny x1
                0, // destiny y1
                TILE_SIZE, // destiny x2
                TILE_SIZE, // destiny y2
                x * TILE_SIZE, // source x1
                y * TILE_SIZE, // source y1
                x * TILE_SIZE + TILE_SIZE, // source x2
                y * TILE_SIZE + TILE_SIZE, // source y2
                null);

        return tileImage;
    }

    private BufferedImage createTileImage() {
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice gs = ge.getDefaultScreenDevice();
        GraphicsConfiguration gc = gs.getDefaultConfiguration();
        BufferedImage tileImage = gc.createCompatibleImage(TILE_SIZE, TILE_SIZE, Transparency.TRANSLUCENT);
        //        return new BufferedImage(Tile.TILE_SIZE, Tile.TILE_SIZE, BufferedImage.TYPE_INT_ARGB);
        return tileImage;
    }

    private void mountButtons(List<Tile> tiles, int cols, int rows) {

        imagePanel.removeAll();
        if (animatedPerformer != null) {
            animatedPerformer.stop();
            animatedPerformer = null;
        }

        imagePanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
        Dimension dimension = new Dimension(cols * TILE_SIZE, rows * TILE_SIZE);

        for (Tile tile : tiles) {
            final JLabel tileLabel = new JLabel();

            tileLabel.setIcon(new ImageIcon(tile.getImage()));
            Dimension labelDimension = new Dimension(TILE_SIZE, TILE_SIZE);
            tileLabel.setMinimumSize(labelDimension);
            tileLabel.setMaximumSize(labelDimension);
            tileLabel.setPreferredSize(labelDimension);
            tileLabel.setSize(labelDimension);
            tileLabel.addMouseListener(new java.awt.event.MouseAdapter() {
                @Override
                public void mouseClicked(java.awt.event.MouseEvent evt) {
                    if (SwingUtilities.isRightMouseButton(evt)) {//select animated sequence

                        if (animatedAction.isSelected()) {
                            addAnimatedTile(tile);
                        } else {
                            addLightSourceTile(tile);
                        }

                    } else {

                        if (animatedPerformer != null) {
                            animatedPerformer.stop();
                        }
                        Iterator<JLabel> iterator = tileLabels.values().iterator();
                        while (iterator.hasNext()) {
                            JLabel next = iterator.next();
                            next.revalidate();
                        }
                        imagePanel.repaint();
                        for (Map.Entry<Tile, JLabel> entry : tileLabels.entrySet()) {
                            Tile key = entry.getKey();
                            JLabel value = entry.getValue();
                            value.setBorder(null); //clear borders
                        }

                        selectedTile = tile;//this isolate for the next operations
                        tileLabel.setBorder(new LineBorder(Color.RED, 2));

                        previewLabel.setIcon(new ImageIcon(tile.getImage()));
                        animatedTb.setSelected(selectedTile.isAnimated());
                        lightTb.setSelected(selectedTile.isLight());
                        solidTb.setSelected(selectedTile.isSolid());

                        if (tile.isAnimated()) {

                            for (Integer animatesTileOffset : selectedTile.getAnimation().getAnimatedSequence()) { //display animated borders
                                for (Map.Entry<Tile, JLabel> entry : tileLabels.entrySet()) {
                                    Tile key = entry.getKey();
                                    JLabel value = entry.getValue();
                                    if (key.getId() == selectedTile.getId() + animatesTileOffset) {
                                        value.setBorder(new LineBorder(Color.BLUE, 2));
                                    }
                                }

                            }

                            animatedPerformer = new Timer(
                                    (int) (selectedTile.getAnimation().getAnimationInterval()),
                                    new TileAnimator(selectedTile, previewLabel, loadedTiles));
                            animatedPerformer.start();
                        }
                        if (selectedTile.isLight()) {//light color has preference
                            for (Tile tile : tiles) {
                                if (tile.getId() == selectedTile.getLightTileId()) {
                                    JLabel found = tileLabels.get(tile);
                                    found.setBorder(new LineBorder(Color.YELLOW, 2));
                                    break;
                                }
                            }

                        }
                    }
                }

                @Override
                public void mouseExited(MouseEvent e) {
                    if (selectedTile != null && selectedTile.getAnimation() != null && selectedTile.getAnimation()
                            .getAnimatedSequence().contains(tile.getId() - selectedTile.getId())) {
                        tileLabel.setBorder(new LineBorder(Color.BLUE, 2));
                    } else if (selectedTile != null && selectedTile.isLight()
                            && selectedTile.getLightTileId() == tile.getId()) {
                        tileLabel.setBorder(new LineBorder(Color.YELLOW, 2));
                    } else if (selectedTile != null) {
                        JLabel get = tileLabels.get(selectedTile);
                        if (!get.equals(tileLabel)) { //keep the red border if is the selected
                            tileLabel.setBorder(null);
                        }
                    } else {
                        tileLabel.setBorder(null);
                    }
                }

                @Override
                public void mouseEntered(MouseEvent e) {
                    if (selectedTile != null && selectedTile.getAnimation() != null
                            && !selectedTile.getAnimation().getAnimatedSequence()
                                    .contains(tile.getId() - selectedTile.getId())
                            && tile.getLight() != null && tile.getLight().getLightTileOffset() != 0) {
                        tileLabel.setBorder(new LineBorder(Color.RED, 2));
                    } else if (selectedTile == null) {
                        tileLabel.setBorder(new LineBorder(Color.RED, 2));
                    }
                }
            });
            tileLabels.put(tile, tileLabel);
            imagePanel.add(tileLabel);
        }

        imagePanel.setMaximumSize(dimension);
        imagePanel.setMinimumSize(dimension);
        imagePanel.setPreferredSize(dimension);
        imagePanel.revalidate();
        imagePanel.repaint();
        this.pack();
    }

    enum RIGH_CLICK_ACTION {
        ANIMATED, LIGHT_SOURCE
    }

    private void addAnimatedTile(Tile tile) {
        if (!tile.equals(selectedTile) && selectedTile != null) { //cannot add the same tile as sequence
            JLabel label = tileLabels.get(tile);
            int animatedTileOffset = tile.getId() - selectedTile.getId();
            if (selectedTile.getAnimation() != null
                    && selectedTile.getAnimation().getAnimatedSequence().contains(animatedTileOffset)) {

                selectedTile.getAnimation().getAnimatedSequence()
                        .remove(selectedTile.getAnimation().getAnimatedSequence().indexOf(animatedTileOffset));
                if (selectedTile.getAnimation().getAnimatedSequence().isEmpty()) { //is not an animated tile anymore
                    label.setBorder(null);
                    selectedTile.setAnimation(null);
                }
                if (animatedPerformer != null) {
                    animatedPerformer.stop();
                }
            } else {//new animated tile
                if (animatedPerformer != null) {
                    animatedPerformer.stop();
                }
                if (!selectedTile.isAnimated()) {
                    selectedTile.setAnimation(new Animation());
                }
                selectedTile.getAnimation().getAnimatedSequence().add(animatedTileOffset);
                label.setBorder(new LineBorder(Color.BLUE, 2));

                animatedTb.setSelected(true);
                animatedPerformer = new Timer((int) (selectedTile.getAnimation().getAnimationInterval()),
                        new TileAnimator(selectedTile, previewLabel, loadedTiles));
                animatedPerformer.start();
            }
        }
    }

    private void addLightSourceTile(Tile tile) {
        if (!tile.equals(selectedTile) && selectedTile != null) {
            JLabel label = tileLabels.get(tile);
            if (tile.getId() == selectedTile.getId()) { //already contains
                selectedTile.setLight(null);
                label.setBorder(null);
            } else {
                selectedTile.setLight(new Light());
                selectedTile.getLight().setLightTileOffset(tile.getId() - selectedTile.getId());
                label.setBorder(new LineBorder(Color.YELLOW, 2));
                lightTb.setSelected(true);
            }
        }
    }
}