package org.newdawn.slick.tools.packulike;
import java.awt.Component;
import java.awt.Font;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.ListSelectionModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.filechooser.FileFilter;
/**
* A simple GUI on the front of the packing tool
*
* @author kevin
*/
public class Packer extends JFrame {
/** The panel showing the currently generated sprite sheet */
private SheetPanel sheetPanel;
/** The sprites currently displayed */
private DefaultListModel sprites = new DefaultListModel();
/** The visual list of the sprites */
private JList list = new JList(sprites);
/** The width of the texture being generated */
private int twidth;
/** The height of the texture being generated */
private int theight;
/** The width texture sizes model */
private DefaultComboBoxModel sizes = new DefaultComboBoxModel();
/** The height texture sizes model */
private DefaultComboBoxModel sizes2 = new DefaultComboBoxModel();
/** The visual selection for texture width */
private JComboBox widths = new JComboBox(sizes);
/** The visual selection for texture height */
private JComboBox heights = new JComboBox(sizes2);
/** The visual selection for border size */
private JSpinner border = new JSpinner(new SpinnerNumberModel(0,0,50,1));
/** The chooser used to select sprites */
private JFileChooser chooser = new JFileChooser(".");
/** The chooser used to save the sprite sheet */
private JFileChooser saveChooser = new JFileChooser(".");
/** The packing tool */
private Pack pack = new Pack();
/**
* Create the new GUI for packer
*/
public Packer() {
super("Pack-U-Like");
saveChooser.setFileFilter(new FileFilter() {
public boolean accept(File f) {
if (f.isDirectory()) {
return true;
}
return (f.getName().endsWith(".png"));
}
public String getDescription() {
return "PNG Images (*.png)";
}
});
chooser.setMultiSelectionEnabled(true);
chooser.setFileFilter(new FileFilter() {
public boolean accept(File f) {
if (f.isDirectory()) {
return true;
}
return (f.getName().endsWith(".png") ||
f.getName().endsWith(".jpg") ||
f.getName().endsWith(".gif"));
}
public String getDescription() {
return "Images (*.jpg, *.png, *.gif)";
}
});
sizes.addElement(new Integer(64));
sizes.addElement(new Integer(128));
sizes.addElement(new Integer(256));
sizes.addElement(new Integer(512));
sizes.addElement(new Integer(1024));
sizes.addElement(new Integer(2048));
sizes2.addElement(new Integer(64));
sizes2.addElement(new Integer(128));
sizes2.addElement(new Integer(256));
sizes2.addElement(new Integer(512));
sizes2.addElement(new Integer(1024));
sizes2.addElement(new Integer(2048));
JMenuBar bar = new JMenuBar();
JMenu file = new JMenu("File");
bar.add(file);
JMenuItem save = new JMenuItem("Save");
file.add(save);
file.addSeparator();
JMenuItem quit = new JMenuItem("Quit");
file.add(quit);
save.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
save();
}
});
quit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
setJMenuBar(bar);
JPanel panel = new JPanel();
panel.setLayout(null);
sheetPanel = new SheetPanel(this);
JScrollPane pane = new JScrollPane(sheetPanel);
pane.setBounds(5,5,530,530);
JScrollPane listScroll = new JScrollPane(list);
listScroll.setBounds(540,5,200,350);
list.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
Object[] values = list.getSelectedValues();
ArrayList sprites = new ArrayList();
for (int i=0;i<values.length;i++) {
sprites.add(values[i]);
}
list.removeListSelectionListener(this);
select(sprites);
list.addListSelectionListener(this);
}
});
list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
list.setCellRenderer(new FileListRenderer());
panel.add(pane);
panel.add(listScroll);
JButton add = new JButton("Add");
add.setFont(add.getFont().deriveFont(Font.BOLD));
add.setMargin(new Insets(0,0,0,0));
add.setBounds(745,5,40,30);
panel.add(add);
add.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int resp = chooser.showOpenDialog(Packer.this);
if (resp == JFileChooser.APPROVE_OPTION) {
File[] selected = chooser.getSelectedFiles();
for (int i=0;i<selected.length;i++) {
try {
sprites.addElement(new Sprite(selected[i]));
} catch (IOException x) {
x.printStackTrace();
JOptionPane.showMessageDialog(Packer.this, "Unable to load: "+selected[i].getName());
}
}
}
regenerate();
}
});
JButton remove = new JButton("Del");
remove.setFont(add.getFont().deriveFont(Font.BOLD));
remove.setMargin(new Insets(0,0,0,0));
remove.setBounds(745,35,40,30);
panel.add(remove);
remove.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Object[] selected = list.getSelectedValues();
for (int i=0;i<selected.length;i++) {
sprites.removeElement(selected[i]);
}
regenerate();
}
});
JLabel label;
label = new JLabel("Border");
label.setBounds(540,375,200,25);
panel.add(label);
border.setBounds(540,400,200,25);
panel.add(border);
border.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
regenerate();
}
});
label = new JLabel("Width");
label.setBounds(540,425,200,25);
panel.add(label);
widths.setBounds(540,450,200,25);
panel.add(widths);
widths.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
twidth = ((Integer) widths.getSelectedItem()).intValue();
sheetPanel.setTextureSize(twidth, theight);
regenerate();
}
});
label = new JLabel("Height");
label.setBounds(540,475,200,25);
panel.add(label);
heights.setBounds(540,500,200,25);
heights.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
theight = ((Integer) heights.getSelectedItem()).intValue();
sheetPanel.setTextureSize(twidth, theight);
regenerate();
}
});
panel.add(heights);
twidth = 512;
theight = 512;
sheetPanel.setTextureSize(twidth, theight);
widths.setSelectedItem(new Integer(twidth));
heights.setSelectedItem(new Integer(theight));
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setContentPane(panel);
setSize(800,600);
setResizable(false);
setVisible(true);
}
/**
* Get the sprite a given location on the current sheet
*
* @param x The x coordinate to look for the sprite
* @param y The y coordinate to look for the sprite
* @return The sprite found at the given location or null if no sprite can be found
*/
public Sprite getSpriteAt(int x, int y) {
for (int i=0;i<sprites.size();i++) {
if (((Sprite) sprites.get(i)).contains(x,y)) {
return ((Sprite) sprites.get(i));
}
}
return null;
}
/**
* Select a series of sprites
*
* @param selection The series of sprites to be selected (Sprite objects)
*/
public void select(ArrayList selection) {
list.clearSelection();
int[] selected = new int[selection.size()];
for (int i=0;i<selection.size();i++) {
selected[i] = sprites.indexOf(selection.get(i));
}
list.setSelectedIndices(selected);
sheetPanel.setSelection(selection);
}
/**
* Save the sprite sheet
*/
private void save() {
int resp = saveChooser.showSaveDialog(this);
if (resp == JFileChooser.APPROVE_OPTION) {
File out = saveChooser.getSelectedFile();
ArrayList list = new ArrayList();
for (int i=0;i<sprites.size();i++) {
list.add(sprites.elementAt(i));
}
try {
int b = ((Integer) border.getValue()).intValue();
pack.packImages(list, twidth, theight, b, out);
} catch (IOException e) {
// shouldn't happen
e.printStackTrace();
JOptionPane.showMessageDialog(this, "Failed to write output");
}
}
}
/**
* Regenerate the sprite sheet that is being displayed
*/
private void regenerate() {
try {
ArrayList list = new ArrayList();
for (int i=0;i<sprites.size();i++) {
list.add(sprites.elementAt(i));
}
int b = ((Integer) border.getValue()).intValue();
Sheet sheet = pack.packImages(list, twidth, theight, b, null);
sheetPanel.setImage(sheet);
} catch (IOException e) {
// shouldn't happen
e.printStackTrace();
}
}
/**
* A list cell renderer to show just the plain names
*
* @author kevin
*/
private class FileListRenderer extends DefaultListCellRenderer {
/**
* @see javax.swing.DefaultListCellRenderer#getListCellRendererComponent(javax.swing.JList, java.lang.Object, int, boolean, boolean)
*/
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected,
cellHasFocus);
Sprite sprite = (Sprite) value;
label.setText(sprite.getName());
return label;
}
}
/**
* Entry point to the simple UI
*
* @param argv The arguments to the program
*/
public static void main(String[] argv) {
new Packer();
}
}