/* * $Id$ * * Copyright (c) 2004 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.mapgrid; import java.awt.AlphaComposite; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.Polygon; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.geom.Point2D; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; import javax.swing.event.MouseInputAdapter; import VASSAL.tools.SequenceEncoder; public class PolygonEditor extends JPanel { private static final long serialVersionUID = 1L; private Polygon polygon; private int selected = -1; protected JScrollPane myScroll; public PolygonEditor(Polygon p) { polygon = p; reset(); } protected void reset() { if (polygon == null || polygon.npoints == 0) { setupForCreate(); } else { setupForEdit(); } } public Polygon getPolygon() { return polygon; } public Polygon clonePolygon() { return new Polygon(polygon.xpoints, polygon.ypoints, polygon.npoints); } public void setPolygon(Polygon polygon) { this.polygon = polygon; } public void setScroll(JScrollPane scroll) { myScroll = scroll; } private void setupForCreate() { DefineRectangle dr = new DefineRectangle(); addMouseListener(dr); } private void setupForEdit() { ModifyPolygon mp = new ModifyPolygon(); addMouseListener(mp); addMouseMotionListener(mp); ActionListener l = new ActionListener() { public void actionPerformed(ActionEvent e) { if (selected >= 0) { for (int i = selected; i < polygon.npoints - 1; ++i) { polygon.xpoints[i] = polygon.xpoints[i + 1]; polygon.ypoints[i] = polygon.ypoints[i + 1]; } polygon.npoints--; selected = -1; repaint(); } } }; registerKeyboardAction(l, KeyStroke.getKeyStroke(KeyEvent.VK_DELETE,0), WHEN_IN_FOCUSED_WINDOW); registerKeyboardAction(l, KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE,0), WHEN_IN_FOCUSED_WINDOW); requestFocus(); selected = 2; repaint(); } public void center(Point p) { Rectangle r = this.getVisibleRect(); if (r.width == 0) { r.width = 600; r.height = 600; } int x = p.x-r.width/2; int y = p.y-r.height/2; if (x < 0) x = 0; if (y < 0) y = 0; scrollRectToVisible(new Rectangle(x, y, r.width, r.height)); } public static void reset(Polygon p, String path) { p.reset(); SequenceEncoder.Decoder sd = new SequenceEncoder.Decoder(path, ';'); while (sd.hasMoreTokens()) { String s = sd.nextToken(); SequenceEncoder.Decoder pd = new SequenceEncoder.Decoder(s, ','); if (pd.hasMoreTokens()) { try { int x = Integer.parseInt(pd.nextToken().trim()); if (pd.hasMoreTokens()) { int y = Integer.parseInt(pd.nextToken().trim()); p.addPoint(x, y); } } // FIXME: review error message catch (NumberFormatException e) { } } } } public static String polygonToString(Polygon p) { final StringBuilder s = new StringBuilder(); for (int i = 0; i < p.npoints; i++) { s.append(Math.round(p.xpoints[i])).append(',').append(Math.round(p.ypoints[i])); if (i < (p.npoints - 1)) { s.append(';'); } } return s.toString(); } public void paint(Graphics g) { paintBackground(g); if (polygon != null && polygon.npoints > 0) { final Graphics2D g2d = (Graphics2D) g; g2d.setColor(Color.white); g2d.setComposite( AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5F)); g2d.fill(polygon); if (selected >= 0 && selected < polygon.xpoints.length) { g2d.setColor(Color.red); int x = polygon.xpoints[selected]; int y = polygon.ypoints[selected]; g2d.fillOval(x - 10, y - 10, 20, 20); } g2d.setComposite(AlphaComposite.SrcAtop); g2d.setColor(Color.black); g2d.setStroke(new BasicStroke(2.0F)); g2d.drawPolygon(polygon); } } protected void paintBackground(Graphics g) { super.paint(g); } private class ModifyPolygon extends MouseInputAdapter { // implements java.awt.event.MouseMotionListener public void mouseDragged(MouseEvent e) { moveSelectedPoint(e); if (SwingUtilities.isLeftMouseButton(e)) { scrollAtEdge(e.getPoint(), 15); } repaint(); } private void moveSelectedPoint(MouseEvent e) { if (selected >= 0 && selected < polygon.xpoints.length) { polygon.xpoints[selected] = e.getX(); polygon.ypoints[selected] = e.getY(); } } // implements java.awt.event.MouseListener public void mouseReleased(MouseEvent e) { moveSelectedPoint(e); repaint(); } // implements java.awt.event.MouseListener public void mousePressed(MouseEvent e) { selected = -1; double minDist = Float.MAX_VALUE; for (int i = 0; i < polygon.npoints; ++i) { double dist = Point2D.distance(polygon.xpoints[i], polygon.ypoints[i], e.getX(), e.getY()); if (dist < minDist) { minDist = dist; selected = i; } } if (e.isMetaDown()) { polygon.addPoint(e.getX(), e.getY()); if (selected >= 0) { for (int i = polygon.npoints - 1; i > selected; --i) { polygon.xpoints[i] = polygon.xpoints[i - 1]; polygon.ypoints[i] = polygon.ypoints[i - 1]; } polygon.xpoints[selected] = e.getX(); polygon.ypoints[selected] = e.getY(); } } } public void scrollAtEdge(Point evtPt, int dist) { Point p = new Point(evtPt.x - myScroll.getViewport().getViewPosition().x, evtPt.y - myScroll.getViewport().getViewPosition().y); int dx = 0, dy = 0; if (p.x < dist && p.x >= 0) dx = -1; if (p.x >= myScroll.getViewport().getSize().width - dist && p.x < myScroll.getViewport().getSize().width) dx = 1; if (p.y < dist && p.y >= 0) dy = -1; if (p.y >= myScroll.getViewport().getSize().height - dist && p.y < myScroll.getViewport().getSize().height) dy = 1; if (dx != 0 || dy != 0) { Rectangle r = new Rectangle(myScroll.getViewport().getViewRect()); r.translate(2 * dist * dx, 2 * dist * dy); r = r.intersection(new Rectangle(new Point(0, 0), getPreferredSize())); scrollRectToVisible(r); } } } private class DefineRectangle extends MouseInputAdapter { // implements java.awt.event.MouseListener public void mousePressed(MouseEvent e) { polygon = new Polygon(); polygon.addPoint(e.getX(), e.getY()); polygon.addPoint(e.getX(), e.getY()); polygon.addPoint(e.getX(), e.getY()); polygon.addPoint(e.getX(), e.getY()); addMouseMotionListener(this); } // implements java.awt.event.MouseMotionListener public void mouseDragged(MouseEvent e) { polygon.xpoints[1] = e.getX(); polygon.xpoints[2] = e.getX(); polygon.ypoints[2] = e.getY(); polygon.ypoints[3] = e.getY(); repaint(); } public void mouseReleased(MouseEvent e) { removeMouseListener(this); removeMouseMotionListener(this); setupForEdit(); } } public static void main(String[] args) { JFrame f = new JFrame(); f.add(new PolygonEditor(null)); f.setSize(500, 500); f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); f.setVisible(true); } }