/*
* 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.token;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import javax.swing.AbstractButton;
import javax.swing.AbstractListModel;
import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.text.JTextComponent;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.RowSpec;
import com.jidesoft.grid.AbstractPropertyTableModel;
import com.jidesoft.grid.Property;
import com.jidesoft.grid.PropertyPane;
import com.jidesoft.grid.PropertyTable;
import com.jidesoft.swing.CheckBoxListWithSelectable;
import com.jidesoft.swing.DefaultSelectable;
import com.jidesoft.swing.Selectable;
import com.t3.client.T3Util;
import com.t3.client.TabletopTool;
import com.t3.client.swing.AbeillePanel;
import com.t3.client.swing.GenericDialog;
import com.t3.language.I18N;
import com.t3.model.AssetManager;
import com.t3.model.Association;
import com.t3.model.ObservableList;
import com.t3.model.Player;
import com.t3.model.Token;
import com.t3.model.TokenFootprint;
import com.t3.model.Zone.Layer;
import com.t3.model.campaign.TokenProperty;
import com.t3.model.campaign.TokenPropertyType;
import com.t3.model.grid.Grid;
import com.t3.util.ImageManager;
/**
* This dialog is used to display all of the token states and notes to the user.
*/
public class EditTokenDialog extends AbeillePanel<Token> {
private static final long serialVersionUID = 1295729281890170792L;
private boolean tokenSaved;
private GenericDialog dialog;
private ImageAssetPanel imagePanel;
// private CharSheetController controller;
/**
* The size used to constrain the icon.
*/
public static final int SIZE = 64;
/**
* Create a new token notes dialog.
*
* @param token
* The token being displayed.
*/
public EditTokenDialog() {
super("com/t3/client/ui/forms/tokenPropertiesDialog.xml");
panelInit();
}
public void initPlayerNotesTextArea() {
getNotesTextArea().addMouseListener(new MouseHandler(getNotesTextArea()));
}
public void initGMNotesTextArea() {
getGMNotesTextArea().addMouseListener(new MouseHandler(getGMNotesTextArea()));
getComponent("@GMNotes").setEnabled(TabletopTool.getPlayer().isGM());
}
public void showDialog(Token token) {
dialog = new GenericDialog(I18N.getString("EditTokenDialog.msg.title"), TabletopTool.getFrame(), this) {
private static final long serialVersionUID = 5439449816096482201L;
@Override
public void closeDialog() {
// TODO: I don't like this. There should really be a AbeilleDialog class that does this
unbind();
super.closeDialog();
}
};
bind(token);
getRootPane().setDefaultButton(getOKButton());
dialog.showDialog();
}
@Override
public void bind(final Token token) {
// ICON
getTokenIconPanel().setImageId(token.getImageAssetId());
// PROPERTIES
updatePropertyTypeCombo();
updatePropertiesTable(token.getPropertyType());
// SIGHT
updateSightTypeCombo();
// STATES
Component barPanel = null;
updateStatesPanel();
Component[] statePanels = getStatesPanel().getComponents();
for (int j = 0; j < statePanels.length; j++) {
if ("bar".equals(statePanels[j].getName())) {
barPanel = statePanels[j];
continue;
}
Component[] states = ((Container) statePanels[j]).getComponents();
for (int i = 0; i < states.length; i++) {
JCheckBox state = (JCheckBox) states[i];
state.setSelected(token.hasState(state.getText()));
}
}
// BARS
if (barPanel != null) {
Component[] bars = ((Container) barPanel).getComponents();
for (int i = 0; i < bars.length; i += 2) {
JCheckBox cb = (JCheckBox) ((Container) bars[i]).getComponent(1);
JSlider bar = (JSlider) bars[i + 1];
if (token.getBar(bar.getName()) == null) {
cb.setSelected(true);
bar.setEnabled(false);
bar.setValue(100);
} else {
cb.setSelected(false);
bar.setEnabled(true);
bar.setValue((int) (token.getBar(bar.getName()) * 100));
}
}
}
// OWNER LIST
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
getOwnerList().setModel(new OwnerListModel());
}
});
// SPEECH TABLE
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
getSpeechTable().setModel(new SpeechTableModel(token));
}
});
// Player player = TabletopTool.getPlayer();
// boolean editable = player.isGM() || !TabletopTool.getServerPolicy().useStrictTokenManagement() || token.isOwner(player.getName());
// getAllPlayersCheckBox().setSelected(token.isOwnedByAll());
// OTHER
getShapeCombo().setSelectedItem(token.getShape());
setSizeCombo(token);
getPropertyTypeCombo().setSelectedItem(token.getPropertyType());
getSightTypeCombo().setSelectedItem(token.getSightType() != null ? token.getSightType() : TabletopTool.getCampaign().getCampaignProperties().getDefaultSightType());
getCharSheetPanel().setImageId(token.getCharsheetImage());
getPortraitPanel().setImageId(token.getPortraitImage());
getTokenLayoutPanel().setToken(token);
// we will disable the Owner only visible check box if the token is not
// visible to players to signify the relationship
ActionListener tokenVisibleActionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
AbstractButton abstractButton = (AbstractButton) actionEvent.getSource();
boolean selected = abstractButton.getModel().isSelected();
getVisibleOnlyToOwnerCheckBox().setEnabled(selected);
getVisibleOnlyToOwnerLabel().setEnabled(selected);
}
};
getVisibleCheckBox().addActionListener(tokenVisibleActionListener);
// Character Sheets
// controller = null;
// String form = TabletopTool.getCampaign().getCharacterSheets().get(token.getPropertyType());
// if (form == null)
// return;
// URL formUrl = getClass().getClassLoader().getResource(form);
// if (formUrl == null)
// return;
// controller = new CharSheetController(formUrl, null);
// HashMap<String, Object> properties = new HashMap<String, Object>();
// for (String prop : token.getPropertyNames())
// properties.put(prop, token.getProperty(prop));
// controller.setData(properties);
// controller.getPanel().setName("characterSheet");
// replaceComponent("sheetPanel", "characterSheet", controller.getPanel());
super.bind(token);
}
public JTabbedPane getTabbedPane() {
return (JTabbedPane) getComponent("tabs");
}
public JTextArea getNotesTextArea() {
return (JTextArea) getComponent("@notes");
}
public JTextArea getGMNotesTextArea() {
return (JTextArea) getComponent("@GMNotes");
}
// private JLabel getGMNameLabel() {
// return (JLabel) getComponent("tokenGMNameLabel");
// }
//
// public JTextField getNameTextField() {
// return (JTextField) getComponent("tokenName");
// }
//
// public JTextField getGMNameTextField() {
// return (JTextField) getComponent("tokenGMName");
// }
public void initTypeCombo() {
DefaultComboBoxModel model = new DefaultComboBoxModel();
model.addElement(Token.Type.NPC);
model.addElement(Token.Type.PC);
// getTypeCombo().setModel(model);
}
public JComboBox getTypeCombo() {
return (JComboBox) getComponent("@type");
}
public void initTokenIconPanel() {
getTokenIconPanel().setPreferredSize(new Dimension(100, 100));
getTokenIconPanel().setMinimumSize(new Dimension(100, 100));
}
public ImageAssetPanel getTokenIconPanel() {
if (imagePanel == null) {
imagePanel = new ImageAssetPanel();
imagePanel.setAllowEmptyImage(false);
replaceComponent("mainPanel", "tokenImage", imagePanel);
}
return imagePanel;
}
public void initShapeCombo() {
getShapeCombo().setModel(new DefaultComboBoxModel<Token.TokenShape>(Token.TokenShape.values()));
}
public JComboBox<Token.TokenShape> getShapeCombo() {
return (JComboBox<Token.TokenShape>) getComponent("shape");
}
public void setSizeCombo(Token token) {
JComboBox size = getSizeCombo();
Grid grid = TabletopTool.getFrame().getCurrentZoneRenderer().getZone().getGrid();
DefaultComboBoxModel model = new DefaultComboBoxModel(grid.getFootprints().toArray());
model.insertElementAt(token.getLayer() == Layer.TOKEN ? "Native Size" : "Free Size", 0);
size.setModel(model);
if (token.isSnapToScale()) {
size.setSelectedItem(token.getFootprint(grid));
} else {
size.setSelectedIndex(0);
}
}
public void initPropertyTypeCombo() {
updatePropertyTypeCombo();
}
private void updatePropertyTypeCombo() {
List<String> typeList = new ArrayList<String>(TabletopTool.getCampaign().getTokenTypes());
Collections.sort(typeList);
DefaultComboBoxModel<String> model = new DefaultComboBoxModel<String>(typeList.toArray(new String[typeList.size()]));
getPropertyTypeCombo().setModel(model);
getPropertyTypeCombo().addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
updatePropertiesTable((String) getPropertyTypeCombo().getSelectedItem());
}
});
}
private void updateSightTypeCombo() {
List<String> typeList = new ArrayList<String>(TabletopTool.getCampaign().getSightTypes());
Collections.sort(typeList);
DefaultComboBoxModel<String> model = new DefaultComboBoxModel<String>(typeList.toArray(new String[typeList.size()]));
getSightTypeCombo().setModel(model);
}
private void updatePropertiesTable(final String propertyType) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
PropertyTable pp = getPropertyTable();
pp.setModel(new TokenPropertyTableModel());
pp.expandAll();
}
});
}
public JComboBox getSizeCombo() {
return (JComboBox) getComponent("size");
}
public JComboBox<String> getPropertyTypeCombo() {
return (JComboBox<String>) getComponent("propertyTypeCombo");
}
public JComboBox<String> getSightTypeCombo() {
return (JComboBox<String>) getComponent("sightTypeCombo");
}
public void initOKButton() {
getOKButton().addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (commit()) {
unbind();
dialog.closeDialog();
}
}
});
}
@Override
public boolean commit() {
Token token = getModel();
if (getNameField().getText().equals("")) {
TabletopTool.showError("msg.error.emptyTokenName");
return false;
}
if (getSpeechTable().isEditing()) {
getSpeechTable().getCellEditor().stopCellEditing();
}
if (getPropertyTable().isEditing()) {
getPropertyTable().getCellEditor().stopCellEditing();
}
// Commit the changes to the token properties
if (!super.commit()) {
return false;
}
// SIZE
token.setSnapToScale(getSizeCombo().getSelectedIndex() != 0);
if (getSizeCombo().getSelectedIndex() > 0) {
Grid grid = TabletopTool.getFrame().getCurrentZoneRenderer().getZone().getGrid();
token.setFootprint(grid, (TokenFootprint) getSizeCombo().getSelectedItem());
}
// Other
token.setPropertyType((String) getPropertyTypeCombo().getSelectedItem());
token.setSightType((String) getSightTypeCombo().getSelectedItem());
// Get the states
Component[] stateComponents = getStatesPanel().getComponents();
Component barPanel = null;
for (int j = 0; j < stateComponents.length; j++) {
if ("bar".equals(stateComponents[j].getName())) {
barPanel = stateComponents[j];
continue;
}
Component[] components = ((Container) stateComponents[j]).getComponents();
for (int i = 0; i < components.length; i++) {
JCheckBox cb = (JCheckBox) components[i];
String state = cb.getText();
token.setState(state, cb.isSelected());
}
} // endfor
// BARS
if (barPanel != null) {
Component[] bars = ((Container) barPanel).getComponents();
for (int i = 0; i < bars.length; i += 2) {
JCheckBox cb = (JCheckBox) ((Container) bars[i]).getComponent(1);
JSlider bar = (JSlider) bars[i + 1];
Float value = cb.isSelected() ? null : new Float(bar.getValue()/100f);
token.setBar(bar.getName(), value);
}
}
// Ownership
// If the token is owned by all and we are a player don't alter the ownership list.
if (TabletopTool.getPlayer().isGM() || !token.isOwnedByAll()) {
token.clearAllOwners();
for (int i = 0; i < getOwnerList().getModel().getSize(); i++) {
DefaultSelectable selectable = (DefaultSelectable) getOwnerList().getModel().getElementAt(i);
if (selectable.isSelected()) {
token.addOwner((String) selectable.getObject());
}
}
// If we are not a GM and the only non GM owner make sure we can't
// take our selves off of the owners list
if (!TabletopTool.getPlayer().isGM()) {
boolean hasPlayer = false;
Set<String> owners = token.getOwners();
if (owners != null) {
Iterator<Player> playerIter = TabletopTool.getPlayerList().iterator();
while (playerIter.hasNext()) {
Player pl = playerIter.next();
if (!pl.isGM() && owners.contains(pl.getName())) {
hasPlayer = true;
}
}
}
if (!hasPlayer) {
token.addOwner(TabletopTool.getPlayer().getName());
}
}
}
// SHAPE
token.setShape((Token.TokenShape) getShapeCombo().getSelectedItem());
// Macros
token.setSpeechMap(((KeyValueTableModel) getSpeechTable().getModel()).getMap());
// Properties
((TokenPropertyTableModel) getPropertyTable().getModel()).applyTo(token);
// Charsheet
if (getCharSheetPanel().getImageId() != null) {
T3Util.uploadAsset(AssetManager.getAsset(getCharSheetPanel().getImageId()));
}
token.setCharsheetImage(getCharSheetPanel().getImageId());
// IMAGE
if (!token.getImageAssetId().equals(getTokenIconPanel().getImageId())) {
BufferedImage image = ImageManager.getImageAndWait(getTokenIconPanel().getImageId());
T3Util.uploadAsset(AssetManager.getAsset(getTokenIconPanel().getImageId()));
token.setImageAsset(null, getTokenIconPanel().getImageId()); // Default image for now
token.setWidth(image.getWidth(null));
token.setHeight(image.getHeight(null));
}
// PORTRAIT
if (getPortraitPanel().getImageId() != null) {
// Make sure the server has the image
if (!TabletopTool.getCampaign().containsAsset(getPortraitPanel().getImageId())) {
TabletopTool.serverCommand().putAsset(AssetManager.getAsset(getPortraitPanel().getImageId()));
}
}
token.setPortraitImage(getPortraitPanel().getImageId());
// LAYOUT
token.setSizeScale(getTokenLayoutPanel().getSizeScale());
token.setAnchor(getTokenLayoutPanel().getAnchorX(), getTokenLayoutPanel().getAnchorY());
// OTHER
tokenSaved = true;
// Character Sheet
// Map<String, Object> properties = controller.getData();
// for (String prop : token.getPropertyNames())
// token.setProperty(prop, properties.get(prop));
// Update UI
TabletopTool.getFrame().updateTokenTree();
TabletopTool.getFrame().resetTokenPanels();
return true;
}
public JButton getOKButton() {
return (JButton) getComponent("okButton");
}
public void initCancelButton() {
getCancelButton().addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
unbind();
dialog.closeDialog();
}
});
}
public JButton getCancelButton() {
return (JButton) getComponent("cancelButton");
}
public PropertyTable getPropertyTable() {
return (PropertyTable) getComponent("propertiesTable");
}
private void updateStatesPanel() {
// Group the states first into individual panels
List<BooleanTokenOverlay> overlays = new ArrayList<BooleanTokenOverlay>(TabletopTool.getCampaign().getTokenStatesMap().values());
Map<String, JPanel> groups = new TreeMap<String, JPanel>();
groups.put("", new JPanel(new FormLayout("0px:grow 2px 0px:grow 2px 0px:grow 2px 0px:grow")));
for (BooleanTokenOverlay overlay : overlays) {
String group = overlay.getGroup();
if (group != null && (group = group.trim()).length() != 0) {
JPanel panel = groups.get(group);
if (panel == null) {
panel = new JPanel(new FormLayout("0px:grow 2px 0px:grow 2px 0px:grow 2px 0px:grow"));
panel.setBorder(BorderFactory.createTitledBorder(group));
groups.put(group, panel);
}
}
}
// Add the group panels and bar panel to the states panel
JPanel panel = getStatesPanel();
panel.removeAll();
FormLayout layout = new FormLayout("0px:grow");
panel.setLayout(layout);
int row = 1;
for (JPanel gPanel : groups.values()) {
layout.appendRow(new RowSpec("pref"));
layout.appendRow(new RowSpec("2px"));
panel.add(gPanel, new CellConstraints(1, row));
row += 2;
}
layout.appendRow(new RowSpec("pref"));
layout.appendRow(new RowSpec("2px"));
JPanel barPanel = new JPanel(new FormLayout("right:pref 2px pref 5px right:pref 2px pref"));
panel.add(barPanel, new CellConstraints(1, row));
// Add the individual check boxes.
for (BooleanTokenOverlay state : overlays) {
String group = state.getGroup();
panel = groups.get("");
if (group != null && (group = group.trim()).length() != 0)
panel = groups.get(group);
int x = panel.getComponentCount() % 4;
int y = panel.getComponentCount() / 4;
if (x == 0) {
layout = (FormLayout) panel.getLayout();
if (y != 0)
layout.appendRow(new RowSpec("2px"));
layout.appendRow(new RowSpec("pref"));
}
panel.add(new JCheckBox(state.getName()), new CellConstraints(x * 2 + 1, y * 2 + 1));
}
// Add sliders to the bar panel
if (TabletopTool.getCampaign().getTokenBarsMap().size() > 0) {
layout = (FormLayout) barPanel.getLayout();
barPanel.setName("bar");
barPanel.setBorder(BorderFactory.createTitledBorder("Bars"));
int count = 0;
row = 0;
for (BarTokenOverlay bar : TabletopTool.getCampaign().getTokenBarsMap().values()) {
int working = count % 2;
if (working == 0) { // slider row
layout.appendRow(new RowSpec("pref"));
row += 1;
}
JPanel labelPanel = new JPanel(new FormLayout("pref", "pref 2px:grow pref"));
barPanel.add(labelPanel, new CellConstraints(1 + working * 4, row));
labelPanel.add(new JLabel(bar.getName() + ":"), new CellConstraints(1, 1, CellConstraints.RIGHT, CellConstraints.TOP));
JSlider slider = new JSlider(0, 100);
JCheckBox hide = new JCheckBox("Hide");
hide.putClientProperty("JSlider", slider);
hide.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
JSlider js = (JSlider) ((JCheckBox) e.getSource()).getClientProperty("JSlider");
js.setEnabled(!((JCheckBox) e.getSource()).isSelected());
}
});
labelPanel.add(hide, new CellConstraints(1, 3, CellConstraints.RIGHT, CellConstraints.TOP));
slider.setName(bar.getName());
slider.setPaintLabels(true);
slider.setPaintTicks(true);
slider.setMajorTickSpacing(20);
slider.createStandardLabels(20);
slider.setMajorTickSpacing(10);
barPanel.add(slider, new CellConstraints(3 + working * 4, row));
if (working != 0) { // spacer row
layout.appendRow(new RowSpec("2px"));
row += 1;
}
count += 1;
}
}
}
public JPanel getStatesPanel() {
return (JPanel) getComponent("statesPanel");
}
public JTable getSpeechTable() {
return (JTable) getComponent("speechTable");
}
public JButton getSpeechClearAllButton() {
return (JButton) getComponent("speechClearAllButton");
}
private JLabel getVisibleLabel() {
return (JLabel) getComponent("visibleLabel");
}
private JCheckBox getVisibleCheckBox() {
return (JCheckBox) getComponent("@visible");
}
private JLabel getVisibleOnlyToOwnerLabel() {
return (JLabel) getComponent("visibleOnlyToOwnerLabel");
}
private JCheckBox getVisibleOnlyToOwnerCheckBox() {
return (JCheckBox) getComponent("@visibleOnlyToOwner");
}
private JPanel getGMNotesPanel() {
return (JPanel) getComponent("gmNotesPanel");
}
private JTextField getNameField() {
return (JTextField) getComponent("@name");
}
public CheckBoxListWithSelectable getOwnerList() {
return (CheckBoxListWithSelectable) getComponent("ownerList");
}
public void initSpeechPanel() {
getSpeechClearAllButton().addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (!TabletopTool.confirm("EditTokenDialog.confirm.clearSpeech")) {
return;
}
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
getSpeechTable().setModel(new SpeechTableModel());
}
});
}
});
}
public void initOwnershipPanel() {
CheckBoxListWithSelectable list = new CheckBoxListWithSelectable();
list.setName("ownerList");
replaceComponent("ownershipPanel", "ownershipList", new JScrollPane(list, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER));
}
public void initTokenDetails() {
// tokenGMNameLabel = panel.getLabel("tokenGMNameLabel");
}
public void initTokenLayoutPanel() {
TokenLayoutPanel layoutPanel = new TokenLayoutPanel();
layoutPanel.setPreferredSize(new Dimension(150, 125));
layoutPanel.setName("tokenLayout");
replaceComponent("tokenLayoutPanel", "tokenLayout", layoutPanel);
}
public void initCharsheetPanel() {
ImageAssetPanel panel = new ImageAssetPanel();
panel.setPreferredSize(new Dimension(150, 125));
panel.setName("charsheet");
panel.setLayout(new GridLayout());
replaceComponent("charsheetPanel", "charsheet", panel);
}
public void initPortraitPanel() {
ImageAssetPanel panel = new ImageAssetPanel();
panel.setPreferredSize(new Dimension(150, 125));
panel.setName("portrait");
panel.setLayout(new GridLayout());
replaceComponent("portraitPanel", "portrait", panel);
}
public ImageAssetPanel getPortraitPanel() {
return (ImageAssetPanel) getComponent("portrait");
}
public ImageAssetPanel getCharSheetPanel() {
return (ImageAssetPanel) getComponent("charsheet");
}
public TokenLayoutPanel getTokenLayoutPanel() {
return (TokenLayoutPanel) getComponent("tokenLayout");
}
public void initPropertiesPanel() {
PropertyTable propertyTable = new PropertyTable();
propertyTable.setFillsViewportHeight(true); // XXX This is Java6-only -- need Java5 solution
propertyTable.setName("propertiesTable");
PropertyPane pane = new PropertyPane(propertyTable);
// pane.setPreferredSize(new Dimension(100, 300));
replaceComponent("propertiesPanel", "propertiesTable", pane);
}
// /**
// * Set the currently displayed token.
// *
// * @param aToken
// * The token to be displayed
// */
// public void setToken(Token aToken) {
// if (aToken == token)
// return;
// if (token != null) {
// token.removeModelChangeListener(this);
// }
// token = aToken;
//
// if (token != null) {
// token.addModelChangeListener(this);
//
// List<String> typeList = new ArrayList<String>();
// typeList.addAll(TabletopTool.getCampaign().getTokenTypes());
// Collections.sort(typeList);
// getPropertyTypeCombo().setModel(new DefaultComboBoxModel(typeList.toArray()));
//
// setFields();
// updateView();
// }
// getTabbedPane().setSelectedIndex(0);
// }
/** @return Getter for tokenSaved */
public boolean isTokenSaved() {
return tokenSaved;
}
// //
// HANDLER
public class MouseHandler extends MouseAdapter {
JTextArea source;
public MouseHandler(JTextArea source) {
this.source = source;
}
@Override
public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
JPopupMenu menu = new JPopupMenu();
JMenuItem sendToChatItem = new JMenuItem("Send to Chat");
sendToChatItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String selectedText = source.getSelectedText();
if (selectedText == null) {
selectedText = source.getText();
}
// TODO: Combine this with the code in MacroButton
JTextComponent commandArea = TabletopTool.getFrame().getCommandPanel().getCommandTextArea();
commandArea.setText(commandArea.getText() + selectedText);
commandArea.requestFocusInWindow();
}
});
menu.add(sendToChatItem);
JMenuItem sendAsEmoteItem = new JMenuItem("Send as Emit");
sendAsEmoteItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String selectedText = source.getSelectedText();
if (selectedText == null) {
selectedText = source.getText();
}
// TODO: Combine this with the code in MacroButton
JTextComponent commandArea = TabletopTool.getFrame().getCommandPanel().getCommandTextArea();
commandArea.setText("/emit " + selectedText);
commandArea.requestFocusInWindow();
TabletopTool.getFrame().getCommandPanel().commitCommand();
}
});
menu.add(sendAsEmoteItem);
menu.show((JComponent) e.getSource(), e.getX(), e.getY());
}
}
}
// //
// MODELS
private class TokenPropertyTableModel extends AbstractPropertyTableModel<com.t3.client.ui.token.EditTokenDialog.TokenPropertyTableModel.EditTokenProperty> {
private static final long serialVersionUID = 2822797264738675580L;
private Map<String, Object> propertyMap;
private List<com.t3.model.campaign.TokenProperty> propertyList;
private Map<String, Object> getPropertyMap() {
Token token = getModel();
if (propertyMap == null) {
propertyMap = new HashMap<String, Object>();
List<com.t3.model.campaign.TokenProperty> propertyList = getPropertyList();
for (com.t3.model.campaign.TokenProperty property : propertyList) {
Object value = token.getProperty(property.getName());
if (value == null) {
value = property.getDefaultValue();
}
propertyMap.put(property.getName(), value);
}
}
return propertyMap;
}
private List<com.t3.model.campaign.TokenProperty> getPropertyList() {
if (propertyList == null) {
propertyList = TabletopTool.getCampaign().getTokenPropertyList((String) getPropertyTypeCombo().getSelectedItem());
}
return propertyList;
}
public void applyTo(Token token) {
for (com.t3.model.campaign.TokenProperty property : getPropertyList()) {
Object value = getPropertyMap().get(property.getName());
if (property.getDefaultValue() != null && property.getDefaultValue().equals(value)) {
token.setProperty(property.getName(), null); // Clear original value
continue;
}
token.setProperty(property.getName(), value);
}
}
@Override
public EditTokenProperty getProperty(int index) {
return new EditTokenProperty(getPropertyList().get(index));
}
@Override
public int getPropertyCount() {
return getPropertyList() != null ? getPropertyList().size() : 0;
}
class EditTokenProperty extends Property {
private static final long serialVersionUID = 4129033551005743554L;
private final String key;
private TokenPropertyType type;
public EditTokenProperty(TokenProperty property) {
super(property.getName(), property.getName(), null, (String) getPropertyTypeCombo().getSelectedItem());
this.key = property.getName();
//get Type from key
type=property.getType();
if(type.getEditorContext()!=null)
this.setEditorContext(type.getEditorContext());
}
@Override
public Object getValue() {
return getPropertyMap().get(key);
}
@Override
public void setValue(Object value) {
if(value==null)
throw new NullPointerException("Tried to set null for "+key);
else
getPropertyMap().put(key, value);
}
@Override
public boolean hasValue() {
return getPropertyMap().get(key) != null;
}
@Override
public Class<?> getType() {
return type.getType();
}
}
}
private class OwnerListModel extends AbstractListModel<Selectable> {
private static final long serialVersionUID = 2375600545516097234L;
List<Selectable> ownerList = new ArrayList<Selectable>();
public OwnerListModel() {
List<String> list = new ArrayList<String>();
Set<String> ownerSet = getModel().getOwners();
list.addAll(ownerSet);
ObservableList<Player> playerList = TabletopTool.getPlayerList();
for (Object item : playerList) {
Player player = (Player) item;
String playerId = player.getName();
if (!list.contains(playerId)) {
list.add(playerId);
}
}
Collections.sort(list);
for (String id : list) {
Selectable selectable = new DefaultSelectable(id);
selectable.setSelected(ownerSet.contains(id));
ownerList.add(selectable);
}
}
@Override
public Selectable getElementAt(int index) {
return ownerList.get(index);
}
@Override
public int getSize() {
return ownerList.size();
}
}
private static class SpeechTableModel extends KeyValueTableModel {
private static final long serialVersionUID = 1601750325218502846L;
public SpeechTableModel(Token token) {
List<Association<String, String>> rowList = new ArrayList<Association<String, String>>();
for (String speechName : token.getSpeechNames()) {
rowList.add(new Association<String, String>(speechName, token.getSpeech(speechName)));
}
Collections.sort(rowList, new Comparator<Association<String, String>>() {
@Override
public int compare(Association<String, String> o1, Association<String, String> o2) {
return o1.getLeft().compareToIgnoreCase(o2.getLeft());
}
});
init(rowList);
}
public SpeechTableModel() {
init(new ArrayList<Association<String, String>>());
}
@Override
public String getColumnName(int column) {
switch (column) {
case 0:
return I18N.getString("EditTokenDialog.msg.speech.colID");
case 1:
return I18N.getString("EditTokenDialog.msg.speech.colSpeechText");
}
return "";
}
}
private static class KeyValueTableModel extends AbstractTableModel {
private static final long serialVersionUID = -1006405977882120853L;
private Association<String, String> newRow = new Association<String, String>("", "");
private List<Association<String, String>> rowList;
protected void init(List<Association<String, String>> rowList) {
this.rowList = rowList;
}
@Override
public int getColumnCount() {
return 2;
}
@Override
public int getRowCount() {
return rowList.size() + 1;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
if (rowIndex == getRowCount() - 1) {
switch (columnIndex) {
case 0:
return newRow.getLeft();
case 1:
return newRow.getRight();
}
return "";
}
switch (columnIndex) {
case 0:
return rowList.get(rowIndex).getLeft();
case 1:
return rowList.get(rowIndex).getRight();
}
return "";
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
if (rowIndex == getRowCount() - 1) {
switch (columnIndex) {
case 0:
newRow.setLeft((String) aValue);
break;
case 1:
newRow.setRight((String) aValue);
break;
}
rowList.add(newRow);
newRow = new Association<String, String>("", "");
return;
}
switch (columnIndex) {
case 0:
rowList.get(rowIndex).setLeft((String) aValue);
break;
case 1:
rowList.get(rowIndex).setRight((String) aValue);
break;
}
}
@Override
public String getColumnName(int column) {
switch (column) {
case 0:
return I18N.getString("EditTokenDialog.msg.generic.colKey");
case 1:
return I18N.getString("EditTokenDialog.msg.generic.colValue");
}
return "";
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return true;
}
public Map<String, String> getMap() {
Map<String, String> map = new HashMap<String, String>();
for (Association<String, String> row : rowList) {
if (row.getLeft() == null || row.getLeft().trim().length() == 0) {
continue;
}
map.put(row.getLeft(), row.getRight());
}
return map;
}
}
}