//
// @(#)MetadataDialog.java 1.00 8/2002
//
// Copyright 2002 Zachary DelProposto. All rights reserved.
// Use is subject to license terms.
//
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// Or from http://www.gnu.org/
//
package dip.gui.dialog;
import dip.world.Power;
import dip.world.World;
import dip.gui.ClientFrame;
import dip.gui.AbstractCFPListener;
import dip.gui.swing.XJTextPane;
import dip.gui.swing.XJScrollPane;
import dip.gui.swing.ColorRectIcon;
import dip.gui.map.SVGColorParser;
import dip.gui.map.MapMetadata;
import dip.world.metadata.GameMetadata;
import dip.world.metadata.PlayerMetadata;
import dip.misc.Utils;
// HIGLayout
import cz.autel.dmi.HIGConstraints;
import cz.autel.dmi.HIGLayout;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.border.EtchedBorder;
import java.net.URI;
import java.net.URISyntaxException;
import java.awt.*;
/**
* Metadata Editing/Viewing dialog
* <p>
* Although the PlayerMetadata object supports multiple email addresses per player, the
* editor currently only supports upto 4.
<p>
TODO: make non-modal; but if game is destroyed, dialog must too be destroyed; if new dialog
selected, and one already exists, it must pop to the top.
*
*/
public class MetadataDialog extends HeaderDialog
{
// il8n constants
private static final String TITLE = "MetadataDialog.title";
private static final String HEADER_LOCATION = "MetadataDialog.location.header";
private static final String TAB_GAME_PANEL = "MetadataDialog.tabname.game";
// il8n constants: game data field names (notes: GDF = Game Data Field)
private static final String GDF_NOTES = "MetadataDialog.field.game.notes";
private static final String GDF_COMMENT = "MetadataDialog.field.game.comment";
private static final String GDF_GAME_NAME = "MetadataDialog.field.game.gamename";
private static final String GDF_MOD_NAME = "MetadataDialog.field.game.modname";
private static final String GDF_MOD_EMAIL = "MetadataDialog.field.game.modemail";
private static final String GDF_MOD_URI = "MetadataDialog.field.game.moduri";
private static final String GDF_JUDGE_NAME = "MetadataDialog.field.game.judgename";
private static final String GDF_GAME_URI = "MetadataDialog.field.game.gameuri";
private static final String GDF_GAME_ID = "MetadataDialog.field.game.gameid";
// il8n constants: player data field names
private static final String PDF_NOTES = "MetadataDialog.field.player.notes";
private static final String PDF_NAME = "MetadataDialog.field.player.name";
private static final String PDF_EMAIL = "MetadataDialog.field.player.email";
private static final String PDF_URI = "MetadataDialog.field.player.uri";
// misc constants
private static final int BORDER = 10;
private static final int COLUMNS = 20;
private static final int COLUMNS_LONG = 40;
// instance variables
private JTabbedPane tabPane = null;
private ClientFrame clientFrame = null;
private IconColorListener propertyListener = null; // for tab icons
private MapMetadata mmd = null; // for tab icons
/**
* Display the dialog. <br>
* Editable by default. Null metadata arguments are not permissable
*/
public static void displayDialog(ClientFrame parent)
{
MetadataDialog md = new MetadataDialog(parent);
md.pack();
md.setSize(Utils.getScreenSize(0.65f, 0.85f));
Utils.centerInScreen(md);
md.tabPane.setSelectedIndex(0); // always reset to first tab
md.setVisible(true);
}// displayDialog()
/** Creates the dialog */
private MetadataDialog(ClientFrame parent)
{
super(parent, Utils.getLocalString(TITLE), true);
this.clientFrame = parent;
mmd = clientFrame.getMapMetadata();
if(mmd == null)
{
propertyListener = new IconColorListener();
clientFrame.addPropertyChangeListener(propertyListener);
}
makeTabPanel();
setTabIcons();
setHeaderText( Utils.getText(Utils.getLocalString(HEADER_LOCATION)) );
createDefaultContentBorder(tabPane);
setContentPane(tabPane);
addTwoButtons( makeCancelButton(), makeOKButton(), false, true );
setHelpID(dip.misc.Help.HelpID.Dialog_Metadata);
}// MetadataDialog()
/** Handle OK/Cancel selections */
public void close(String actionCommand)
{
super.close(actionCommand);
if(isOKorAccept(actionCommand))
{
World world = clientFrame.getWorld();
// this isn't really the way to do it
GamePanel gp = (GamePanel) tabPane.getComponentAt(0);
GameMetadata gmd = new GameMetadata();
gp.write(gmd);
world.setGameMetadata(gmd);
// assume panels 1-n are all player panels
for(int i=1; i<tabPane.getTabCount(); i++)
{
PlayerPanel pp = (PlayerPanel) tabPane.getComponentAt(i);
PlayerMetadata pmd = new PlayerMetadata();
pp.write(pmd);
world.setPlayerMetadata(pp.getPower(), pmd);
}
// set data-changed flag
clientFrame.fireStateModified();
}
if(propertyListener != null)
{
clientFrame.removePropertyChangeListener(propertyListener);
}
}// close()
/** Make the tab panel */
private void makeTabPanel()
{
// create tabbed pane
tabPane = new JTabbedPane();
// first tab is Game info
World world = clientFrame.getWorld();
tabPane.add( Utils.getLocalString(TAB_GAME_PANEL), makeGamePanel(world.getGameMetadata()) );
// all other tabs are by Power name
Power[] powers = world.getMap().getPowers();
for(int i=0; i<powers.length; i++)
{
tabPane.add( powers[i].getName(),
makePlayerPanel(powers[i], world.getPlayerMetadata(powers[i])) );
}
}// makeTabPanel()
/** Make a GameMetadata display */
private GamePanel makeGamePanel(GameMetadata gmd)
{
GamePanel panel = new GamePanel();
panel.read(gmd);
panel.revalidate();
return panel;
}// makeGamePanel()
/** Make a PlayerMetadata display */
private JPanel makePlayerPanel(Power power, PlayerMetadata pmd)
{
PlayerPanel panel = new PlayerPanel(power);
panel.read(pmd);
panel.revalidate();
return panel;
}// makePlayerPanel()
/** n2e = null-to-empty; If field may be null, allow field to be empty.
Converts all objects to strings.
*/
private String n2e(Object in)
{
if(in == null)
{
return "";
}
return in.toString();
}// n2e()
private class GamePanel extends JPanel
{
private JTextPane notes = new JTextPane();
private JTextField comment = new JTextField(COLUMNS_LONG);
private JTextField gameName = new JTextField(COLUMNS_LONG);
private JTextField modName = new JTextField(COLUMNS_LONG);
private JTextField modEmail = Utils.createEmailTextField(COLUMNS_LONG);
private JTextField modURI = Utils.createURITextField(COLUMNS_LONG);
private JTextField judgeName = new JTextField(COLUMNS);
private JTextField gameURI = Utils.createURITextField(COLUMNS_LONG);
private JTextField gameID = new JTextField(COLUMNS);
public GamePanel()
{
notes.setBorder(new EtchedBorder());
// layout
int w1[] = { BORDER, 10, 0, 5, 0, 10, 5, 0, BORDER };
int h1[] = { BORDER, 0, 20, 0, 5, 0,10, 0,10, 0,10, 0,30, 0,10, 0,10, 0, BORDER };
HIGLayout layout = new HIGLayout(w1, h1);
layout.setColumnWeight(8,1);
this.setLayout(layout);
HIGConstraints c = new HIGConstraints();
this.add(new JLabel(Utils.getLocalString(GDF_GAME_NAME)), c.rcwh(2,3,1,1,"r"));
this.add(gameName, c.rcwh(2,5,1,1,"lr"));
this.add(new JLabel(Utils.getLocalString(GDF_NOTES)), c.rcwh(4,8,1,1,"l"));
this.add(makeScrollPane(notes), c.rcwh(6,8,1,14,"lrtb"));
this.add(new JLabel(Utils.getLocalString(GDF_COMMENT)), c.rcwh(6,3,1,1,"r"));
this.add(comment, c.rcwh(6,5,1,1,"lr"));
this.add(new JLabel(Utils.getLocalString(GDF_GAME_URI)), c.rcwh(8,3,1,1,"r"));
this.add(gameURI, c.rcwh(8,5,1,1,"lr"));
this.add(new JLabel(Utils.getLocalString(GDF_GAME_ID)), c.rcwh(10,3,1,1,"r"));
this.add(gameID, c.rcwh(10,5,1,1,"lr"));
this.add(new JLabel(Utils.getLocalString(GDF_JUDGE_NAME)), c.rcwh(12,3,1,1,"r"));
this.add(judgeName, c.rcwh(12,5,1,1,"lr"));
this.add(new JLabel(Utils.getLocalString(GDF_MOD_NAME)), c.rcwh(14,3,1,1,"r"));
this.add(modName, c.rcwh(14,5,1,1,"lr"));
this.add(new JLabel(Utils.getLocalString(GDF_MOD_EMAIL)), c.rcwh(16,3,1,1,"r"));
this.add(modEmail, c.rcwh(16,5,1,1,"lr"));
this.add(new JLabel(Utils.getLocalString(GDF_MOD_URI)), c.rcwh(18,3,1,1,"r"));
this.add(modURI, c.rcwh(18,5,1,1,"lr"));
}// GamePanel()
/** Get the panel values from the given GameMetadata object. */
public void read(GameMetadata gmd)
{
notes.setText(gmd.getNotes());
comment.setText(gmd.getComment());
gameName.setText(gmd.getGameName());
modName.setText(n2e(gmd.getModeratorName()));
modEmail.setText(n2e(gmd.getModeratorEmail()));
modURI.setText(n2e(gmd.getModeratorURI()));
judgeName.setText(n2e(gmd.getJudgeName()));
gameURI.setText(n2e(gmd.getGameURI()));
gameID.setText(gmd.getGameID());
}// read()
/** Set GameMetadata object from the entered panel values. */
public void write(GameMetadata gmd)
{
gmd.setNotes(notes.getText());
gmd.setComment(comment.getText());
gmd.setGameName(gameName.getText());
gmd.setGameID(gameID.getText());
gmd.setGameURI( convertURI(gameURI.getText()) );
gmd.setJudgeName( (judgeName.getText().length() == 0) ? null : judgeName.getText() );
gmd.setModeratorName( (modName.getText().length() == 0) ? null : modName.getText() );
gmd.setModeratorEmail( (modEmail.getText().length() == 0) ? null : modEmail.getText() );
gmd.setModeratorURI( convertURI(modURI.getText()) );
}// write()
}// inner class GamePanel
private class PlayerPanel extends JPanel
{
private JTextPane notes = new JTextPane();
private JTextField name = new JTextField(COLUMNS);
private JTextField uri = Utils.createURITextField(COLUMNS);
private JTextField[] email = new JTextField[4];
private Power power = null;
public PlayerPanel(Power power)
{
this.power = power;
notes.setBorder(new EtchedBorder());
for(int i=0; i<email.length; i++)
{
email[i] = Utils.createEmailTextField(COLUMNS);
}
// layout
int w1[] = { BORDER, 0, 5, 0, 15, 0, 5, 0, BORDER };
int h1[] = { BORDER, 0,5, 0,5, 0,5, 0,5, 0,5, 10, 0,5, 0, BORDER };
HIGLayout layout = new HIGLayout(w1, h1);
layout.setColumnWeight(5,1);
layout.setRowWeight(12, 1);
this.setLayout(layout);
HIGConstraints c = new HIGConstraints();
this.add(new JLabel(Utils.getLocalString(PDF_NAME)), c.rcwh(2,2,1,1,"r"));
this.add(name, c.rcwh(2,4,1,1,"l"));
this.add(new JLabel(Utils.getLocalString(PDF_URI)), c.rcwh(4,2,1,1,"r"));
this.add(uri, c.rcwh(4,4,1,1,"l"));
this.add(new JLabel(Utils.getLocalString(PDF_NOTES)), c.rcwh(10,2,1,1,"l"));
this.add(makeScrollPane(notes), c.rcwh(12,2,7,1,"lrtb"));
for(int i=0; i<email.length; i++)
{
int row = 2 + (i*2);
this.add(new JLabel(Utils.getLocalString(PDF_EMAIL)+" "+String.valueOf(i+1)), c.rcwh(row,6,1,1,"r"));
this.add(email[i], c.rcwh(row,8,1,1,"l"));
}
}// PlayerPanel()
/** Returns the Power associated with this PlayerPanel */
public Power getPower()
{
return power;
}// getPower()
/** Get the panel values from the given PlayerMetadata object. */
public void read(PlayerMetadata pmd)
{
notes.setText(pmd.getNotes());
name.setText(pmd.getName());
uri.setText(n2e(pmd.getURI()));
String[] tmpEmail = pmd.getEmailAddresses();
for(int i=0; i<email.length; i++)
{
if(i < tmpEmail.length)
{
email[i].setText( n2e(tmpEmail[i]) );
}
else
{
email[i].setText("");
}
}
}// read()
/** Write the panel values to the given PlayerMetadata object. */
public void write(PlayerMetadata pmd)
{
pmd.setName( name.getText() );
pmd.setURI( convertURI(uri.getText()) );
pmd.setNotes( notes.getText() );
String[] tmpEmail = new String[email.length];
for(int i=0; i<email.length; i++)
{
tmpEmail[i] = email[i].getText().trim();
}
pmd.setEmailAddresses(tmpEmail);
}// write()
}// inner class PlayerPanel
/** If can convert to URI, do it; otherwise returns null */
private static URI convertURI(String in)
{
try
{
return new URI(in);
}
catch(URISyntaxException e)
{
}
return null;
}// convertURI()
/** Creates a JScrollPane that can only scroll vertically. */
private JScrollPane makeScrollPane(JComponent c)
{
JScrollPane jsp = new XJScrollPane(c);
jsp.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
return jsp;
}// makeScrollPane()
/** Listener to get Tab Icon colors */
private class IconColorListener extends AbstractCFPListener
{
public void actionMMDReady(MapMetadata mmd)
{
MetadataDialog.this.mmd = mmd;
setTabIcons();
}// actionMMDReady()
}// nested class IconColorListener
/** Sets the tab icons for each power. */
private void setTabIcons()
{
if(mmd != null)
{
final World world = clientFrame.getWorld();
final int tabCount = tabPane.getTabCount();
for(int i=1; i<tabCount; i++) // no icon for 'game' info
{
Power power = world.getMap().getPower( tabPane.getTitleAt(i) );
assert(power != null);
String colorName = mmd.getPowerColor(power);
Color color = SVGColorParser.parseColor(colorName);
tabPane.setIconAt( i, new ColorRectIcon(12,12, color) );
}
}
}// setTabIcons()
}// class MetadataDialog