package sg.atom2d.tools.map;
import java.awt.*;
import java.awt.image.*;
import javax.swing.*;
import javax.swing.border.*;
import java.util.*;
import java.awt.event.*;
import java.awt.dnd.*;
import java.awt.datatransfer.*;
import java.io.*;
import javax.imageio.ImageIO;
public class TileChooser extends JPanel implements ActionListener, GraphicsBankChangeListener {
//DropTarget dropTarget;
ArrayList tiles;
GridLayout layout;
GraphicsBank gfx;
int tileWidth = 32;
Tile selectedTile;
ButtonGroup group;
JPanel tilePanel;
JPanel spacer;
/* For tile properties dialog */
JDialog propertiesDialog;
Tile propertyTile;
JTextField userText;
JSpinner tileNumber;
JTextField tileName;
JTextField tileType;
JLabel tileImg;
JButton applyBtn;
JButton cancelBtn;
JButton deleteBtn;
JTextField imageFile;
FileDropHandler fileDrop;
public TileChooser(GraphicsBank gfx) {
tilePanel = new JPanel();
layout = new GridLayout(0, 5);
tilePanel.setLayout(layout);
this.setLayout(new BorderLayout());
this.add(tilePanel, BorderLayout.NORTH);
/* Put in spacer to enlarge the panel as a drop target */
spacer = new JPanel();
spacer.add(new JLabel(" Drop new tiles here"));
spacer.setToolTipText("Drop image files here to create more tiles.");
//spacer.setPreferredSize(gfx.getBaseTileSize());
this.add(spacer, BorderLayout.CENTER);
this.gfx = gfx;
reset();
fileDrop = new FileDropHandler();
setTransferHandler(fileDrop);
gfx.addChangeListener(this);
propertiesDialog = null;
}
public TileChooser(GraphicsBank gfx, JFrame dialogOwner) {
this(gfx);
createPropertiesDialog(dialogOwner);
}
void createPropertiesDialog(JFrame dialogOwner) {
/* Setup for the proeprties dialog */
propertiesDialog = new JDialog(dialogOwner, "Tile Properties");
propertiesDialog.setSize(300, 300); //to set location better
propertiesDialog.setLocationRelativeTo(null);
tileName = new JTextField("", 20);
tileType = new JTextField("", 20);
imageFile = new JTextField("", 20);
imageFile.setEditable(false);
tileNumber = new JSpinner();
userText = new JTextField("", 20);
propertyTile = null;
tileImg = new JLabel();
tileImg.setHorizontalAlignment(SwingConstants.CENTER);
tileImg.setBorder(new TitledBorder("Image"));
JPanel cp = (JPanel) propertiesDialog.getContentPane();
cp.setLayout(new BorderLayout());
JPanel p2 = new JPanel(new BorderLayout());
cp.add(p2, BorderLayout.CENTER);
cp.add(tileImg, BorderLayout.NORTH);
JPanel btns1 = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.insets = new Insets(3, 3, 3, 3);
c.gridx = 0;
c.gridy = 0;
btns1.add(new JLabel("ID"), c);
c.gridx = 1;
c.ipadx = 30;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.WEST;
btns1.add(tileNumber, c);
c.ipadx = 0;
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 1;
btns1.add(new JLabel("Type"), c);
c.gridx = 1;
btns1.add(tileType, c);
c.gridx = 0;
c.gridy = 2;
btns1.add(new JLabel("Name"), c);
c.gridx = 1;
btns1.add(tileName, c);
c.gridx = 0;
c.gridy = 3;
btns1.add(new JLabel("User Text"), c);
c.gridx = 1;
btns1.add(userText, c);
p2.add(btns1, BorderLayout.NORTH);
/* The buttons */
applyBtn = new JButton("Save");
deleteBtn = new JButton("Delete Tile");
cancelBtn = new JButton("Cancel");
applyBtn.addActionListener(this);
cancelBtn.addActionListener(this);
deleteBtn.addActionListener(this);
JPanel btns2 = new JPanel(new GridLayout(1, 3));
btns2.add(deleteBtn);
btns2.add(applyBtn);
btns2.add(cancelBtn);
c.gridx = 0;
c.gridy = 4;
c.gridwidth = 2;
btns1.add(btns2, c);
propertiesDialog.setSize(300, 500);
propertiesDialog.setResizable(false);
}
/**
* Rebuild the entire panel from the graphics bank
*
*/
public void reset() {
int count = 0;
tilePanel.removeAll();
group = new ButtonGroup();
TileButton b = new TileButton(null);
tilePanel.add(b);
group.add(b);
count++;
Iterator i = gfx.iterator();
while (i.hasNext()) {
b = new TileButton((Tile) i.next());
tilePanel.add(b);
group.add(b);
count++;
}
if (count <= 0) {
//spacer.setText(" No Tiles");
spacer.setPreferredSize(new Dimension(1, 100));
//spacer.setBorder(new LineBorder(Color.black));
} else {
//spacer.setText(" Drop new tiles");
spacer.setPreferredSize(new Dimension(1, 30));
}
tilePanel.revalidate();
repaint();
}
/**
* Large change to the tileset, so we just remove all the buttons and
* rebuild them
*
*/
public void tilesetUpdated(GraphicsBank g) {
System.out.println("tilset updated");
if (g == gfx) {
reset();
}
}
/**
* Reset. we don't keep track of the buttons so we have to remove everything
* and rebuild it.
*
*/
public void tileRemoved(GraphicsBank g, Tile t) {
System.out.println("tilset updated");
if (g == gfx) {
reset();
}
}
/**
* Add a single tile button
*
*/
public void tileAdded(GraphicsBank g, Tile t) {
System.out.println("tilset updated");
TileButton b = new TileButton(t);
tilePanel.add(b);
group.add(b);
//spacer.setText(" Drop new tiles");
spacer.setPreferredSize(new Dimension(1, 30));
tilePanel.revalidate();
repaint();
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == applyBtn && propertyTile != null) {
propertyTile.name = tileName.getText();
propertyTile.type = tileType.getText();
propertyTile.number = ((Integer) tileNumber.getValue()).intValue();
propertyTile.info = userText.getText();
propertiesDialog.dispose();
propertyTile = null;
} else if (e.getSource() == cancelBtn) {
propertiesDialog.dispose();
propertyTile = null;
} else if (e.getSource() == deleteBtn) {
if (propertyTile != null) {
gfx.remove(propertyTile);
propertyTile = null;
}
propertiesDialog.dispose();
} else {
System.err.println("Unknown button fired action. " + e);
}
}
public void setWidth(int width) {
if (width >= tileWidth + 8) {
layout.setColumns(width / (tileWidth + 15));
tilePanel.revalidate();
}
}
public Tile getSelectedTile() {
return selectedTile;
}
void showProperties(Tile t) {
propertyTile = t;
if (t != null) {
userText.setText(t.getInfo());
tileNumber.setValue(new Integer(t.getNumber()));
tileName.setText(t.getName());
tileType.setText(t.getType());
tileImg.setIcon(new ImageIcon(t.getImage()));
applyBtn.setEnabled(true);
deleteBtn.setEnabled(true);
userText.setEditable(true);
tileNumber.setEnabled(true);
tileName.setEditable(true);
tileType.setEditable(true);
} else {
userText.setText("");
tileNumber.setValue(new Integer(0));
tileName.setText("Null (Erases existing tiles)");
tileType.setText("");
tileImg.setIcon(null);
userText.setEditable(false);
tileNumber.setEnabled(false);
tileName.setEditable(false);
tileType.setEditable(false);
applyBtn.setEnabled(false);
deleteBtn.setEnabled(false);
}
propertiesDialog.pack();
propertiesDialog.setVisible(true);
}
public void importImageAsTile(File f) throws IOException {
importImageAsTile(f, 0);
}
public void importImageAsTile(File f, int level) throws IOException {
if (f.isDirectory()) {
File[] contents = f.listFiles();
for (int num = 0; num < contents.length; num++) {
importImageAsTile(contents[num]);
}
}
System.out.println("Import " + f);
try {
ImageIO.read(f);
} catch (Exception e) {
System.out.println("FAIL");
return;
}
System.out.println("getbasedir.... ahuh!");
//File base = new File(gfx.getBaseDirectory().getCanonicalPath());
System.out.println("?1");
int n = gfx.getUnusedNumber();
System.out.println("?2");
Tile t = new Tile(n, f.getAbsolutePath(), "New Tile " + n, "No Type");
System.out.println("Adding " + f);
gfx.add(t);
if (propertiesDialog != null) {
showProperties(t);
}
}
/**
* ******************************************************
* Inner class. The buttons that appear on the chooser. *
*******************************************************
*/
class TileButton extends JToggleButton implements ActionListener, MouseListener {
Tile tile;
public TileButton(Tile t) {
super();
Image i2 = new BufferedImage(gfx.getBaseTileSize().width, gfx.getBaseTileSize().height, BufferedImage.TYPE_INT_ARGB);
if (t != null) {
Image i = t.getImage();
i2.getGraphics().drawImage(i, 0, 0, 32, 32, null);
setToolTipText(t.getName());
}
setIcon(new ImageIcon(i2));
setMargin(new Insets(2, 2, 2, 2));
tile = t;
this.addMouseListener(this);
this.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
selectedTile = tile;
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
showProperties(tile);
}
}
public Tile getTile() {
return tile;
}
}
/**
* ************************************
* Inner class - the transfer handler *
*************************************
*/
class FileDropHandler extends TransferHandler {
/**
* Determine whether we can or cannot accept the stuff the user is
* dragging onto our panel. In this case we accept only file lists.
*
*/
public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) {
//System.out.println("Got query by component: "+comp);
for (int i = 0; i < transferFlavors.length; i++) {
//System.out.println("Available flavor: "+transferFlavors[i]);
if (transferFlavors[i].equals(DataFlavor.javaFileListFlavor)) {
//System.out.println("I can use this");
return true;
}
}
return false;
}
/**
* Import info about the file. Makes the assumption that the "canImport"
* has worked correctly and this data can in fact be served up as a File
* List.
*
*/
public boolean importData(JComponent comp, Transferable t) {
//System.out.println("Import data");
try {
java.util.List files = (java.util.List) t.getTransferData(DataFlavor.javaFileListFlavor);
if (files.size() > 4) {
/* Does not work. Forever halts the AWT thread.
if(!(PromptDialog.ask("Really process "+files.size()+" files?", "Yes", "Cancel").equals("Yes"))) {
return false;
} */
}
Iterator itr = files.iterator();
//System.out.println("itr, size = "+files.size());
while (itr.hasNext()) {
File f = (File) itr.next();
//System.out.println("imported "+f);
importImageAsTile(f);
//System.out.println("done "+f);
}
} catch (UnsupportedFlavorException e) {
System.err.println("Unsupported drop content: " + e);
} catch (IOException e) {
System.err.println("Unexpected IO Exception while importing tile: " + e);
e.printStackTrace();
//PromptDialog.tell("Sorry, something broke. Please save your work and restart the program.", "OK");
}
return true;
}
}
/**
* **********************
* End of inner classes *
***********************
*/
}