com.alvermont.terraj.stargen.ui.SystemFrame.java Source code

Java tutorial

Introduction

Here is the source code for com.alvermont.terraj.stargen.ui.SystemFrame.java

Source

/*
 * Java Terrain and Stellar System Ports
 *
 * Copyright (C) 2006 Martin H. Smith based on work by original
 * authors.
 *
 * Released under the terms of the GNU General Public License
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA  02110-1301, USA.
 *
 * Linking TerraJ statically or dynamically with other modules is making a
 * combined work based on TerraJ. Thus, the terms and conditions of the
 * GNU General Public License cover the whole combination.
 *
 * In addition, as a special exception, the copyright holders of TerraJ
 * give you permission to combine this program with free software programs
 * or libraries that are released under the GNU LGPL and with code included
 * in the standard release of JOGL, Java Getopt and FreeMarker under the BSD
 * license (or modified versions of such code, with unchanged license) and with
 * Apache Commons and Log4J libraries under the Apache license (or modified versions
 * of such code. You may copy and distribute such a system following the terms
 * of the GNU GPL for TerraJ and the licenses of the other code concerned,
 * provided that you include the source code of that other code when and as the
 * GNU GPL requires distribution of source code.
 *
 * Note that people who make modified versions of TerraJ are not obligated to grant
 * this special exception for their modified versions; it is their choice whether
 * to do so. The GNU General Public License gives permission to release a modified
 * version without this exception; this exception also makes it possible to release
 * a modified version which carries forward this exception.
 */

/*
 * SystemFrame.java
 *
 * Created on 20 April 2006, 11:03
 */

package com.alvermont.terraj.stargen.ui;

import com.alvermont.terraj.fracplanet.io.FileUtils;
import com.alvermont.terraj.stargen.Constants;
import com.alvermont.terraj.stargen.Planet;
import com.alvermont.terraj.stargen.Primary;
import com.alvermont.terraj.util.io.ImagePrinter;
import com.alvermont.terraj.util.ui.PNGFileFilter;
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.PrinterJob;
import java.io.CharArrayWriter;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Displays the details of a solar system
 *
 * @author  martin
 * @version $Id: SystemFrame.java,v 1.16 2006/07/06 06:58:35 martin Exp $
 *
 * The JButton in JTable code came from www.devx.com. The original article
 * is at http://www.devx.com/getHelpOn/10MinuteSolution/20425. This didn't
 * work properly for me so I've disabled it for the moment.
 */
public class SystemFrame extends javax.swing.JFrame {
    /** Our logger object */
    private static Log log = LogFactory.getLog(SystemFrame.class);

    /** File chooser for saving PNG files */
    private static JFileChooser pngChooser = new JFileChooser();

    /** The key dialog */
    protected KeyDialog keyDialog;

    TableCellRenderer defaultRenderer;

    static {
        pngChooser.addChoosableFileFilter(new PNGFileFilter());
    }

    /**
     * Creates new form SystemFrame
     *
     * @param star The star at the centre of the solar system
     * @param planets The list of planets in the solar system
     */
    public SystemFrame(Primary star, List<Planet> planets) {
        initComponents();

        this.planets = planets;
        this.star = star;

        overviewTable.setModel(new JTableButtonModel());
        defaultRenderer = overviewTable.getDefaultRenderer(JButton.class);
        overviewTable.setDefaultRenderer(JButton.class, new JTableButtonRenderer(defaultRenderer));
        overviewTable.addMouseListener(new JTableButtonMouseListener(overviewTable));
    }

    class JTableButtonRenderer implements TableCellRenderer {
        private TableCellRenderer __defaultRenderer;

