/*
* 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.campaignproperties;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.ListCellRenderer;
import javax.swing.ListModel;
import javax.swing.SpinnerListModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.filechooser.FileFilter;
import com.jeta.forms.components.colors.JETAColorWell;
import com.jeta.forms.components.panel.FormPanel;
import com.jeta.forms.store.properties.ListItemProperty;
import com.t3.MD5Key;
import com.t3.client.AppConstants;
import com.t3.client.AppPreferences;
import com.t3.client.ui.PreviewPanelFileChooser;
import com.t3.client.ui.token.AbstractTokenOverlay;
import com.t3.client.ui.token.BooleanTokenOverlay;
import com.t3.client.ui.token.ColorDotTokenOverlay;
import com.t3.client.ui.token.CornerImageTokenOverlay;
import com.t3.client.ui.token.CrossTokenOverlay;
import com.t3.client.ui.token.DiamondTokenOverlay;
import com.t3.client.ui.token.FlowColorDotTokenOverlay;
import com.t3.client.ui.token.FlowColorSquareTokenOverlay;
import com.t3.client.ui.token.FlowDiamondTokenOverlay;
import com.t3.client.ui.token.FlowImageTokenOverlay;
import com.t3.client.ui.token.FlowTriangleTokenOverlay;
import com.t3.client.ui.token.FlowYieldTokenOverlay;
import com.t3.client.ui.token.ImageTokenOverlay;
import com.t3.client.ui.token.OTokenOverlay;
import com.t3.client.ui.token.ShadedTokenOverlay;
import com.t3.client.ui.token.TriangleTokenOverlay;
import com.t3.client.ui.token.XTokenOverlay;
import com.t3.client.ui.token.YieldTokenOverlay;
import com.t3.model.Asset;
import com.t3.model.AssetManager;
import com.t3.model.Token;
import com.t3.model.campaign.Campaign;
import com.t3.model.campaign.CampaignProperties;
import com.t3.model.drawing.AbstractTemplate.Quadrant;
import com.t3.util.StringUtil;
/**
* This controller will handle all of the components on the States panel of the {@link CampaignPropertiesDialog}.
*
* @author Jay
*/
public class TokenStatesController implements ActionListener, DocumentListener, ListSelectionListener, ItemListener {
/** Panel containing the campaign properties form panel */
private final FormPanel formPanel;
/** The names of states currently in the list data model */
private Set<String> names = new HashSet<String>();
/** Image file chooser used to support the browse buttons */
private PreviewPanelFileChooser imageFileChooser;
/** Name of the text field containing the name {@link String} value */
public static final String NAME = "tokenStatesName";
/** Name of the text field containing the group {@link String} value */
public static final String GROUP = "tokenStatesGroup";
/**
* Name of the combo box containing a {@link String} value that maps directly to a {@link BooleanTokenOverlay} class
*/
public static final String TYPE = "tokenStatesType";
/** Name of the color well containing a {@link Color} value for token state types that need colors */
public static final String COLOR = "tokenStatesColor";
/** Name of the check box containing the {@link Boolean} mouseover value */
public static final String MOUSEOVER = "tokenStatesMouseover";
/**
* Name of the spinner containing an {@link Integer} value that is the width of lines for token state types that
* need line width
*/
public static final String WIDTH = "tokenStatesWidth";
/**
* Name of the combo box containing a {@link String} value that one of the four corners of the token and is used in
* the {@link ColorDotTokenOverlay} & {@link CornerImageTokenOverlay}
*/
public static final String CORNER = "tokenStatesCorner";
/** Name of the button used to add a new token state */
public static final String ADD = "tokenStatesAddState";
/** Name of the button used to delete selected token states */
public static final String DELETE = "tokenStatesDeleteState";
/** Name of the list containing all of the currently defined token states */
public static final String STATES = "tokenStatesStates";
/** Name of the spinner containing a {@link String} value that is converted into the grid size for flow token states */
public static final String FLOW_GRID = "tokenStatesFlowGrid";
/** Name of the spinner containing an {@link Integer} value that is the opacity used in drawing */
public static final String OPACITY = "tokenStatesOpacity";
/** Name of the text field containing a {@link File} name that is the image file used for image token states */
public static final String IMAGE = "tokenStatesImageFile";
/** Name of the button used to browse for an image icon */
public static final String BROWSE = "tokenStatesBrowseImage";
/** Name of the button used to edit an existing token state. */
public static final String UPDATE = "tokenStatesUpdateState";
/** Name of the button used to move a state up one space */
public static final String MOVE_UP = "tokenStatesMoveUp";
/** Name of the button used to move a state down one space */
public static final String MOVE_DOWN = "tokenStatesMoveDown";
/** Name of the check box that shows the GM sees the state */
public static final String SHOW_GM = "tokenStatesGM";
/** Name of the check box that shows the GM sees the state */
public static final String SHOW_OWNER = "tokenStatesOwner";
/** Name of the check box that shows the GM sees the state */
public static final String SHOW_OTHERS = "tokenStatesEverybody";
/** The size of the ICON faked in the list renderer */
public static final int ICON_SIZE = 50;
/** Each of the data entry components that can be enabled/disabled by type of state */
public static final String[] DATA_ENTRY_COMPONENTS = { COLOR, WIDTH, CORNER, FLOW_GRID, IMAGE, BROWSE };
/** Each of the data entry components that can be enabled/disabled by type of state */
public static final String[] DATA_ENTRY_COMPONENT_LABELS = { COLOR + "Label", WIDTH + "Label", CORNER + "Label", FLOW_GRID + "Label", IMAGE + "Label" };
/**
* Flags for each of the data entry components needed by each of the types. The order of the types is the' same as
* the list in the combo box. The order of the flags is the same as that in {@link #DATA_ENTRY_COMPONENTS}.
*/
public static final boolean[][] NEEDED_COMPONENTS = {
{ false, false, false, false, true, true }, // Image
{ false, false, true, false, true, true }, // Corner Image
{ false, false, false, true, true, true }, // Flow Image
{ true, false, true, false, false, false }, // Dot
{ true, false, false, true, false, false }, // Flow Dot
{ true, true, false, false, false, false }, // Circle
{ true, false, false, false, false, false }, // Shaded
{ true, true, false, false, false, false }, // X
{ true, true, false, false, false, false }, // Cross
{ true, true, false, false, false, false }, // Diamond
{ true, false, false, true, false, false }, // Flow Diamond
{ true, true, false, false, false, false }, // Yield
{ true, false, false, true, false, false }, // Flow Yield
{ true, true, false, false, false, false }, // Triangle
{ true, false, false, true, false, false }, // Flow Triangle
{ true, false, false, true, false, false }, // Flow Square
};
/**
* Set up the button listeners, spinner models, list cell renderer and selection listeners
*
* @param panel
* The {@link CampaignProperties} form panel
*/
public TokenStatesController(FormPanel panel) {
formPanel = panel;
panel.getButton(ADD).addActionListener(this);
panel.getButton(DELETE).addActionListener(this);
panel.getButton(BROWSE).addActionListener(this);
panel.getButton(UPDATE).addActionListener(this);
panel.getButton(MOVE_UP).addActionListener(this);
panel.getButton(MOVE_DOWN).addActionListener(this);
panel.getComboBox(TYPE).addActionListener(this);
panel.getSpinner(WIDTH).setModel(new SpinnerNumberModel(5, 1, 10, 1));
panel.getSpinner(FLOW_GRID).setModel(new SpinnerListModel(new String[] { "2x2", "3x3", "4x4", "5x5", "8x8" }));
panel.getSpinner(OPACITY).setModel(new SpinnerNumberModel(100, 1, 100, 5));
panel.getList(STATES).setCellRenderer(new StateListRenderer<Boolean>(Boolean.TRUE));
panel.getList(STATES).addListSelectionListener(this);
panel.getTextComponent(NAME).getDocument().addDocumentListener(this);
panel.getTextComponent(IMAGE).getDocument().addDocumentListener(this);
panel.getCheckBox(SHOW_GM).addItemListener(this);
panel.getCheckBox(SHOW_OTHERS).addItemListener(this);
panel.getCheckBox(SHOW_OWNER).addItemListener(this);
enableDataComponents();
changedUpdate(null);
}
/**
* @see java.awt.event.ItemListener#itemStateChanged(java.awt.event.ItemEvent)
*/
@Override
public void itemStateChanged(ItemEvent e) {
changedUpdate(null);
}
/**
* Handle all of the buttons & state combo box
*
* @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
@Override
public void actionPerformed(ActionEvent e) {
String name = ((JComponent) e.getSource()).getName();
JList list = formPanel.getList(STATES);
DefaultListModel model = (DefaultListModel) list.getModel();
int selected = list.getSelectedIndex();
// Add a new state
if (ADD.equals(name)) {
BooleanTokenOverlay overlay = createTokenOverlay(null);
if (overlay != null) {
model.addElement(overlay);
getNames().add(overlay.getName());
formPanel.setText(NAME, "");
formPanel.setText(GROUP, "");
formPanel.setSelected(MOUSEOVER, false);
formPanel.getSpinner(OPACITY).setValue(new Integer(100));
formPanel.setSelected(SHOW_GM, true);
formPanel.setSelected(SHOW_OWNER, true);
formPanel.setSelected(SHOW_OTHERS, true);
} // endif
// Delete selected state
} else if (DELETE.equals(name)) {
int[] selectedElements = list.getSelectedIndices();
for (int j = selectedElements.length - 1; j >= 0; j--) {
BooleanTokenOverlay overlay = (BooleanTokenOverlay) model.remove(selectedElements[j]);
getNames().remove(overlay.getName());
} // endfor
changedUpdate(null);
// Browse for an image for image token states
} else if (BROWSE.equals(name)) {
if (getImageFileChooser().showOpenDialog(formPanel) == JFileChooser.APPROVE_OPTION) {
File imageFile = getImageFileChooser().getSelectedFile();
if (imageFile == null || imageFile.isDirectory() || !imageFile.exists() || !imageFile.canRead())
return;
formPanel.setText(IMAGE, imageFile.getPath());
AppPreferences.setLoadDir(imageFile.getParentFile());
} // endif
// Change the enabled data components.
} else if (TYPE.equals(name)) {
enableDataComponents();
// Update the selected overlay
} else if (UPDATE.equals(name)) {
BooleanTokenOverlay selectedOverlay = (BooleanTokenOverlay) formPanel.getSelectedItem(STATES);
BooleanTokenOverlay overlay = createTokenOverlay(selectedOverlay);
if (overlay != null)
model.set(selected, overlay);
// Move an item up one row
} else if (MOVE_UP.equals(name)) {
Object element = model.remove(selected);
model.add(selected - 1, element);
list.setSelectedIndex(selected - 1);
list.scrollRectToVisible(list.getCellBounds(selected - 1, selected - 1));
// Move an item down one row
} else if (MOVE_DOWN.equals(name)) {
Object element = model.remove(selected);
model.add(selected + 1, element);
list.setSelectedIndex(selected + 1);
list.scrollRectToVisible(list.getCellBounds(selected + 1, selected + 1));
} // endif
}
/**
* Enable the data components needed by the selected type of overlay. Disable the rest.
*/
private void enableDataComponents() {
int selected = formPanel.getComboBox(TYPE).getSelectedIndex();
for (int i = 0; i < DATA_ENTRY_COMPONENTS.length; i++) {
formPanel.getComponentByName(DATA_ENTRY_COMPONENTS[i]).setEnabled(NEEDED_COMPONENTS[selected][i]);
if (i < DATA_ENTRY_COMPONENT_LABELS.length)
formPanel.getComponentByName(DATA_ENTRY_COMPONENT_LABELS[i]).setEnabled(NEEDED_COMPONENTS[selected][i]);
} // endfor
}
/**
* Get the file chooser which allows an image to be selected.
*
* @return The image file chooser.
*/
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";
}
});
}
return imageFileChooser;
}
/**
* Enable/disable the buttons as needed.
*
* @see javax.swing.event.DocumentListener#changedUpdate(javax.swing.event.DocumentEvent)
*/
@Override
public void changedUpdate(DocumentEvent e) {
String text = formPanel.getText(IMAGE);
boolean hasImage = !((ListItemProperty) formPanel.getSelectedItem(TYPE)).getLabel().contains("Image") || text != null && (text = text.trim()).length() != 0;
text = formPanel.getText(NAME);
boolean hasName = text != null && (text = text.trim()).length() != 0;
boolean hasShow = formPanel.isSelected(SHOW_GM) || formPanel.isSelected(SHOW_OWNER) || formPanel.isSelected(SHOW_OTHERS);
formPanel.getButton(ADD).setEnabled(hasName && !getNames().contains(text) && hasImage && hasShow);
formPanel.getButton(UPDATE).setEnabled(hasName && formPanel.getSelectedItem(STATES) != null && hasShow);
}
/**
* @see javax.swing.event.DocumentListener#insertUpdate(javax.swing.event.DocumentEvent)
*/
@Override
public void insertUpdate(DocumentEvent e) {
changedUpdate(e);
}
/**
* @see javax.swing.event.DocumentListener#removeUpdate(javax.swing.event.DocumentEvent)
*/
@Override
public void removeUpdate(DocumentEvent e) {
changedUpdate(e);
}
/**
* Handle a change in the selected list item.
*
* @see javax.swing.event.ListSelectionListener#valueChanged(javax.swing.event.ListSelectionEvent)
*/
@Override
public void valueChanged(ListSelectionEvent e) {
if (e.getValueIsAdjusting())
return;
int selected = formPanel.getList(STATES).getSelectedIndex();
formPanel.getButton(DELETE).setEnabled(selected >= 0);
changedUpdate(null); // Makes sure update is selected
formPanel.getButton(MOVE_UP).setEnabled(selected >= 1);
formPanel.getButton(MOVE_DOWN).setEnabled(selected <= formPanel.getList(STATES).getModel().getSize() - 2);
if (selected >= 0) {
// Set name, and always clear image
BooleanTokenOverlay s = (BooleanTokenOverlay) formPanel.getList(STATES).getSelectedValue();
formPanel.setText(NAME, s.getName());
formPanel.setText(GROUP, s.getGroup());
formPanel.setText(IMAGE, "");
formPanel.setSelected(MOUSEOVER, s.isMouseover());
formPanel.getSpinner(OPACITY).setValue(new Integer(s.getOpacity()));
formPanel.setSelected(SHOW_GM, s.isShowGM());
formPanel.setSelected(SHOW_OWNER, s.isShowOwner());
formPanel.setSelected(SHOW_OTHERS, s.isShowOthers());
// Get most of the colors and all of the widths from the XTokenOverlay
int type = -1;
if (s instanceof XTokenOverlay) {
type = 7;
formPanel.getSpinner(WIDTH).setValue(Integer.valueOf(((XTokenOverlay) s).getWidth()));
((JETAColorWell) formPanel.getComponentByName(COLOR)).setColor(((XTokenOverlay) s).getColor());
} // endif
// Get the the flow grid for most components from FlowColorDotTokenOverlay
if (s instanceof FlowColorDotTokenOverlay) {
type = 4;
int size = ((FlowColorDotTokenOverlay) s).getGrid();
formPanel.getSpinner(FLOW_GRID).setValue(size + "x" + size);
} // endif
// Handle the
if (s instanceof CornerImageTokenOverlay) {
type = 1;
formPanel.getComboBox(CORNER).setSelectedIndex(((CornerImageTokenOverlay) s).getCorner().ordinal());
} else if (s instanceof FlowImageTokenOverlay) {
type = 2;
int size = ((FlowImageTokenOverlay) s).getGrid(); // Still need grid size
formPanel.getSpinner(FLOW_GRID).setValue(size + "x" + size);
} else if (s instanceof ImageTokenOverlay) {
type = 0;
} else if (s instanceof ColorDotTokenOverlay) {
type = 3;
formPanel.getComboBox(CORNER).setSelectedIndex(((ColorDotTokenOverlay) s).getCorner().ordinal());
} else if (s instanceof OTokenOverlay) {
type = 5;
} else if (s instanceof ShadedTokenOverlay) {
type = 6;
((JETAColorWell) formPanel.getComponentByName(COLOR)).setColor(((ShadedTokenOverlay) s).getColor());
} else if (s instanceof CrossTokenOverlay) {
type = 8;
} else if (s instanceof DiamondTokenOverlay) {
type = 9;
} else if (s instanceof FlowDiamondTokenOverlay) {
type = 10;
} else if (s instanceof YieldTokenOverlay) {
type = 11;
} else if (s instanceof FlowYieldTokenOverlay) {
type = 12;
} else if (s instanceof TriangleTokenOverlay) {
type = 13;
} else if (s instanceof FlowTriangleTokenOverlay) {
type = 14;
} else if (s instanceof FlowColorSquareTokenOverlay) {
type = 15;
} // endif
// Set the type and change components
formPanel.getComboBox(TYPE).setSelectedIndex(type);
enableDataComponents();
}
}
/**
* The {@link ListCellRenderer} that draws the state as an icon and a state name.
*
* @author Jay
*/
public static class StateListRenderer<T> extends DefaultListCellRenderer {
public StateListRenderer (T defaultValue) {
this.value=defaultValue;
}
/** Bounds sent to the token state */
Rectangle bounds = new Rectangle(0, 0, ICON_SIZE, ICON_SIZE);
/** Fake token sent to the token state */
Token token = new Token("name", null);
/** Overlay being painted by the icon */
AbstractTokenOverlay<T> overlay;
T value;
/**
* Create an icon from the token state. The icon has a black rectangle and the actual state is drawn inside of
* it.
*/
Icon icon = new Icon() {
@Override
public int getIconHeight() {
return ICON_SIZE + 2;
}
@Override
public int getIconWidth() {
return ICON_SIZE + 2;
}
@Override
public void paintIcon(Component c, java.awt.Graphics g, int x, int y) {
g.setColor(Color.BLACK);
g.drawRect(x, y, ICON_SIZE + 2, ICON_SIZE + 2);
g.translate(x + 1, y + 1);
Shape old = g.getClip();
g.setClip(bounds.intersection(old.getBounds()));
overlay.paintOverlay((Graphics2D) g, token, bounds, value);
g.setClip(old);
g.translate(-(x + 1), -(y + 1));
}
};
/**
* Set the icon and name in the renderer.
*
* @see javax.swing.DefaultListCellRenderer#getListCellRendererComponent(javax.swing.JList, java.lang.Object,
* int, boolean, boolean)
*/
@Override
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
overlay = (AbstractTokenOverlay) value;
setText(overlay.getName());
setIcon(icon);
return this;
}
}
/**
* Copy the token states from the campaign properties to the state tab.
*
* @param campaign
* Place the states in these properties in the form panel
*/
public void copyCampaignToUI(CampaignProperties campaign) {
names.clear();
DefaultListModel<BooleanTokenOverlay> model = new DefaultListModel<BooleanTokenOverlay>();
List<BooleanTokenOverlay> overlays = new ArrayList<BooleanTokenOverlay>(campaign.getTokenStatesMap().values());
Collections.sort(overlays, BooleanTokenOverlay.COMPARATOR);
for (BooleanTokenOverlay overlay : overlays) {
model.addElement(overlay);
getNames().add(overlay.getName());
}
formPanel.getList(STATES).setModel(model);
}
/**
* Copy the token states from the state tab and place it in the passed campaign.
*
* @param campaign
* Campaign containing the properties being updated
*/
public void copyUIToCampaign(Campaign campaign) {
ListModel<BooleanTokenOverlay> model = formPanel.getList(STATES).getModel();
Map<String, BooleanTokenOverlay> states = new LinkedHashMap<String, BooleanTokenOverlay>();
for (int i = 0; i < model.getSize(); i++) {
BooleanTokenOverlay overlay = model.getElementAt(i);
overlay.setOrder(i);
states.put(overlay.getName(), overlay);
}
campaign.getTokenStatesMap().clear();
campaign.getTokenStatesMap().putAll(states);
}
/**
* Create a token state from the user's input
*
* @param updatedOverlay
* Overlay being modified.
* @return The new token state.
*/
public BooleanTokenOverlay createTokenOverlay(BooleanTokenOverlay updatedOverlay) {
// Need the color group, and name for everything
Color color = ((JETAColorWell) formPanel.getComponentByName(COLOR)).getColor();
String name = formPanel.getText(NAME);
String group = formPanel.getText(GROUP);
boolean mouseover = formPanel.isSelected(MOUSEOVER);
String overlay = ((ListItemProperty) formPanel.getSelectedItem(TYPE)).getLabel();
int opacity = getSpinner(OPACITY, "opacity", formPanel);
boolean showGM = formPanel.isSelected(SHOW_GM);
boolean showOwner = formPanel.isSelected(SHOW_OWNER);
boolean showOthers = formPanel.isSelected(SHOW_OTHERS);
// Check for overlays that don't use width
BooleanTokenOverlay to = null;
if (overlay.equals("Dot")) {
String cornerName = formPanel.getSelectedItem(CORNER).toString().toUpperCase().replace(' ', '_');
to = new ColorDotTokenOverlay(name, color, Quadrant.valueOf(cornerName));
} else if (overlay.equals("Shaded")) {
to = new ShadedTokenOverlay(name, color);
} // endif
// Get flow information
int grid = -1;
if (to == null) {
String sGrid = (String) formPanel.getSpinner(FLOW_GRID).getValue();
grid = Integer.parseInt(sGrid.substring(0, 1));
if (overlay.equals("Grid Dot")) {
to = new FlowColorDotTokenOverlay(name, color, grid);
}
if (overlay.equals("Grid Square")) {
to = new FlowColorSquareTokenOverlay(name, color, grid);
}
if (overlay.equals("Grid Triangle")) {
to = new FlowTriangleTokenOverlay(name, color, grid);
}
if (overlay.equals("Grid Diamond")) {
to = new FlowDiamondTokenOverlay(name, color, grid);
}
if (overlay.equals("Grid Yield")) {
to = new FlowYieldTokenOverlay(name, color, grid);
} // endif
} // endif
// Handle all of the overlays with width
if (to == null) {
int width = getSpinner(WIDTH, "width", formPanel);
if (overlay.equals("Circle")) {
to = new OTokenOverlay(name, color, width);
} else if (overlay.equals("X")) {
to = new XTokenOverlay(name, color, width);
} else if (overlay.equals("Cross")) {
to = new CrossTokenOverlay(name, color, width);
} else if (overlay.equals("Diamond")) {
to = new DiamondTokenOverlay(name, color, width);
} else if (overlay.equals("Yield")) {
to = new YieldTokenOverlay(name, color, width);
} else if (overlay.equals("Triangle")) {
to = new TriangleTokenOverlay(name, color, width);
} // endif
} // endif
// If we get here it is an image overlay, grab the image as an asset
if (to == null) {
MD5Key assetId = null;
String fName = formPanel.getText(IMAGE).trim();
fName = fName.length() == 0 ? null : fName;
if (updatedOverlay == null || fName != null) {
assetId = loadAsssetFile(fName, formPanel);
} else {
if (updatedOverlay instanceof ImageTokenOverlay)
assetId = ((ImageTokenOverlay) updatedOverlay).getAssetId();
} // endif
// Create all of the image overlays
if (assetId != null) {
if (overlay.equals("Image")) {
to = new ImageTokenOverlay(name, assetId);
} else if (overlay.equals("Corner Image")) {
String cornerName = formPanel.getSelectedItem(CORNER).toString().toUpperCase().replace(' ', '_');
to = new CornerImageTokenOverlay(name, assetId, Quadrant.valueOf(cornerName));
} else if (overlay.equals("Grid Image")) {
to = new FlowImageTokenOverlay(name, assetId, grid);
} // endif
} // endif
} // endif
// Set the common token stuff
if (to != null) {
to.setGroup(group);
to.setMouseover(mouseover);
to.setOpacity(opacity);
to.setShowGM(showGM);
to.setShowOthers(showOthers);
to.setShowOwner(showOwner);
} // endif
return to;
}
/**
* Read an integer value from a spinner.
*
* @param name
* Name of the spinner.
* @param displayName
* Name used in the message if there is an error.
* @param formPanel
* The form panel containing the component.
* @return The integer value selected.
*/
public static int getSpinner(String name, String displayName, FormPanel formPanel) {
int width = 0;
JSpinner spinner = formPanel.getSpinner(name);
try {
spinner.commitEdit();
width = ((Integer) spinner.getValue()).intValue();
} catch (ParseException e) {
JOptionPane.showMessageDialog(spinner, "There is an invalid " + displayName + " specified: " + ((JTextField) spinner.getEditor()).getText(),
"Error!", JOptionPane.ERROR_MESSAGE);
throw new IllegalStateException(e);
} // endtry
return width;
}
/** @return Getter for names */
public Set<String> getNames() {
return names;
}
/**
* @param names
* Setter for names
*/
public void setNames(Set<String> names) {
this.names = names;
}
/**
* Load an asset file to get its key.
*
* @param fName
* Name of the asset file (returns <code>null</code> if <b>fName</b> is empty or <code>null</code>)
* @param formPanel
* Panel to use as parent for displaying error messages
* @return The asset id if found or <code>null</code> if it could not be found.
*/
public static MD5Key loadAsssetFile(String fName, FormPanel formPanel) {
if (StringUtil.isEmpty(fName))
return null;
File file = new File(fName);
String message = null;
if (!file.exists()) {
message = "The image file does not exist: ";
} else if (!file.canRead()) {
message = "The image file cannot be read: ";
} else if (file.isDirectory()) {
message = "The file specified is a directory: ";
}
if (message != null) {
JOptionPane.showMessageDialog(formPanel, message + file.getAbsolutePath(), "Error", JOptionPane.ERROR_MESSAGE);
return null;
}
Asset asset = null;
try {
asset = AssetManager.createAsset(file);
} catch (IOException e) {
JOptionPane.showMessageDialog(formPanel, "Error reading image file: " + file.getAbsolutePath(), "Error", JOptionPane.ERROR_MESSAGE);
return null;
}
AssetManager.putAsset(asset);
return asset.getId();
}
}