/* * $Id$ * * Copyright (c) 2005 by Rodney Kinney * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License (LGPL) as published by the Free Software Foundation. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, copies are available * at http://www.opensource.org. */ package VASSAL.build.module.map.boardPicker.board; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.Box; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.WindowConstants; import VASSAL.build.module.map.boardPicker.Board; import VASSAL.build.module.map.boardPicker.board.mapgrid.GridContainer; import VASSAL.build.module.map.boardPicker.board.mapgrid.GridNumbering; import VASSAL.build.module.map.boardPicker.board.mapgrid.RegularGridNumbering; import VASSAL.i18n.Resources; import VASSAL.tools.AdjustableSpeedScrollPane; public abstract class GridEditor extends JDialog implements MouseListener, KeyListener { private static final long serialVersionUID = 1L; protected static final String SET = Resources.getString("Editor.GridEditor.set_grid_shape"); //$NON-NLS-1$ protected static final String CANCEL = Resources.getString(Resources.CANCEL); protected static final String CANCEL_SET = Resources.getString("Editor.GridEditor.cancel_set"); //$NON-NLS-1$ protected static final String OK = Resources.getString(Resources.SAVE); protected static final String NUMBERING = Resources.getString("Editor.GridEditor.numbering"); //$NON-NLS-1$ protected EditableGrid grid; protected Board board; protected JPanel view; protected JScrollPane scroll; protected boolean setMode; protected Point hp1, hp2, hp3; protected JButton okButton, canSetButton, setButton, numberingButton; protected boolean saveGridVisible, saveNumberingVisible; protected double saveDx, saveDy; protected Point saveOrigin; public GridEditor(EditableGrid grid) { super(); setTitle(Resources.getString("Editor.ModuleEditor.edit", grid.getGridName())); //$NON-NLS-1$ setModal(true); this.grid = grid; GridContainer container = grid.getContainer(); if (container != null) { board = container.getBoard(); } saveGridVisible = grid.isVisible(); if (grid.getGridNumbering() != null) { saveNumberingVisible = grid.getGridNumbering().isVisible(); // if (saveGridVisible) { // ((RegularGridNumbering) grid.getGridNumbering()).setAttribute(RegularGridNumbering.VISIBLE, Boolean.FALSE); // } } saveDx = grid.getDx(); saveDy = grid.getDy(); saveOrigin = grid.getOrigin(); initComponents(); } protected void initComponents() { setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent we) { cancel(); } }); view = new GridPanel(board); view.addMouseListener(this); view.addKeyListener(this); view.setFocusable(true); scroll = new AdjustableSpeedScrollPane( view, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); scroll.setPreferredSize(new Dimension(800, 600)); add(scroll, BorderLayout.CENTER); Box textPanel = Box.createVerticalBox(); textPanel.add(new JLabel(Resources.getString("Editor.GridEditor.arrow_keys"))); //$NON-NLS-1$ textPanel.add(new JLabel(Resources.getString("Editor.GridEditor.control_arrow_keys"))); //$NON-NLS-1$ textPanel.add(new JLabel(Resources.getString("Editor.GridEditor.shift_key"))); //$NON-NLS-1$ JPanel buttonPanel = new JPanel(); okButton = new JButton(OK); okButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { cancelSetMode(); setVisible(false); /* GameModule.getGameModule() .getDataArchive().clearTransformedImageCache(); */ } }); buttonPanel.add(okButton); JButton canButton = new JButton(CANCEL); canButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { cancel(); } }); buttonPanel.add(canButton); setButton = new JButton(SET); setButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { startSetMode(); } }); setButton.setRequestFocusEnabled(false); buttonPanel.add(setButton); canSetButton = new JButton(CANCEL_SET); canSetButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { cancelSetMode(); } }); canSetButton.setVisible(false); canSetButton.setRequestFocusEnabled(false); buttonPanel.add(canSetButton); numberingButton = new JButton(NUMBERING); numberingButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ((RegularGridNumbering) grid.getGridNumbering()).setAttribute(RegularGridNumbering.VISIBLE, Boolean.valueOf(! grid.getGridNumbering().isVisible())); repaint(); } }); numberingButton.setEnabled(grid.getGridNumbering() != null); numberingButton.setVisible(true); numberingButton.setRequestFocusEnabled(false); buttonPanel.add(numberingButton); Box controlPanel = Box.createVerticalBox(); controlPanel.add(textPanel); controlPanel.add(buttonPanel); add(controlPanel, BorderLayout.SOUTH); scroll.revalidate(); pack(); repaint(); } protected void cancel() { cancelSetMode(); grid.setDx(saveDx); grid.setDy(saveDy); grid.setOrigin(saveOrigin); setVisible(false); } protected void cancelSetMode() { canSetButton.setVisible(false); setButton.setVisible(true); view.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); setMode = false; grid.setVisible(saveGridVisible); if (grid.getGridNumbering() != null && saveNumberingVisible) { ((RegularGridNumbering) grid.getGridNumbering()).setAttribute(RegularGridNumbering.VISIBLE, Boolean.valueOf(saveNumberingVisible)); } repaint(); } protected void startSetMode() { hp1 = null; hp2 = null; hp3 = null; setMode = true; canSetButton.setVisible(true); setButton.setVisible(false); view.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR)); grid.setVisible(false); JOptionPane.showMessageDialog(null, Resources.getString("Editor.GridEditor.click_on_3")); //$NON-NLS-1$ repaint(); } public void keyPressed(KeyEvent e) { if (setMode) { return; } boolean sideways = grid.isSideways(); switch (e.getKeyCode()) { case KeyEvent.VK_UP: if (e.isControlDown()) { if (sideways) { adjustDx(-1, e); } else { adjustDy(-1, e); } } else { if (sideways) { adjustX0(-1, e); } else { adjustY0(-1, e); } } break; case KeyEvent.VK_DOWN: if (e.isControlDown()) { if (sideways) { adjustDx(1, e); } else { adjustDy(1, e); } } else { if (sideways) { adjustX0(1, e); } else { adjustY0(1, e); } } break; case KeyEvent.VK_LEFT: if (e.isControlDown()) { if (sideways) { adjustDy(-1, e); } else { adjustDx(-1, e); } } else { if (sideways) { adjustY0(-1, e); } else { adjustX0(-1, e); } } break; case KeyEvent.VK_RIGHT: if (e.isControlDown()) { if (sideways) { adjustDy(1, e); } else { adjustDx(1, e); } } else { if (sideways) { adjustY0(1, e); } else { adjustX0(1, e); } } break; default : return; } repaint(); e.consume(); } public void rebuild() { } public void keyReleased(KeyEvent e) { rebuild(); } public void keyTyped(KeyEvent e) { } public void mouseClicked(MouseEvent e) { if (setMode) { if (hp1 == null) { hp1 = e.getPoint(); } else if (hp2 == null) { hp2 = e.getPoint(); } else if (hp3 == null) { hp3 = e.getPoint(); calculate(); cancelSetMode(); } repaint(); } } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public void mousePressed(MouseEvent e) { } public void mouseReleased(MouseEvent e) { } protected static final int DELTA = 1; protected static final double DDELTA = 0.1; protected static final int FAST = 5; protected static final int ERROR_MARGIN = 5; protected void adjustX0(int direction, KeyEvent e) { int delta = direction * DELTA; if (e.isShiftDown()) { delta *= FAST; } Point p = grid.getOrigin(); setNewOrigin(new Point(p.x + delta, p.y)); } protected void adjustY0(int direction, KeyEvent e) { int delta = direction * DELTA; if (e.isShiftDown()) { delta *= FAST; } Point p = grid.getOrigin(); setNewOrigin(new Point(p.x, p.y + delta)); } protected void adjustDx(int direction, KeyEvent e) { double delta = direction * DDELTA; if (e.isShiftDown()) { delta *= FAST; } grid.setDx(grid.getDx() + delta); } protected void adjustDy(int direction, KeyEvent e) { double delta = direction * DDELTA; if (e.isShiftDown()) { delta *= FAST; } grid.setDy(grid.getDy() + delta); } protected void setNewOrigin(Point p) { int width = (int) Math.round(grid.getDx()); int height = (int) Math.round(grid.getDy()); if (p.x < (-width)) { p.x += width; } else if (p.x > width) { p.x -= width; } if (p.y < (-height)) { p.y += height; } else if (p.y > height) { p.y -= height; } grid.setOrigin(p); } protected boolean isHorizontal(Point p1, Point p2) { return Math.abs(p2.y - p1.y) <= ERROR_MARGIN; } protected boolean isVertical(Point p1, Point p2) { return Math.abs(p2.x - p1.x) <= ERROR_MARGIN; } protected boolean isPerpendicular(Point p1, Point p2) { return isHorizontal(p1, p2) || isVertical(p1, p2); } protected void reportShapeError() { JOptionPane.showMessageDialog(null, Resources.getString("Editor.GridEditor.does_not_look", grid.getGridName()), //$NON-NLS-1$ Resources.getString("Editor.GridEditor.grid_shape_error"), //$NON-NLS-1$ JOptionPane.ERROR_MESSAGE); } /* * Calculate and set the Origin and size of the grid * based on the the 3 selected points. */ public abstract void calculate(); /* * Panel to display the Grid Editor */ protected class GridPanel extends JPanel { private static final long serialVersionUID = 1L; protected Board board; public GridPanel() { super(); setFocusTraversalKeysEnabled(false); } public GridPanel(Board b) { this(); setBoard(b); } public void setBoard(Board b) { board = b; setSize(board.getSize()); setPreferredSize(board.getSize()); } public Board getBoard() { return board; } public void paint(Graphics g) { if (board != null) { Rectangle b = getVisibleRect(); g.clearRect(b.x, b.y, b.width, b.height); board.draw(g, 0, 0, 1.0, this); if (setMode) { highlight(g, hp1); highlight(g, hp2); highlight(g, hp3); } } else { super.paint(g); } } protected void highlight(Graphics g, Point p) { final int r1 = 3; final int r2 = 10; if (p != null) { g.setColor(Color.red); g.fillOval(p.x-r1/2, p.y-r1/2, r1, r1); g.drawOval(p.x-r2/2, p.y-r2/2, r2, r2); } } public boolean isFocusable() { return true; } } /* * Interface to be implemented by a class that wants to be edited * by RegularGridEditor */ public interface EditableGrid { public double getDx(); public double getDy(); public Point getOrigin(); public void setDx(double dx); public void setDy(double dy); public void setOrigin(Point p); public boolean isSideways(); public void setSideways(boolean sideways); public GridContainer getContainer(); public GridNumbering getGridNumbering(); public boolean isVisible(); public void setVisible(boolean b); public String getGridName(); } }