/* * Copyright (c) 2014 tabletoptool.com team. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/gpl.html * * Contributors: * rptools.com team - initial implementation * tabletoptool.com team - further development */ package com.t3.client.ui; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GridLayout; import java.awt.Image; import java.awt.Paint; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.image.BufferedImage; import java.awt.image.ImageObserver; import java.io.File; import java.io.IOException; import java.util.List; import javax.swing.AbstractAction; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JSplitPane; import javax.swing.JTextField; import javax.swing.KeyStroke; import javax.swing.filechooser.FileFilter; import com.jeta.forms.components.panel.FormPanel; import com.jeta.forms.gui.form.FormAccessor; import com.t3.client.AppConstants; import com.t3.client.AppPreferences; import com.t3.client.T3Util; import com.t3.client.TabletopTool; import com.t3.client.ui.assetpanel.AssetPanel; import com.t3.model.Asset; import com.t3.model.AssetManager; import com.t3.model.Zone; import com.t3.model.drawing.DrawablePaint; import com.t3.model.grid.Grid; import com.t3.model.grid.GridFactory; import com.t3.model.grid.GridlessGrid; import com.t3.model.grid.HexGridHorizontal; import com.t3.model.grid.HexGridVertical; import com.t3.model.grid.SquareGrid; import com.t3.swing.PaintChooser; import com.t3.swing.SelectionListener; import com.t3.swing.SwingUtil; import com.t3.util.ImageManager; import com.t3.util.StringUtil; public class MapPropertiesDialog extends JDialog { private static final int AUTO_REPEAT_THRESHOLD = 200; public enum Status { OK, CANCEL } private static File lastFilePath; private Status status; private PreviewPanelFileChooser imageFileChooser; private MapPreviewPanel imagePreviewPanel; private MapSelectorDialog mapSelectorDialog; private FormPanel formPanel; private DrawablePaint backgroundPaint; private Asset mapAsset; private DrawablePaint fogPaint; private Zone zone; private PaintChooser paintChooser; public MapPropertiesDialog(JFrame owner) { super(owner, "Map Properties", true); initialize(); pack(); } public Status getStatus() { return status; } @Override public void setVisible(boolean b) { if (b) { SwingUtil.centerOver(this, TabletopTool.getFrame()); } super.setVisible(b); } private void initialize() { setLayout(new GridLayout()); formPanel = new FormPanel("com/t3/client/ui/forms/mapPropertiesDialog.xml"); initDistanceTextField(); initOKButton(); initCancelButton(); initBackgroundButton(); initFogButton(); initMapButton(); initMapPreviewPanel(); initDistanceTextField(); initPixelsPerCellTextField(); initDefaultVisionTextField(); initHexHoriRadio(); initHexVertRadio(); initSquareRadio(); add(formPanel); // Escape key formPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "cancel"); formPanel.getActionMap().put("cancel", new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { cancel(); } }); // Color picker paintChooser = new PaintChooser(); TextureChooserPanel textureChooserPanel = new TextureChooserPanel(paintChooser, TabletopTool.getFrame().getAssetPanel().getModel(), "mapPropertiesTextureChooser"); paintChooser.addPaintChooser(textureChooserPanel); paintChooser.setPreferredSize(new Dimension(450, 400)); mapSelectorDialog = new MapSelectorDialog(); getRootPane().setDefaultButton(getOKButton()); } private void cancel() { status = Status.CANCEL; setVisible(false); } private void accept() { // Push the assets to the server T3Util.uploadTexture(backgroundPaint); T3Util.uploadTexture(fogPaint); if (mapAsset != null) { AssetManager.putAsset(mapAsset); if (!TabletopTool.isHostingServer()) { TabletopTool.serverCommand().putAsset(mapAsset); } } copyUIToZone(); status = Status.OK; setVisible(false); } public JCheckBox getRepeatCheckBox() { return formPanel.getCheckBox("repeat"); } public JRadioButton getHexHorizontalRadio() { return formPanel.getRadioButton("hexHoriRadio"); } public JRadioButton getHexVerticalRadio() { return formPanel.getRadioButton("hexVertRadio"); } public JRadioButton getSquareRadio() { return formPanel.getRadioButton("squareRadio"); } public JRadioButton getNoGridRadio() { return formPanel.getRadioButton("noGridRadio"); } public void setZone(Zone zone) { this.zone = zone; copyZoneToUI(); } private void copyZoneToUI() { getNameTextField().setText(zone.getName()); getDistanceTextField().setText(Integer.toString(zone.getUnitsPerCell())); getPixelsPerCellTextField().setText(Integer.toString(zone.getGrid().getSize())); getDefaultVisionTextField().setText(Integer.toString(zone.getTokenVisionDistance())); getHexHorizontalRadio().setSelected(zone.getGrid() instanceof HexGridHorizontal); getHexVerticalRadio().setSelected(zone.getGrid() instanceof HexGridVertical); getSquareRadio().setSelected(zone.getGrid() instanceof SquareGrid); getNoGridRadio().setSelected(zone.getGrid() instanceof GridlessGrid); fogPaint = zone.getFogPaint(); backgroundPaint = zone.getBackgroundPaint(); mapAsset = AssetManager.getAsset(zone.getMapAssetId()); } private void copyUIToZone() { zone.setName(getNameTextField().getText().trim()); zone.setUnitsPerCell(StringUtil.parseInteger(getDistanceTextField().getText(), zone.getUnitsPerCell())); zone.setGrid(createZoneGrid()); zone.setTokenVisionDistance(StringUtil.parseInteger(getDefaultVisionTextField().getText(), zone.getTokenVisionDistance())); zone.setFogPaint(fogPaint); zone.setBackgroundPaint(backgroundPaint); zone.setMapAsset(mapAsset != null ? mapAsset.getId() : null); // TODO: Handle grid type changes } private void initHexHoriRadio() { getHexHorizontalRadio().setSelected(GridFactory.isHexHorizontal(AppPreferences.getDefaultGridType())); } private void initHexVertRadio() { getHexVerticalRadio().setSelected(GridFactory.isHexVertical(AppPreferences.getDefaultGridType())); } private void initSquareRadio() { getSquareRadio().setSelected(GridFactory.isSquare(AppPreferences.getDefaultGridType())); } private void initNoGridRadio() { getNoGridRadio().setSelected(GridFactory.isNone(AppPreferences.getDefaultGridType())); } public JTextField getDistanceTextField() { return formPanel.getTextField("distance"); } private void initDistanceTextField() { getDistanceTextField().setText("5"); } private void initMapPreviewPanel() { FormAccessor accessor = formPanel.getFormAccessor("previewPanel"); JPanel previewPanel = new JPanel(new GridLayout()); previewPanel.setBorder(BorderFactory.createLineBorder(Color.darkGray)); previewPanel.add(getMapPreviewPanel()); accessor.replaceBean("mapPreviewPanel", previewPanel); } public JTextField getNameTextField() { return formPanel.getTextField("name"); } public JButton getOKButton() { return (JButton) formPanel.getButton("okButton"); } private void initOKButton() { getOKButton().addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { accept(); } }); } public JButton getBackgroundButton() { return (JButton) formPanel.getButton("backgroundButton"); } public JButton getMapButton() { return (JButton) formPanel.getButton("mapButton"); } public JButton getFogButton() { return (JButton) formPanel.getButton("fogButton"); } private void initBackgroundButton() { getBackgroundButton().addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { Paint paint = paintChooser.choosePaint(TabletopTool.getFrame(), backgroundPaint != null ? backgroundPaint.getPaint() : null, "Choose Background"); if (paint != null) { backgroundPaint = DrawablePaint.convertPaint(paint); } updatePreview(); } }); } private void initMapButton() { getMapButton().addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { Asset asset = mapSelectorDialog.chooseAsset(); if (asset == null) { return; } mapAsset = asset; getNameTextField().setText(asset.getName()); updatePreview(); } }); } private void initFogButton() { getFogButton().addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { Paint paint = paintChooser.choosePaint(TabletopTool.getFrame(), fogPaint != null ? fogPaint.getPaint() : null, "Choose Fog"); if (paint != null) { fogPaint = DrawablePaint.convertPaint(paint); } updatePreview(); } }); } private void updatePreview() { getMapPreviewPanel().repaint(); } public JButton getCancelButton() { return (JButton) formPanel.getButton("cancelButton"); } private void initCancelButton() { getCancelButton().addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { status = Status.CANCEL; setVisible(false); } }); } private PreviewPanelFileChooser getImageFileChooser() { if (imageFileChooser == null) { imageFileChooser = new PreviewPanelFileChooser(); imageFileChooser.setFileFilter(new FileFilter() { @Override public boolean accept(File f) { return f.isDirectory() || AppConstants.IMAGE_FILE_FILTER.accept(f.getAbsoluteFile(), f.getName()); } @Override public String getDescription() { return "Images only"; } }); if (lastFilePath != null) { imageFileChooser.setCurrentDirectory(lastFilePath); } } return imageFileChooser; } private MapPreviewPanel getMapPreviewPanel() { if (imagePreviewPanel == null) { imagePreviewPanel = new MapPreviewPanel(); imagePreviewPanel.setPreferredSize(new Dimension(150, 150)); imagePreviewPanel.setMinimumSize(new Dimension(150, 150)); } return imagePreviewPanel; } public JTextField getPixelsPerCellTextField() { return formPanel.getTextField("pixelsPerCell"); } private void initPixelsPerCellTextField() { getPixelsPerCellTextField().setText(Integer.toString(AppPreferences.getDefaultGridSize())); } public JTextField getDefaultVisionTextField() { return formPanel.getTextField("defaultVision"); } private void initDefaultVisionTextField() { this.getDefaultVisionTextField().setText(Integer.toString(AppPreferences.getDefaultVisionDistance())); } public String getZoneName() { return getNameTextField().getText(); } public int getZoneDistancePerCell() { try { // TODO: Handle this in validation return Integer.parseInt(getDistanceTextField().getText()); } catch (NumberFormatException nfe) { return 0; } } private Grid createZoneGrid() { Grid grid = null; if (getHexHorizontalRadio().isSelected()) { grid = GridFactory.createGrid(GridFactory.HEX_HORI, AppPreferences.getFaceEdge(), AppPreferences.getFaceVertex()); } if (getHexVerticalRadio().isSelected()) { grid = GridFactory.createGrid(GridFactory.HEX_VERT, AppPreferences.getFaceEdge(), AppPreferences.getFaceVertex()); } if (getSquareRadio().isSelected()) { grid = GridFactory.createGrid(GridFactory.SQUARE, AppPreferences.getFaceEdge(), AppPreferences.getFaceVertex()); } if (getNoGridRadio().isSelected()) { grid = GridFactory.createGrid(GridFactory.NONE); } grid.setSize(StringUtil.parseInteger(getPixelsPerCellTextField().getText(), grid.getSize())); return grid; } private class MapSelectorDialog extends JDialog { private static final long serialVersionUID = -854043369053089633L; private Asset selectedAsset; public MapSelectorDialog() { super(TabletopTool.getFrame(), true); setLayout(new BorderLayout()); add(BorderLayout.CENTER, createImageExplorerPanel()); add(BorderLayout.SOUTH, createButtonBar()); this.setTitle("Select Map Image"); setSize(500, 400); } @Override public void setVisible(boolean b) { if (b) { SwingUtil.centerOver(this, TabletopTool.getFrame()); } super.setVisible(b); } private JPanel createButtonBar() { JPanel panel = new JPanel(new BorderLayout()); JPanel leftPanel = new JPanel(); leftPanel.add(createFilesystemButton()); // leftPanel.add(createClearButton()); JPanel rightPanel = new JPanel(); rightPanel.add(createOKButton()); rightPanel.add(createCancelButton()); panel.add(BorderLayout.WEST, leftPanel); panel.add(BorderLayout.EAST, rightPanel); return panel; } private JButton createFilesystemButton() { JButton button = new JButton("Filesystem ..."); button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { setVisible(false); if (getImageFileChooser().showOpenDialog(MapPropertiesDialog.this) == JFileChooser.APPROVE_OPTION) { File imageFile = getImageFileChooser().getSelectedFile(); if (imageFile == null || imageFile.isDirectory()) { return; } lastFilePath = new File(imageFile.getParentFile() + "/."); try { selectedAsset = AssetManager.createAsset(imageFile); // Store for later use AssetManager.putAsset(selectedAsset); updatePreview(); // setBackgroundAsset(asset, getImageFileChooser().getSelectedThumbnailImage()); } catch (IOException ioe) { TabletopTool.showError("Could not load that map: " + ioe); selectedAsset = null; } } } }); return button; } // private JButton createClearButton() { // JButton button = new JButton("Clear"); // // return button; // } private JButton createOKButton() { JButton button = new JButton("OK"); button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { setVisible(false); } }); return button; } private JButton createCancelButton() { JButton button = new JButton("Cancel"); button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { selectedAsset = null; setVisible(false); } }); return button; } public Asset chooseAsset() { setVisible(true); return selectedAsset; } private JComponent createImageExplorerPanel() { final AssetPanel assetPanel = new AssetPanel("mapPropertiesImageExplorer", TabletopTool.getFrame().getAssetPanel().getModel(), JSplitPane.HORIZONTAL_SPLIT); assetPanel.addImageSelectionListener(new SelectionListener() { @Override public void selectionPerformed(List<Object> selectedList) { // There should be exactly one if (selectedList.size() != 1) { return; } Integer imageIndex = (Integer) selectedList.get(0); // if (getBackgroundAsset() != null) { // // Tighten memory usage // ImageManager.flushImage(getBackgroundAsset()); // } selectedAsset = assetPanel.getAsset(imageIndex); // Store for later use if (selectedAsset != null) { AssetManager.putAsset(selectedAsset); } } }); return assetPanel; } } private class MapPreviewPanel extends JComponent { private static final long serialVersionUID = 3761329103161077644L; @Override protected void paintComponent(Graphics g) { Dimension size = getSize(); Graphics2D g2d = (Graphics2D) g; g.setColor(Color.gray); g.fillRect(0, 0, size.width, size.height); // Tile if (backgroundPaint != null) { g2d.setPaint(backgroundPaint.getPaint(drawableObserver)); g.fillRect(0, 0, size.width, size.height); } // Fog if (fogPaint != null) { g2d.setPaint(fogPaint.getPaint()); g.fillRect(0, 0, size.width, 10); g.fillRect(0, 0, 10, size.height); g.fillRect(0, size.height - 10, size.width, 10); g.fillRect(size.width - 10, 0, 10, size.height); } // Map if (mapAsset != null) { BufferedImage image = ImageManager.getImageAndWait(mapAsset.getId()); Dimension imgSize = new Dimension(image.getWidth(), image.getHeight()); SwingUtil.constrainTo(imgSize, size.width - 10 * 4, size.height - 10 * 4); int x = (size.width - imgSize.width) / 2; int y = (size.height - imgSize.height) / 2; g.drawImage(image, x, y, imgSize.width, imgSize.height, this); } } } private final ImageObserver drawableObserver = new ImageObserver() { @Override public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) { MapPropertiesDialog.this.imagePreviewPanel.repaint(); return true; } }; }