package tools.map.xml.creator;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JViewport;
import javax.swing.SwingUtilities;
import com.google.common.collect.Maps;
import games.strategy.debug.ClientLogger;
import games.strategy.util.PointFileReaderWriter;
import tools.image.FileOpen;
/**
* Base class for image *Panel classes that show a map for defining certain map XML properties.
* It contains the polygons and center points of the territories.
*/
public abstract class ImageScrollPanePanel {
private static Font font = null;
private static MapXmlCreator mapXmlCreator;
// TODO: Check if only usage point outside this class can be erased
protected static MapXmlCreator getMapXmlCreator() {
return mapXmlCreator;
}
// hash map for polygon points
protected static Map<String, List<Polygon>> polygons = Maps.newHashMap();
public static boolean polygonsInvalid = true;
private JPanel imagePanel;
private static Map<String, Point> centers = Maps.newHashMap();
protected void layout(final JPanel stepActionPanel) {
final Dimension size = stepActionPanel.getSize();
final JScrollPane js = new JScrollPane(createImagePanel());
js.setBorder(null);
stepActionPanel.setLayout(new BorderLayout());
stepActionPanel.add(js, BorderLayout.CENTER);
stepActionPanel.setPreferredSize(size);
}
protected abstract void paintPreparation(final Map<String, Point> centers);
protected abstract void paintCenterSpecifics(final Graphics g, final String centerName, final FontMetrics fontMetrics,
final Point item, final int textStartX);
protected abstract void paintOwnSpecifics(final Graphics g, final Map<String, Point> centers);
protected abstract void mouseClickedOnImage(final Map<String, Point> centers,
final MouseEvent e);
protected void repaint() {
SwingUtilities.invokeLater(() -> imagePanel.repaint());
}
protected JPanel createImagePanel() {
if (polygonsInvalid) {
polygons.clear();
polygonsInvalid = false;
}
if (polygons.isEmpty()) {
MapXmlCreator.mapPolygonsFile = loadPolygons();
}
final Image mapImage = Toolkit.getDefaultToolkit().getImage(MapXmlCreator.mapImageFile.getAbsolutePath());
if (centers.isEmpty()) {
loadCenters();
}
paintPreparation(centers);
setImagePanel(mapImage);
return imagePanel;
}
protected void addMouseAdapterToImagePanel() {
final MouseAdapter imageMouseAdapter = new MouseAdapter() {
private final Cursor defCursor = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
private final Cursor hndCursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
private final Point pp = new Point();
@Override
public void mouseClicked(final MouseEvent e) {
mouseClickedOnImage(centers, e);
}
@Override
public void mouseDragged(final MouseEvent e) {
final JViewport vport = (JViewport) imagePanel.getParent();
final Point cp = e.getPoint();
final Point vp = vport.getViewPosition();
vp.translate(pp.x - cp.x, pp.y - cp.y);
SwingUtilities.invokeLater(() -> imagePanel.scrollRectToVisible(new Rectangle(vp, vport.getSize())));
pp.setLocation(cp);
}
@Override
public void mousePressed(final MouseEvent e) {
imagePanel.setCursor(hndCursor);
pp.setLocation(e.getPoint());
}
@Override
public void mouseReleased(final MouseEvent e) {
imagePanel.setCursor(defCursor);
pp.setLocation(e.getPoint());
}
};
imagePanel.addMouseListener(imageMouseAdapter);
imagePanel.addMouseMotionListener(imageMouseAdapter);
}
private void setImagePanel(final Image mapImage) {
imagePanel = getNewImagePanel(mapImage);
final Dimension mapImageDim = getImageDimension(mapImage);
SwingUtilities.invokeLater(() -> imagePanel
.setPreferredSize(mapImageDim));
imagePanel
.setPreferredSize(mapImageDim);
addMouseAdapterToImagePanel();
}
private JPanel getNewImagePanel(final Image mapImage) {
return new JPanel() {
private static final long serialVersionUID = -7130828419508975924L;
@Override
public void paint(final Graphics g) {
final Rectangle clipBounds = g.getClipBounds();
if (font == null) {
font = g.getFont();
} else {
g.setFont(font);
}
g.drawImage(mapImage, clipBounds.x, clipBounds.y, clipBounds.x + clipBounds.width,
clipBounds.y + clipBounds.height, clipBounds.x, clipBounds.y, clipBounds.x + clipBounds.width,
clipBounds.y + clipBounds.height, this);
paintOwnSpecifics(g, centers);
g.setColor(Color.red);
final FontMetrics fontMetrics = g.getFontMetrics();
for (final Entry<String, Point> centerEntry : centers.entrySet()) {
final String centerName = centerEntry.getKey();
final Point item = centerEntry.getValue();
final int x_text_start = item.x - centerName.length() / 2 * 5;
final Rectangle2D stringBounds = fontMetrics.getStringBounds(centerName, g);
final Rectangle boxRect = new Rectangle(Math.max(0, x_text_start - 2), Math.max(0, item.y - 6),
(int) stringBounds.getWidth() + 4, (int) stringBounds.getHeight());
if (clipBounds.intersects(boxRect)) {
g.setColor(Color.white);
g.fillRect(boxRect.x, boxRect.y, boxRect.width, boxRect.height);
g.setColor(Color.red);
g.drawString(centerName, Math.max(0, x_text_start), item.y + 5);
}
boxRect.width += boxRect.width;
boxRect.height += boxRect.height;
if (clipBounds.intersects(boxRect)) {
paintCenterSpecifics(g, centerName, fontMetrics, item, x_text_start);
}
}
}
};
}
private Dimension getImageDimension(final Image mapImage) {
return new Dimension(mapImage.getWidth(mapXmlCreator), mapImage.getHeight(mapXmlCreator));
}
protected JPanel getImagePanel() {
return imagePanel;
}
private static File loadPolygons() {
File file = null;
if (MapXmlCreator.mapPolygonsFile == null) {
if (MapXmlCreator.mapFolderLocation != null && MapXmlCreator.mapFolderLocation.exists()) {
file = new File(MapXmlCreator.mapFolderLocation, "polygons.txt");
}
if (file == null || !file.exists()) {
file = new File(MapXmlCreator.mapImageFile.getParent() + File.separator + "polygons.txt");
}
} else {
file = MapXmlCreator.mapPolygonsFile;
}
if (MapXmlCreator.mapPolygonsFile != null
|| file.exists()
&& (JOptionPane.showConfirmDialog(new JPanel(),
"A polygons.txt file was found in the map's folder, do you want to use the file to supply the "
+ "territory shapes?",
"File Suggestion",
1) == 0)) {
try {
Logger.getLogger(MapXmlCreator.MAP_XML_CREATOR_LOGGER_NAME).log(Level.INFO,
"Load Polygons from " + file.getPath());
polygons = PointFileReaderWriter.readOneToManyPolygons(new FileInputStream(file.getPath()));
} catch (final IOException ex1) {
Logger.getLogger(MapXmlCreator.MAP_XML_CREATOR_LOGGER_NAME).log(Level.SEVERE,
"Something wrong with your Polygons file");
ex1.printStackTrace();
}
} else {
try {
Logger.getLogger(MapXmlCreator.MAP_XML_CREATOR_LOGGER_NAME).log(Level.FINE, "Select the Polygons file");
final String polyPath =
new FileOpen("Select A Polygon File", MapXmlCreator.mapFolderLocation, ".txt").getPathString();
if (polyPath != null) {
Logger.getLogger(MapXmlCreator.MAP_XML_CREATOR_LOGGER_NAME).log(Level.FINE, "Polygons : " + polyPath);
polygons = PointFileReaderWriter.readOneToManyPolygons(new FileInputStream(polyPath));
} else {
Logger.getLogger(MapXmlCreator.MAP_XML_CREATOR_LOGGER_NAME).log(Level.WARNING,
"Polygons file not given. Will run regardless");
}
} catch (final IOException ex1) {
Logger.getLogger(MapXmlCreator.MAP_XML_CREATOR_LOGGER_NAME).log(Level.SEVERE,
"Something wrong with your Polygons file");
ex1.printStackTrace();
}
}
return file;
}
private static Map<String, Point> loadCenters() {
centers.clear();
final String fileName = "Load Centers from " + MapXmlCreator.mapCentersFile.getAbsolutePath();
try {
final FileInputStream in = new FileInputStream(MapXmlCreator.mapCentersFile);
centers = PointFileReaderWriter.readOneToOne(in);
} catch (final Exception ex) {
ClientLogger.logQuietly("failed to load file: " + "Load Centers from " + fileName, ex);
}
return centers;
}
protected static void setMapXmlCreator(final MapXmlCreator mapXmlCreator) {
ImageScrollPanePanel.mapXmlCreator = mapXmlCreator;
}
public ImageScrollPanePanel() {
super();
}
}