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 * *********************** */ }