        public JTableButtonRenderer(TableCellRenderer renderer) {
            __defaultRenderer = renderer;
        }

        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
                boolean hasFocus, int row, int column) {
            if (value instanceof Component)
                return (Component) value;
            return __defaultRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        }
    }

    class JTableButtonMouseListener implements MouseListener {
        private JTable __table;

        private void __forwardEventToButton(MouseEvent e) {
            TableColumnModel columnModel = __table.getColumnModel();
            int column = columnModel.getColumnIndexAtX(e.getX());
            int row = e.getY() / __table.getRowHeight();
            Object value;
            JButton button;
            MouseEvent buttonEvent;

            if (row >= __table.getRowCount() || row < 0 || column >= __table.getColumnCount() || column < 0)
                return;

            value = __table.getValueAt(row, column);

            if (!(value instanceof JButton))
                return;

            button = (JButton) value;

            buttonEvent = (MouseEvent) SwingUtilities.convertMouseEvent(__table, e, button);
            button.dispatchEvent(buttonEvent);
            // This is necessary so that when a button is pressed and released
            // it gets rendered properly.  Otherwise, the button may still appear
            // pressed down when it has been released.
            __table.repaint();
        }

        public JTableButtonMouseListener(JTable table) {
            __table = table;
        }

        public void mouseClicked(MouseEvent e) {
            __forwardEventToButton(e);
        }

        public void mouseEntered(MouseEvent e) {
            __forwardEventToButton(e);
        }

        public void mouseExited(MouseEvent e) {
            __forwardEventToButton(e);
        }

        public void mousePressed(MouseEvent e) {
            __forwardEventToButton(e);
        }

        public void mouseReleased(MouseEvent e) {
            __forwardEventToButton(e);
        }
    }

    class JTableButtonModel extends DefaultTableModel {
        private String[] __columns = { "#", "Type", "Distance", "Mass", "Radius"
                /*,"Action" */ };

        private Class[] classes = { java.lang.Integer.class, java.lang.String.class, java.lang.String.class,
                java.lang.String.class, java.lang.String.class, JButton.class };

        public String getColumnName(int column) {
            return __columns[column];
        }

        public int getColumnCount() {
            return __columns.length;
        }

        public boolean isCellEditable(int row, int column) {
            return false;
        }

        public Class getColumnClass(int column) {
            return classes[column];
        }
    }

    /**
     * Build a list of images to be used for a list of planets and assign them
     * to the panels.
     * 
     * @throws java.io.IOException If there is an error building the images
     */
    public void buildImages() throws IOException {
        List<JLabel> labels = UIUtils.buildImages(this.planets);

        JPanel panel = new JPanel();

        panel.add(UIUtils.getSunLabel());

        for (JLabel label : labels) {
            panel.add(label);
        }

        panel.setBackground(Color.BLACK);

        systemScrollpane.setViewportView(panel);

        systemScrollpane.validate();

        populateOverview();
    }

    /**
     * Fill in the details on the overview panel
     */
    public void populateOverview() {
        DefaultTableModel dtm = (DefaultTableModel) overviewTable.getModel();

        for (Planet p : this.planets) {
            Object[] row = new Object[6];

            row[0] = new Integer(p.getNumber());
            row[1] = p.getType().getPrintText(p.getType());
            row[2] = String.format("%.3f AU", p.getA());
            row[3] = String.format("%.3f EM", p.getMass() * Constants.SUN_MASS_IN_EARTH_MASSES);
            row[4] = String.format("%.3f ER", p.getRadius() / Constants.KM_EARTH_RADIUS);
            row[5] = new JButton("Details ...");

            dtm.addRow(row);
        }

        // Disable auto resizing
        overviewTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);

        // Set the first visible column to 100 pixels wide
        TableColumn col = overviewTable.getColumnModel().getColumn(0);
        int width = 50;
        col.setPreferredWidth(width);
        overviewTable.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
    }

    /** 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.
     */
    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
    private void initComponents() {
        systemScrollpane = new javax.swing.JScrollPane();
        jPanel1 = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        overviewTable = new javax.swing.JTable();
        jMenuBar1 = new javax.swing.JMenuBar();
        jMenu1 = new javax.swing.JMenu();
        saveMenuItem = new javax.swing.JMenuItem();
        printMenuItem = new javax.swing.JMenuItem();
        jSeparator1 = new javax.swing.JSeparator();
        closeMenuItem = new javax.swing.JMenuItem();
        jMenu2 = new javax.swing.JMenu();
        detailsMenuItem = new javax.swing.JMenuItem();
        jMenu3 = new javax.swing.JMenu();
        keyMenuItem = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Generated Solar System");
        systemScrollpane.setBackground(new java.awt.Color(0, 0, 0));

        jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Planetary Overview"));
        overviewTable.setModel(new javax.swing.table.DefaultTableModel(new Object[][] {

        }, new String[] { "#", "Type", "Distance", "Mass", "Radius", "Action" }) {
            Class[] types = new Class[] { java.lang.Integer.class, java.lang.Object.class, java.lang.String.class,
                    java.lang.String.class, java.lang.String.class, java.lang.Object.class };
            boolean[] canEdit = new boolean[] { false, false, false, false, false, false };

            public Class getColumnClass(int columnIndex) {
                return types[columnIndex];
            }

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit[columnIndex];
            }
        });
        overviewTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS);
        jScrollPane1.setViewportView(overviewTable);

        org.jdesktop.layout.GroupLayout jPanel1Layout = new org.jdesktop.layout.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 679, Short.MAX_VALUE));
        jPanel1Layout.setVerticalGroup(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 245, Short.MAX_VALUE));

        jMenu1.setText("File");
        saveMenuItem.setText("Save Image ...");
        saveMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveMenuItemActionPerformed(evt);
            }
        });

        jMenu1.add(saveMenuItem);

        printMenuItem.setText("Print Image ...");
        printMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                printMenuItemActionPerformed(evt);
            }
        });

        jMenu1.add(printMenuItem);

        jMenu1.add(jSeparator1);

        closeMenuItem.setText("Close");
        closeMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                closeMenuItemActionPerformed(evt);
            }
        });

        jMenu1.add(closeMenuItem);

        jMenuBar1.add(jMenu1);

        jMenu2.setText("View");
        detailsMenuItem.setText("Solar System Details ...");
        detailsMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                detailsMenuItemActionPerformed(evt);
            }
        });

        jMenu2.add(detailsMenuItem);

        jMenuBar1.add(jMenu2);

        jMenu3.setText("Help");
        keyMenuItem.setText("Show Key ...");
        keyMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                keyMenuItemActionPerformed(evt);
            }
        });

        jMenu3.add(keyMenuItem);

        jMenuBar1.add(jMenu3);

        setJMenuBar(jMenuBar1);

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING).add(
                org.jdesktop.layout.GroupLayout.TRAILING,
                layout.createSequentialGroup().addContainerGap()
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                                .add(org.jdesktop.layout.GroupLayout.LEADING, jPanel1,
                                        org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
                                        org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .add(org.jdesktop.layout.GroupLayout.LEADING, systemScrollpane,
                                        org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 691, Short.MAX_VALUE))
                        .addContainerGap()));
        layout.setVerticalGroup(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                .add(layout.createSequentialGroup().addContainerGap()
                        .add(systemScrollpane, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 152, Short.MAX_VALUE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(jPanel1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
                                org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addContainerGap()));
        java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        setBounds((screenSize.width - 719) / 2, (screenSize.height - 499) / 2, 719, 499);
    }// </editor-fold>//GEN-END:initComponents

    private void keyMenuItemActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_keyMenuItemActionPerformed
    {//GEN-HEADEREND:event_keyMenuItemActionPerformed

        if (keyDialog == null)
            keyDialog = new KeyDialog(this, false);

        keyDialog.setVisible(true);

    }//GEN-LAST:event_keyMenuItemActionPerformed

    private void detailsMenuItemActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_detailsMenuItemActionPerformed
    {//GEN-HEADEREND:event_detailsMenuItemActionPerformed

        try {
            Configuration cfg = new Configuration();
            // Specify the data source where the template files come from.
            cfg.setClassForTemplateLoading(TemplateTest.class, "/com/alvermont/terraj/stargen/templates/");

            // Specify how templates will see the data model. This is an advanced topic...
            // but just use this:
            cfg.setObjectWrapper(new DefaultObjectWrapper());

            DetailsFromTemplate dft = new DetailsFromTemplate();

            List<PlanetDetailsPanel> panels = new ArrayList<PlanetDetailsPanel>();

            // first the star

            Template temp = cfg.getTemplate("starmain_html.ftl");

            CharArrayWriter out = new CharArrayWriter();

            dft.processTemplate(temp, star, out);
            out.flush();

            BufferedImage image = UIUtils.getImage("Sun");

            image = UIUtils.scaleImage(image, 32, 64);

            PlanetDetailsPanel panel = new PlanetDetailsPanel(image, "Star", out.toString());

            panel.setName("Star");

            panels.add(panel);

            // now do the planets

            temp = cfg.getTemplate("planetmain_html.ftl");

            for (Planet planet : this.planets) {
                out = new CharArrayWriter();

                dft.processTemplate(temp, planet, this.star, out);
                out.flush();

                image = UIUtils.getImage(planet.getType().getPrintText(planet.getType()));

                image = UIUtils.scaleImage(image, 64, 64);

                panel = new PlanetDetailsPanel(image, planet.getType().getPrintText(planet.getType()),
                        out.toString());

                panel.setName("#" + planet.getNumber());

                panels.add(panel);
            }

            DetailsFrame details = new DetailsFrame(this.star, this.planets, panels);

            details.setVisible(true);
        } catch (Exception ex) {
            log.error("Error getting details from template", ex);

            JOptionPane.showMessageDialog(this, "Error: " + ex.getMessage() + "\nCheck log file for full details",
                    "Template Error", JOptionPane.ERROR_MESSAGE);
        }

    }//GEN-LAST:event_detailsMenuItemActionPerformed

    private void saveMenuItemActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_saveMenuItemActionPerformed
    {//GEN-HEADEREND:event_saveMenuItemActionPerformed

        final int choice = this.pngChooser.showSaveDialog(this);

        try {
            if (choice == JFileChooser.APPROVE_OPTION) {
                if (!this.pngChooser.getSelectedFile().isFile() || (JOptionPane.showConfirmDialog(this,
                        "This file already exists. Do you want to\n" + "overwrite it?", "Replace File?",
                        JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION)) {
                    List<BufferedImage> images = UIUtils.getPlanetImages(this.planets);

                    BufferedImage collage = UIUtils.combineImagesHorizontal(images);

                    final File target = FileUtils.addExtension(this.pngChooser.getSelectedFile(), ".png");

                    ImageIO.write(collage, PNGFileFilter.getFormatName(target), target);
                }
            }
        } catch (IOException ioe) {
            log.error("Error writing image file", ioe);

            JOptionPane.showMessageDialog(this, "Error: " + ioe.getMessage() + "\nCheck log file for full details",
                    "Error Saving", JOptionPane.ERROR_MESSAGE);
        }

    }//GEN-LAST:event_saveMenuItemActionPerformed

    private void closeMenuItemActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_closeMenuItemActionPerformed
    {//GEN-HEADEREND:event_closeMenuItemActionPerformed
        this.setVisible(false);
        this.dispose();
    }//GEN-LAST:event_closeMenuItemActionPerformed

    private void printMenuItemActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_printMenuItemActionPerformed
    {//GEN-HEADEREND:event_printMenuItemActionPerformed

        try {
            List<BufferedImage> images = UIUtils.getPlanetImages(this.planets);

            BufferedImage collage = UIUtils.combineImagesHorizontal(images);

            final PrinterJob printJob = PrinterJob.getPrinterJob();
            final PageFormat pf = printJob.pageDialog(printJob.defaultPage());

            printJob.setPrintable(new ImagePrinter(collage, pf), pf);

            if (printJob.printDialog()) {
                printJob.print();
            }
        } catch (Exception e) {
            log.error("Error printing", e);

            JOptionPane.showMessageDialog(this, "Error: " + e.getMessage() + "\nCheck log file for full details",
                    "Error Printing", JOptionPane.ERROR_MESSAGE);
        }

    }//GEN-LAST:event_printMenuItemActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JMenuItem closeMenuItem;
    private javax.swing.JMenuItem detailsMenuItem;
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenu jMenu2;
    private javax.swing.JMenu jMenu3;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JMenuItem keyMenuItem;
    private javax.swing.JTable overviewTable;
    private javax.swing.JMenuItem printMenuItem;
    private javax.swing.JMenuItem saveMenuItem;
    private javax.swing.JScrollPane systemScrollpane;
    // End of variables declaration//GEN-END:variables

    /**
     * Holds value of property planets.
     */
    private List<Planet> planets;

    /**
     * Getter for property planets.
     * @return Value of property planets.
     */
    public List<Planet> getPlanets() {
        return this.planets;
    }

    /**
     * Holds value of property star.
     */
    private Primary star;

    /**
     * Getter for property star.
     * @return Value of property star.
     */
    public Primary getStar() {
        return this.star;
    }

}