package tools.map.making; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.HeadlessException; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.List; import java.util.Map.Entry; import java.util.Properties; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JButton; import javax.swing.JColorChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.KeyStroke; import games.strategy.debug.ClientLogger; import games.strategy.engine.data.properties.PropertiesUI; import games.strategy.ui.DoubleTextField; import games.strategy.ui.IntTextField; import games.strategy.ui.SwingAction; import games.strategy.util.Tuple; import tools.image.FileOpen; import tools.image.FileSave; /** * This is the MapPropertiesMaker, it will create a map.properties file for you. <br> * The map.properties is located in the map's directory, and it will tell TripleA various * display related information about your map. <br> * Such things as the dimensions of your map, the colors of each of the players, * the size of the unit images, and how zoomed out they are, etc. <br> * To use, just fill in the information in the fields below, and click on 'Show More' to * show other, optional, fields. */ public class MapPropertiesMaker extends JFrame { private static final long serialVersionUID = 8182821091131994702L; private static File s_mapFolderLocation = null; private static final String TRIPLEA_MAP_FOLDER = "triplea.map.folder"; private static final String TRIPLEA_UNIT_ZOOM = "triplea.unit.zoom"; private static final String TRIPLEA_UNIT_WIDTH = "triplea.unit.width"; private static final String TRIPLEA_UNIT_HEIGHT = "triplea.unit.height"; private static final MapProperties s_mapProperties = new MapProperties(); private static JPanel s_playerColorChooser = new JPanel(); public static String[] getProperties() { return new String[] {TRIPLEA_MAP_FOLDER, TRIPLEA_UNIT_ZOOM, TRIPLEA_UNIT_WIDTH, TRIPLEA_UNIT_HEIGHT}; } public static void main(final String[] args) { handleCommandLineArgs(args); // JOptionPane.showMessageDialog(null, new JLabel("<html>" + "This is the MapPropertiesMaker, it will create a // map.properties file for // you. " + "</html>")); if (s_mapFolderLocation == null) { System.out.println("Select the map folder"); final String path = new FileSave("Where is your map's folder?", null, s_mapFolderLocation).getPathString(); if (path != null) { final File mapFolder = new File(path); if (mapFolder.exists()) { s_mapFolderLocation = mapFolder; System.setProperty(TRIPLEA_MAP_FOLDER, s_mapFolderLocation.getPath()); } } } if (s_mapFolderLocation != null) { final MapPropertiesMaker maker = new MapPropertiesMaker(); maker.setSize(800, 800); maker.setLocationRelativeTo(null); maker.setVisible(true); } else { System.out.println("No Map Folder Selected. Shutting down."); System.exit(0); } } // end main public MapPropertiesMaker() { super("Map Properties Maker"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.getContentPane().setLayout(new BorderLayout()); final JPanel panel = createPropertiesPanel(); this.getContentPane().add(new JScrollPane(panel), BorderLayout.CENTER); // set up the actions final Action openAction = SwingAction.of("Load Properties", e -> loadProperties()); openAction.putValue(Action.SHORT_DESCRIPTION, "Load An Existing Properties File"); final Action saveAction = SwingAction.of("Save Properties", e -> saveProperties()); saveAction.putValue(Action.SHORT_DESCRIPTION, "Save The Properties To File"); final Action exitAction = SwingAction.of("Exit", e -> System.exit(0)); exitAction.putValue(Action.SHORT_DESCRIPTION, "Exit The Program"); // set up the menu items final JMenuItem openItem = new JMenuItem(openAction); openItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_MASK)); final JMenuItem saveItem = new JMenuItem(saveAction); saveItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_MASK)); final JMenuItem exitItem = new JMenuItem(exitAction); // set up the menu bar final JMenuBar menuBar = new JMenuBar(); setJMenuBar(menuBar); final JMenu fileMenu = new JMenu("File"); fileMenu.setMnemonic('F'); // fileMenu.add(openItem); fileMenu.add(saveItem); fileMenu.addSeparator(); fileMenu.add(exitItem); menuBar.add(fileMenu); } private JPanel createPropertiesPanel() { final JPanel panel = new JPanel(); panel.setLayout(new GridBagLayout()); int row = 0; panel.add( new JLabel("<html>" + "This is the MapPropertiesMaker, it will create a map.properties file for you. " + "<br>The map.properties is located in the map's directory, and it will tell TripleA various " + "<br>display related information about your map. " + "<br>Such things as the dimensions of your map, the colors of each of the players, " + "<br>the size of the unit images, and how zoomed out they are, etc. " + "<br>To use, just fill in the information in the fields below, and click on 'Show More' to " + "<br>show other, optional, fields. " + "</html>"), new GridBagConstraints(0, row++, 2, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(20, 20, 20, 20), 0, 0)); panel.add(new JLabel("The Width in Pixels of your map: "), new GridBagConstraints(0, row, 1, 1, 1, 1, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); final IntTextField widthField = new IntTextField(0, Integer.MAX_VALUE); widthField.setText("" + s_mapProperties.getMapWidth()); widthField.addFocusListener(new FocusListener() { @Override public void focusGained(final FocusEvent e) {} @Override public void focusLost(final FocusEvent e) { try { s_mapProperties.setMapWidth(Integer.parseInt(widthField.getText())); } catch (final Exception ex) { // ignore malformed input } widthField.setText("" + s_mapProperties.getMapWidth()); } }); panel.add(widthField, new GridBagConstraints(1, row++, 1, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); panel.add(new JLabel("The Height in Pixels of your map: "), new GridBagConstraints(0, row, 1, 1, 1, 1, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); final IntTextField heightField = new IntTextField(0, Integer.MAX_VALUE); heightField.setText("" + s_mapProperties.getMapHeight()); heightField.addFocusListener(new FocusListener() { @Override public void focusGained(final FocusEvent e) {} @Override public void focusLost(final FocusEvent e) { try { s_mapProperties.setMapHeight(Integer.parseInt(heightField.getText())); } catch (final Exception ex) { // ignore malformed input } heightField.setText("" + s_mapProperties.getMapHeight()); } }); panel.add(heightField, new GridBagConstraints(1, row++, 1, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); panel.add( new JLabel("<html>The initial Scale (zoom) of your unit images: " + "<br>Must be one of: 1.25, 1, 0.875, 0.8333, 0.75, 0.6666, 0.5625, 0.5</html>"), new GridBagConstraints(0, row, 1, 1, 1, 1, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); final DoubleTextField scaleField = new DoubleTextField(0.1d, 2.0d); scaleField.setText("" + s_mapProperties.getUnitsScale()); scaleField.addFocusListener(new FocusListener() { @Override public void focusGained(final FocusEvent e) {} @Override public void focusLost(final FocusEvent e) { try { // s_mapProperties.setUNITS_SCALE(Double.parseDouble(scaleField.getText())); s_mapProperties.setUnitsScale(scaleField.getText()); } catch (final Exception ex) { // ignore malformed input } scaleField.setText("" + s_mapProperties.getUnitsScale()); } }); panel.add(scaleField, new GridBagConstraints(1, row++, 1, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); panel.add(new JLabel("Create Players and Click on the Color to set their Color: "), new GridBagConstraints(0, row++, 2, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(20, 50, 20, 50), 0, 0)); createPlayerColorChooser(); panel.add(s_playerColorChooser, new GridBagConstraints(0, row++, 2, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); final JButton showMore = new JButton("Show All Options"); showMore.addActionListener(SwingAction.of("Show All Options", e -> { final Tuple<PropertiesUI, List<MapPropertyWrapper<?>>> propertyWrapperUI = MapPropertiesMaker.s_mapProperties.propertyWrapperUI(true); JOptionPane.showMessageDialog(MapPropertiesMaker.this, propertyWrapperUI.getFirst()); s_mapProperties.writePropertiesToObject(propertyWrapperUI.getSecond()); MapPropertiesMaker.this.createPlayerColorChooser(); MapPropertiesMaker.this.validate(); MapPropertiesMaker.this.repaint(); })); panel.add(showMore, new GridBagConstraints(0, row++, 2, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); return panel; } private void createPlayerColorChooser() { s_playerColorChooser.removeAll(); s_playerColorChooser.setLayout(new GridBagLayout()); int row = 0; for (final Entry<String, Color> entry : s_mapProperties.getColorMap().entrySet()) { s_playerColorChooser.add(new JLabel(entry.getKey()), new GridBagConstraints(0, row, 1, 1, 1, 1, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); final JLabel label = new JLabel(entry.getKey()) { private static final long serialVersionUID = 5624227155029721033L; @Override public void paintComponent(final Graphics g) { final Graphics2D g2 = (Graphics2D) g; g2.setColor(entry.getValue()); g2.fill(g2.getClip()); } }; label.setBackground(entry.getValue()); label.addMouseListener(new MouseListener() { @Override public void mouseClicked(final MouseEvent e) { System.out.println(label.getBackground()); final Color color = JColorChooser.showDialog(label, "Choose color", label.getBackground()); s_mapProperties.getColorMap().put(label.getText(), color); MapPropertiesMaker.this.createPlayerColorChooser(); MapPropertiesMaker.this.validate(); MapPropertiesMaker.this.repaint(); } @Override public void mouseEntered(final MouseEvent e) {} @Override public void mouseExited(final MouseEvent e) {} @Override public void mousePressed(final MouseEvent e) {} @Override public void mouseReleased(final MouseEvent e) {} }); s_playerColorChooser.add(label, new GridBagConstraints(1, row, 1, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); final JButton removePlayer = new JButton("Remove " + entry.getKey()); removePlayer.addActionListener(new AbstractAction("Remove " + entry.getKey()) { private static final long serialVersionUID = -3593575469168341735L; @Override public void actionPerformed(final ActionEvent e) { s_mapProperties.getColorMap().remove(removePlayer.getText().replaceFirst("Remove ", "")); MapPropertiesMaker.this.createPlayerColorChooser(); MapPropertiesMaker.this.validate(); MapPropertiesMaker.this.repaint(); } }); s_playerColorChooser.add(removePlayer, new GridBagConstraints(2, row, 1, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); row++; } final JTextField nameTextField = new JTextField("Player" + (s_mapProperties.getColorMap().size() + 1)); final Dimension ourMinimum = new Dimension(150, 30); nameTextField.setMinimumSize(ourMinimum); nameTextField.setPreferredSize(ourMinimum); final JButton addPlayer = new JButton("Add Another Player"); addPlayer.addActionListener(SwingAction.of("Add Another Player", e -> { s_mapProperties.getColorMap().put(nameTextField.getText(), Color.GREEN); MapPropertiesMaker.this.createPlayerColorChooser(); MapPropertiesMaker.this.validate(); MapPropertiesMaker.this.repaint(); })); s_playerColorChooser.add(addPlayer, new GridBagConstraints(0, row, 1, 1, 1, 1, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); s_playerColorChooser.add(nameTextField, new GridBagConstraints(1, row++, 1, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); } private void loadProperties() { final Properties properties = new Properties(); try { System.out.println("Load a properties file"); final String centerName = new FileOpen("Load A Properties File", s_mapFolderLocation, ".properties").getPathString(); if (centerName == null) { return; } final FileInputStream in = new FileInputStream(centerName); properties.load(in); } catch (final HeadlessException | IOException ex) { ClientLogger.logQuietly(ex); } for (final Method setter : s_mapProperties.getClass().getMethods()) { final boolean startsWithSet = setter.getName().startsWith("set"); if (!startsWithSet) { continue; } // TODO: finish this } validate(); repaint(); } private static void saveProperties() { try { final String fileName = new FileSave("Where To Save map.properties ?", "map.properties", s_mapFolderLocation).getPathString(); if (fileName == null) { return; } final FileOutputStream sink = new FileOutputStream(fileName); final String stringToWrite = getOutPutString(); final OutputStreamWriter out = new OutputStreamWriter(sink); out.write(stringToWrite); out.flush(); out.close(); System.out.println(""); System.out.println("Data written to :" + new File(fileName).getCanonicalPath()); System.out.println(""); System.out.println(stringToWrite); } catch (final Exception e) { ClientLogger.logQuietly(e); } } private static String getOutPutString() { final StringBuilder outString = new StringBuilder(); for (final Method outMethod : s_mapProperties.getClass().getMethods()) { final boolean startsWithSet = outMethod.getName().startsWith("out"); if (!startsWithSet) { continue; } try { outString.append(outMethod.invoke(s_mapProperties)); } catch (final IllegalArgumentException | InvocationTargetException | IllegalAccessException e) { ClientLogger.logQuietly(e); } } return outString.toString(); } private static String getValue(final String arg) { final int index = arg.indexOf('='); if (index == -1) { return ""; } return arg.substring(index + 1); } private static void handleCommandLineArgs(final String[] args) { final String[] properties = getProperties(); boolean usagePrinted = false; for (final String arg2 : args) { boolean found = false; String arg = arg2; final int indexOf = arg.indexOf('='); if (indexOf > 0) { arg = arg.substring(0, indexOf); for (final String propertie : properties) { if (arg.equals(propertie)) { final String value = getValue(arg2); System.getProperties().setProperty(propertie, value); System.out.println(propertie + ":" + value); found = true; break; } } } if (!found) { System.out.println("Unrecogized:" + arg2); if (!usagePrinted) { usagePrinted = true; System.out.println("Arguments\r\n" + " " + TRIPLEA_MAP_FOLDER + "=<FILE_PATH>\r\n" + " " + TRIPLEA_UNIT_ZOOM + "=<UNIT_ZOOM_LEVEL>\r\n" + " " + TRIPLEA_UNIT_WIDTH + "=<UNIT_WIDTH>\r\n" + " " + TRIPLEA_UNIT_HEIGHT + "=<UNIT_HEIGHT>\r\n"); } } } // now account for anything set by -D final String folderString = System.getProperty(TRIPLEA_MAP_FOLDER); if (folderString != null && folderString.length() > 0) { final File mapFolder = new File(folderString); if (mapFolder.exists()) { s_mapFolderLocation = mapFolder; } else { System.out.println("Could not find directory: " + folderString); } } final String zoomString = System.getProperty(TRIPLEA_UNIT_ZOOM); if (zoomString != null && zoomString.length() > 0) { try { final double unit_zoom_percent = Double.parseDouble(zoomString); // s_mapProperties.setUNITS_SCALE(unit_zoom_percent); s_mapProperties.setUnitsScale(zoomString); System.out.println("Unit Zoom Percent to use: " + unit_zoom_percent); } catch (final Exception ex) { System.err.println("Not a decimal percentage: " + zoomString); } } final String widthString = System.getProperty(TRIPLEA_UNIT_WIDTH); if (widthString != null && widthString.length() > 0) { try { final int unit_width = Integer.parseInt(widthString); s_mapProperties.setUnitsWidth(unit_width); s_mapProperties.setUnitsCounterOffsetWidth(unit_width / 4); System.out.println("Unit Width to use: " + unit_width); } catch (final Exception ex) { System.err.println("Not an integer: " + widthString); } } final String heightString = System.getProperty(TRIPLEA_UNIT_HEIGHT); if (heightString != null && heightString.length() > 0) { try { final int unit_height = Integer.parseInt(heightString); s_mapProperties.setUnitsHeight(unit_height); s_mapProperties.setUnitsCounterOffsetHeight(unit_height); System.out.println("Unit Height to use: " + unit_height); } catch (final Exception ex) { System.err.println("Not an integer: " + heightString); } } } }