/*
* (c) 2005-2009 Carlos G�mez Rodr�guez, todos los derechos reservados / all rights reserved.
* Licencia en license/bsd.txt / License in license/bsd.txt
*
* Created at regulus on 20-jul-2005 18:51:54
* as file EntityPanel.java on package org.f2o.absurdum.puck.gui.panels
*/
package org.f2o.absurdum.puck.gui.panels;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SpringLayout;
import javax.swing.SwingConstants;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.f2o.absurdum.puck.bsh.BeanShellCodeHolder;
import org.f2o.absurdum.puck.gui.graph.AbstractEntityNode;
import org.f2o.absurdum.puck.gui.graph.Arrow;
import org.f2o.absurdum.puck.gui.graph.CharacterNode;
import org.f2o.absurdum.puck.gui.graph.GraphArranger;
import org.f2o.absurdum.puck.gui.graph.GraphEditingPanel;
import org.f2o.absurdum.puck.gui.graph.ItemNode;
import org.f2o.absurdum.puck.gui.graph.Node;
import org.f2o.absurdum.puck.gui.graph.RoomNode;
import org.f2o.absurdum.puck.gui.graph.SpellNode;
import org.f2o.absurdum.puck.gui.graph.StructuralArrow;
import org.f2o.absurdum.puck.gui.panels.code.BSHCodePanel;
import org.f2o.absurdum.puck.gui.panels.code.BSHCodePanelFactory;
import org.f2o.absurdum.puck.gui.panels.code.JSyntaxBSHCodePanel;
import org.f2o.absurdum.puck.gui.util.SpringUtilities;
import org.f2o.absurdum.puck.i18n.UIMessages;
import org.f2o.absurdum.puck.util.ColorUtils;
import org.f2o.absurdum.puck.util.UniqueNameEnforcer;
import org.f2o.absurdum.puck.util.debug.Debug;
import org.f2o.absurdum.puck.util.swing.EnhancedJTextField;
import org.f2o.absurdum.puck.util.xml.DOMUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import eu.irreality.age.windowing.TabUtils;
/**
* @author carlos
*
* Created at regulus, 20-jul-2005 18:51:54
*/
public class WorldPanel extends GraphElementPanel implements BeanShellCodeHolder
{
private GraphEditingPanel gep;
private JTabbedPane jtp;
/*
private JLabel lBackground = new JLabel("Background");
private JLabel lForeground = new JLabel("Foreground");
private JLabel lDefault = new JLabel("Default");
private JLabel lDescription = new JLabel("Description");
private JLabel lInformation = new JLabel("Information");
private JLabel lAction = new JLabel("Action");
private JLabel lDenial = new JLabel("Denial");
private JLabel lError = new JLabel("Error");
private JLabel lStory = new JLabel("Story");
private JLabel lInput = new JLabel("Input");
*/
/*
private Color cBackground = Color.BLACK;
private Color cForeground = Color.BLACK;
private Color cDefault = Color.BLACK;
private Color cDescription = Color.BLACK;
private Color cInformation = Color.BLACK;
private Color cAction = Color.BLACK;
private Color cDenial = Color.BLACK;
private Color cError = Color.BLACK;
private Color cStory = Color.BLACK;
private Color cInput = Color.BLACK;
private JButton bBackground = new JButton("Background");
private JButton bForeground = new JButton("Foreground");
private JButton bDefault = new JButton("Default");
private JButton bDescription = new JButton("Description");
private JButton bInformation = new JButton("Information");
private JButton bAction = new JButton("Action");
private JButton bDenial = new JButton("Denial");
private JButton bError = new JButton("Error");
private JButton bStory = new JButton("Story");
private JButton bInput = new JButton("Input");
*/
private final String [] colorCodes = new String[]{ "Background" , "Foreground" , "Default" , "Description" ,
"Information" , "Action" , "Denial" , "Error" , "Story" , "Important", "Input" };
private final Color [] defaultColors = new Color[]{
new Color(Integer.parseInt("F7F7F7",16)), //background
new Color(Integer.parseInt("000000",16)), //foreground
new Color(Integer.parseInt("000000",16)), //default
new Color(Integer.parseInt("000099",16)), //description
new Color(Integer.parseInt("660066",16)), //information
new Color(Integer.parseInt("006600",16)), //action
new Color(Integer.parseInt("660000",16)), //denial
new Color(Integer.parseInt("663300",16)), //error
new Color(Integer.parseInt("006666",16)), //story
new Color(Integer.parseInt("CC6600",16)), //important
new Color(Integer.parseInt("0066CC",16)), //input
};
private final String [] supportedWorldLanguages = new String[]{ "es", "en", "eo", "gl", "ca" };
private final Map languageToIndex; //es->0, etc.
private HashMap colorsMap = new HashMap();
private HashMap buttonsMap = new HashMap();
public static String DEFAULT_AGE_VERSION = "1.3.6";
public void setDefaultWorldVersion()
{
tfAgeVersion.setText(DEFAULT_AGE_VERSION);
}
public WorldPanel ( final GraphEditingPanel gep )
{
super();
this.gep = gep;
setDefaultWorldVersion();
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
entitiesPanel = new EntityListPanel(gep);
//init languages combo box and languageToIndex set in a generic way, from supported world languages
languageToIndex = new HashMap();
String[] languageComboBoxLines = new String[supportedWorldLanguages.length];
for ( int i = 0 ; i < supportedWorldLanguages.length ; i++ )
{
languageComboBoxLines[i] = UIMessages.getInstance().getMessage("language." + supportedWorldLanguages[i]);
languageToIndex.put(supportedWorldLanguages[i], i);
}
cbLanguage = new JComboBox( languageComboBoxLines );
}
private int languageToIndex ( String language )
{
Integer index = (Integer) languageToIndex.get(language);
if ( index != null ) return index.intValue();
else return 0;
}
public String toString()
{
return "World Panel";
}
public String getPanelName()
{
return "World Panel";
}
//returns the index of the object in v whose name is s.
private int indexOf ( Vector v , String s )
{
for ( int i = 0 ; i < v.size() ; i++ )
{
if ( s.equals(v.get(i).toString()) )
return i;
}
return -1;
}
private JTextField tfShortName = new EnhancedJTextField();
private JTextField tfLongName = new EnhancedJTextField();
private JComboBox cbLanguage;
private JTextField tfAuthor = new EnhancedJTextField();
private JTextField tfVersion = new EnhancedJTextField();
private JTextField tfAgeVersion = new EnhancedJTextField();
private JTextField tfDate = new EnhancedJTextField();
private JTextField tfType = new EnhancedJTextField();
//private JSyntaxBSHCodePanel bcp = new JSyntaxBSHCodePanel("world");
private BSHCodePanel bcp = BSHCodePanelFactory.getInstance().createPanel("world");
private JTextField tfFontName = new EnhancedJTextField(20);
private JTextField tfFontFile = new EnhancedJTextField(20);
private JTextField tfFontSize = new EnhancedJTextField(5);
private EntityListPanel entitiesPanel;
private void styleAndAddTwo(JPanel p, JLabel l, JComponent editable)
{
l.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
p.add(l);
p.add(editable);
}
public void linkWithGraph()
{
//no doughnut!
this.removeAll();
colorsMap = new HashMap();
buttonsMap = new HashMap();
//we do need a tabbed pane!
jtp = new JTabbedPane();
this.add(jtp);
JPanel firstTab = new JPanel();
firstTab.setLayout(new BoxLayout(firstTab, BoxLayout.PAGE_AXIS));
firstTab.setBorder(BorderFactory.createTitledBorder(
UIMessages.getInstance().getMessage("worldpanel.header")));
JPanel pGeneralData = new JPanel(new SpringLayout());
styleAndAddTwo(pGeneralData,
new JLabel(UIMessages.getInstance().getMessage("world.shortname")),
tfShortName);
styleAndAddTwo(pGeneralData,
new JLabel(UIMessages.getInstance().getMessage("world.longname")),
tfLongName);
styleAndAddTwo(pGeneralData,
new JLabel(UIMessages.getInstance().getMessage("language") + ":"),
cbLanguage);
styleAndAddTwo(pGeneralData,
new JLabel(UIMessages.getInstance().getMessage("world.author")),
tfAuthor);
styleAndAddTwo(pGeneralData,
new JLabel(UIMessages.getInstance().getMessage("world.version")),
tfVersion);
styleAndAddTwo(pGeneralData,
new JLabel(UIMessages.getInstance().getMessage("world.ageversion")),
tfAgeVersion);
styleAndAddTwo(pGeneralData,
new JLabel(UIMessages.getInstance().getMessage("world.date")),
tfDate);
styleAndAddTwo(pGeneralData,
new JLabel(UIMessages.getInstance().getMessage("world.type")),
tfType);
SpringUtilities.makeCompactGrid(
pGeneralData,
8, 2, //rows, cols
6, 6, //initX, initY
6, 6 //xPad, yPad
);
firstTab.add(pGeneralData);
firstTab.add(bcp);
jtp.add("General",firstTab);
JPanel secondTab = new JPanel();
secondTab.setLayout(new BoxLayout(secondTab, BoxLayout.PAGE_AXIS));
JPanel colorsPanel = new JPanel( new GridLayout(0, 2) );
colorsPanel.setBorder(BorderFactory.createTitledBorder(UIMessages.getInstance().getMessage("label.colors")));
final JButton[] _buttons = new JButton[colorCodes.length];
for ( int i = 0 ; i < colorCodes.length ; i++ )
{
final int ind = i;
Color color;
_buttons[i] = new JButton(colorCodes[i]);
colorsPanel.add(_buttons[i]);
color = defaultColors[i];
colorsMap.put(colorCodes[i],color);
buttonsMap.put(colorCodes[i],_buttons[i]);
if ( i > 0 ) //one of the foreground colors
_buttons[i].setForeground(color);
_buttons[i].addActionListener( new ActionListener()
{
public void actionPerformed ( ActionEvent evt )
{
Color c = JColorChooser.showDialog(WorldPanel.this,"Choose Color",(Color)colorsMap.get(colorCodes[ind]));
if ( c != null )
{
_buttons[ind].setForeground(c);
colorsMap.put(colorCodes[ind],c);
if ( ind == 0 )
{
for ( int i = 1 ; i < colorCodes.length ; i++ )
{
_buttons[i].setBackground(c);
}
}
}
}
}
);
}
//set background of the visual configuration color buttons to background color
for ( int k = 1 ; k < colorCodes.length ; k++ )
_buttons[k].setBackground(defaultColors[0]); //background color
secondTab.add(colorsPanel);
JPanel fontPanel = new JPanel(new SpringLayout());
fontPanel.setMaximumSize(new Dimension(
(int)fontPanel.getMaximumSize().getWidth(),
(int)(18+6)*3) // FIXME: Take into account the font size.
);
fontPanel.setBorder(BorderFactory.createTitledBorder(UIMessages.getInstance().getMessage("label.font")));
tfFontName.setText("Lucida Sans Typewriter");
styleAndAddTwo(fontPanel,
new JLabel(UIMessages.getInstance().getMessage("label.font.name")),
tfFontName
);
styleAndAddTwo(fontPanel,
new JLabel(UIMessages.getInstance().getMessage("label.font.filename")),
tfFontFile
);
tfFontSize.setText("18");
styleAndAddTwo(fontPanel,
new JLabel(UIMessages.getInstance().getMessage("label.font.size")),
tfFontSize
);
SpringUtilities.makeCompactGrid(
fontPanel,
3, 2, //rows, cols
6, 6, //initX, initY
6, 6 //xPad, yPad
);
secondTab.add(fontPanel);
jtp.add(UIMessages.getInstance().getMessage("tab.visualconf"),secondTab);
JPanel thirdTab = new JPanel();
thirdTab.setLayout(new BoxLayout(thirdTab, BoxLayout.PAGE_AXIS));
thirdTab.add(entitiesPanel);
jtp.add(UIMessages.getInstance().getMessage("tab.entities"),thirdTab);
TabUtils.setDefaultMnemonics(jtp);
}
public void refresh()
{
entitiesPanel.refresh();
}
/**
* Obtain the language code corresponding to the language that is selected in the world language combo box.
* @return
*/
public String getSelectedLanguageCode()
{
int index = cbLanguage.getSelectedIndex();
return supportedWorldLanguages[index];
}
public org.w3c.dom.Node doGetXML ( Document d )
{
//here comes the big stuff.
org.w3c.dom.Element result = d.createElement("World");
result.setAttribute("worldName",tfShortName.getText());
result.setAttribute("moduleName",tfLongName.getText());
result.setAttribute("language",getSelectedLanguageCode());
/*
String languageString = (String) cbLanguage.getSelectedItem();
if (languageString.equals(UIMessages.getInstance().getMessage("language.en")))
result.setAttribute("language","en");
else if (languageString.equals(UIMessages.getInstance().getMessage("language.eo")))
result.setAttribute("language","eo");
else if (languageString.equals(UIMessages.getInstance().getMessage("language.gl")))
result.setAttribute("language","gl");
else
result.setAttribute("language","es");
*/
result.setAttribute("worldDir",".");
result.setAttribute("author",tfAuthor.getText());
result.setAttribute("version",tfVersion.getText());
result.setAttribute("parserVersion",tfAgeVersion.getText());
result.setAttribute("date",tfDate.getText());
result.setAttribute("type",tfType.getText());
/*check for duplicate unique names and change them if needed*/
Set usedNames = new LinkedHashSet();
for ( int i = 0 ; i < gep.getNodes().size() ; i++ )
{
Node n = (Node) gep.getNodes().get(i);
if ( n.getAssociatedPanel() instanceof EntityPanel ) //entity node
{
EntityPanel ep = (EntityPanel) n.getAssociatedPanel();
ep.checkAndIndexUniqueName();
}
}
/*meta-inf*/
Element metaElt = d.createElement("IdeMetaInf");
Element viewElt = d.createElement("View");
viewElt.setAttribute("xoffset",String.valueOf(this.getGraphEditingPanel().getViewXOffset()));
viewElt.setAttribute("yoffset",String.valueOf(this.getGraphEditingPanel().getViewYOffset()));
viewElt.setAttribute("zoom",String.valueOf(this.getGraphEditingPanel().getViewZoom()));
metaElt.appendChild(viewElt);
//We sort the world's nodes by unique name so that nodes are saved to the XML in a consistent order.
//This is to make it easier to work with diffs, patches, version control, etc. on the world files.
Vector sortedNodes = new Vector();
sortedNodes.addAll(gep.getNodes());
Collections.sort(sortedNodes);
for ( int i = 0 ; i < sortedNodes.size() ; i++ )
{
Element nodeElt = d.createElement("Node");
Node n = (Node) sortedNodes.get(i);
nodeElt.setAttribute("name",n.getName());
nodeElt.setAttribute("class",n.getClass().getName());
nodeElt.setAttribute("x",String.valueOf(n.getBounds().x));
nodeElt.setAttribute("y",String.valueOf(n.getBounds().y));
metaElt.appendChild(nodeElt);
}
result.appendChild(metaElt);
if ( bcp.getXML(d) != null )
result.appendChild(bcp.getXML(d));
/*visual conf*/
Element visConfElt = d.createElement("VisualConfiguration");
Element colorsElt = d.createElement("Colors");
visConfElt.appendChild(colorsElt);
Iterator codesIter = colorsMap.keySet().iterator();
while ( codesIter.hasNext() )
{
String colorCode = (String) codesIter.next();
Color color = (Color) colorsMap.get(colorCode);
if ( color == null ) System.err.println(colorCode + " gives us null!");
Element colorElt = d.createElement(colorCode);
colorElt.setAttribute("color","#"+ColorUtils.colorToString(color));
colorsElt.appendChild(colorElt);
}
Element fontElt = d.createElement("Font");
fontElt.setAttribute("name","Arial");
fontElt.setAttribute("size","18.0");
fontElt.setAttribute("filename","");
fontElt.setAttribute("name", tfFontName.getText());
fontElt.setAttribute("filename", tfFontFile.getText());
double size = 18.0;
try
{
size = Double.valueOf(tfFontSize.getText()).doubleValue();
}
catch ( NumberFormatException nfe )
{
System.err.println("Illegal value in font size field (must be a number): size set to default value 18.0");
}
fontElt.setAttribute("size",String.valueOf(size));
visConfElt.appendChild(fontElt);
Element roomsElt = d.createElement("Rooms");
List roomNodes = new Vector();
roomNodes.addAll(gep.getRoomNodes(false));
Collections.sort(roomNodes);
for ( int i = 0 ; i < roomNodes.size() ; i++ )
{
if ( roomNodes.get(i) instanceof RoomNode )
{
RoomNode rn = (RoomNode)roomNodes.get(i);
roomsElt.appendChild( rn.getAssociatedPanel().getXML(d) );
}
}
Element itemsElt = d.createElement("Items");
List itemNodes = new Vector();
itemNodes.addAll(gep.getItemNodes(false));
Collections.sort(itemNodes);
for ( int i = 0 ; i < itemNodes.size() ; i++ )
{
if ( itemNodes.get(i) instanceof ItemNode )
{
ItemNode rn = (ItemNode)itemNodes.get(i);
itemsElt.appendChild( rn.getAssociatedPanel().getXML(d) );
}
}
Element mobsElt = d.createElement("Mobiles");
Element playersElt = d.createElement("PlayerList");
List charNodes = new Vector();
charNodes.addAll(gep.getCharNodes(false));
Collections.sort(charNodes);
for ( int i = 0 ; i < charNodes.size() ; i++ )
{
if ( charNodes.get(i) instanceof CharacterNode )
{
CharacterNode cn = (CharacterNode)charNodes.get(i);
Element mobNode = (Element) cn.getAssociatedPanel().getXML(d);
//establish "current room" and "last room" info from relationships
for ( int j = 0 ; j < roomNodes.size() ; j++ )
{
if ( roomNodes.get(j) instanceof RoomNode )
{
RoomNode rn = (RoomNode)roomNodes.get(j);
List roomArrows = rn.getArrows();
for ( int k = 0 ; k < roomArrows.size() ; k++ )
{
Arrow a = (Arrow) roomArrows.get(k);
if ( a.getDestination().equals(cn) )
{
Element curRoomElt = d.createElement("CurrentRoom");
curRoomElt.setAttribute("id",rn.getName());
Element lastRoomElt = d.createElement("LastRoom");
lastRoomElt.setAttribute("id",rn.getName());
if ( mobNode.getElementsByTagName("CurrentRoom").getLength() == 0 )
{
mobNode.appendChild(curRoomElt);
mobNode.appendChild(lastRoomElt);
}
}
}
}
}
mobsElt.appendChild( mobNode );
//if the creature is a player, add it to the player list
CharPanel cp = (CharPanel) cn.getAssociatedPanel();
if ( cp.isPlayer() )
{
Element playerElt = d.createElement("Player");
playerElt.setAttribute("id",cn.getName());
playersElt.appendChild(playerElt);
}
}
}
Element abstractEntitiesElt = d.createElement("AbstractEntities");
List abstractEntityNodes = new Vector();
abstractEntityNodes.addAll(gep.getNodes(AbstractEntityNode.class,false));
Collections.sort(abstractEntityNodes);
for ( int i = 0 ; i < abstractEntityNodes.size() ; i++ )
{
if ( abstractEntityNodes.get(i) instanceof AbstractEntityNode )
{
AbstractEntityNode rn = (AbstractEntityNode)abstractEntityNodes.get(i);
abstractEntitiesElt.appendChild( rn.getAssociatedPanel().getXML(d) );
}
}
Element spellsElt = d.createElement("Spells");
List spellNodes = new Vector();
spellNodes.addAll(gep.getNodes(SpellNode.class,false));
Collections.sort(spellNodes);
for ( int i = 0 ; i < spellNodes.size() ; i++ )
{
if ( spellNodes.get(i) instanceof SpellNode )
{
Node rn = (Node)spellNodes.get(i);
spellsElt.appendChild( rn.getAssociatedPanel().getXML(d) );
}
}
result.appendChild(playersElt);
result.appendChild(visConfElt);
result.appendChild(roomsElt);
result.appendChild(itemsElt);
result.appendChild(mobsElt);
result.appendChild(spellsElt);
result.appendChild(abstractEntitiesElt);
return result;
}
//gets coordinates of an entity from the meta-inf node.
//if the info cannot be found in the meta-inf node, it returns null.
private Point findCoords ( org.w3c.dom.Node metaInf , String name )
{
if ( metaInf == null ) return null;
Element e = (Element) metaInf;
NodeList nl = e.getElementsByTagName("Node");
for ( int i = 0 ; i < nl.getLength() ; i++ )
{
Element elt = (Element) nl.item(i);
String eltName = elt.getAttribute("name");
if ( name.equals(eltName) )
{
int x = Integer.valueOf(elt.getAttribute("x")).intValue();
int y = Integer.valueOf(elt.getAttribute("y")).intValue();
return new Point(x,y);
}
}
return null;
}
//gets display size of an entity from the meta-inf node.
//if the info cannot be found in the meta-inf node, it returns -1.
private int findDisplaySize ( org.w3c.dom.Node metaInf , String name )
{
if ( metaInf == null ) return -1;
Element e = (Element) metaInf;
NodeList nl = e.getElementsByTagName("Node");
for ( int i = 0 ; i < nl.getLength() ; i++ )
{
Element elt = (Element) nl.item(i);
String eltName = elt.getAttribute("name");
if ( name.equals(eltName) )
{
if ( elt.hasAttribute("displaySize") )
return Integer.valueOf(elt.getAttribute("displaySize")).intValue();
else
return -1;
}
}
return -1;
}
/**
* Assigns random coordinates to some object when it is read from a file not created by PUCK
* (and therefore with unspecified -null- coordinates).
* @param coords A point representing the coordinates of an object in the world graph.
* @return If coords is not null, it returns it (the same instance), else, a new random point is created
* and returned.
*/
private Point assignRandomCoordsIfNeeded ( Point coords )
{
if ( coords == null )
{
Point coords2 = new Point();
coords2.x = 200 + (int) (Math.random()*100);
coords2.y = 200 + (int) (Math.random()*100);
return coords2;
}
else return coords;
}
/**
* Auxiliary method called by initFromXML (org.w3c.dom.Node).
* Reads the RelationshipList element and initialises custom relationships.
* @param n The entity node whose relationships will be initialised.
* @param namesToNodes A map converting the names and numeric ID's of entities to PUCK nodes.
* @param destNodeToArrow A map converting a PUCK node X to the arrow from the node associated to n to X, if such an arrow exists.
*/
public void initCustomRelationshipsFromXML ( org.w3c.dom.Node n , Map namesToNodes , Map destNodeToArrow )
{
//custom relationship
Element e = (Element)n;
NodeList relListNodes = e.getElementsByTagName("RelationshipList");
String nodeName = e.getAttribute("name");
Node src = (Node) namesToNodes.get(nodeName);
if ( relListNodes.getLength() > 0 )
{
Element relListNode = (Element) relListNodes.item(0);
NodeList relationshipNodes = relListNode.getElementsByTagName("Relationship");
for ( int j = 0 ; j < relationshipNodes.getLength() ; j++ )
{
Element relationshipNode = (Element) relationshipNodes.item(j);
String dest = relationshipNode.getAttribute("id");
Node dst = (Node) namesToNodes.get(dest);
if ( dst == null )
{
System.out.println("Warning: null destination node (rels).");
System.out.println("Target name (relationship id): " + dest);
System.out.println(e);
System.out.println(e.getAttribute("id"));
continue;
}
Arrow theArrow = (Arrow) destNodeToArrow.get(dst);
if ( theArrow == null )
{
/*
* If we enter this if statement, there is no structural relationship
* between the nodes, only custom relationships. So we create a new arrow between
* the nodes (since none has been created during the initialization of structural
* relationships) and set the structural relationship type of its associated
* panel to "none".
*/
theArrow = new StructuralArrow();
destNodeToArrow.put(dst,theArrow);
theArrow.setSource(src);
theArrow.setDestination(dst);
src.addArrow(theArrow);
if ( theArrow.getAssociatedPanel() instanceof ArrowPanel ) //TODO When custom relationship system is completed, this if check won't be necessary.
((ArrowPanel)theArrow.getAssociatedPanel()).setRelationshipType(ArrowPanel.NO_STRUCTURAL_RELATIONSHIP);
gep.getPropertiesPanel().loadWithoutShowing(theArrow);
theArrow.getAssociatedPanel().initFromXML(relationshipNode); //panel init
}
if ( theArrow.getAssociatedPanel() instanceof ArrowPanel ) //TODO When custom relationship system is completed, this if check won't be necessary.
((ArrowPanel)theArrow.getAssociatedPanel()).initCustomRelationshipsFromXML(relationshipNode);
}
}
}
/**
*
* @param entityNode The valid XML element defining an entity.
* @param namesToNodes Names-to-nodes map. Unused parameter.
* @param dispSize Display size for the node, -1 for default size (e.g. for pasted nodes).
* @param coords (x,y) coordinates to add the node. May be null for random coordinates.
*/
public void addEntityFromXML ( Element entityNode , Map unusedParameter , int dispSize , Point coords )
{
String entityName = entityNode.getAttribute("name");
//entityName = UniqueNameEnforcer.makeUnique(entityName,namesToNodes); //didn't work, because then we call initFromXML which ignores this
String entityId = entityNode.getAttribute("id");
coords = assignRandomCoordsIfNeeded(coords);
//add the node
String type = entityNode.getTagName();
Node rn;
if ( type.equalsIgnoreCase("Room") )
rn = new RoomNode(coords.x,coords.y);
else if ( type.equalsIgnoreCase("Item") )
rn = new ItemNode(coords.x,coords.y);
else if ( type.equalsIgnoreCase("Mobile") )
rn = new CharacterNode(coords.x,coords.y);
else if ( type.equalsIgnoreCase("Spell") )
rn = new SpellNode(coords.x,coords.y);
else if ( type.equalsIgnoreCase("AbstractEntity") )
rn = new AbstractEntityNode(coords.x,coords.y);
else
rn = null;
//this also updates the maps:
gep.addNode(rn);
//this is currently redundant, done by gep.addNode(...), probably can remove <- no, not the ID! the ID is not redundant.
if ( namesToNodes != null ) //should not be null if called when building the world. Should be null if called from a paste action, f. ex.
{
namesToNodes.put(entityName,rn);
nodesToNames.put(rn, entityName);
if ( entityId.length() > 0 )
{
namesToNodes.put(entityId,rn);
//idsToNames.put(roomId,roomName);
}
}
if ( dispSize >= 0 ) rn.setExplicitSize(dispSize);
gep.getPropertiesPanel().loadWithoutShowing(rn);
rn.getAssociatedPanel().initFromXML(entityNode);
rn.getAssociatedPanel().initMinimal(); //updated with data from xml
panelsToNodes.put(rn.getAssociatedPanel(),rn);
}
/**
* @param entityNode The valid XML element defining an entity.
* @param metaInfNode The meta-inf node with info like coordinates of nodes, their size, etc. May be null.
* @param namesToNodes Names-to-nodes map. May be null.
* @param changeNameIfNotUnique Generate an unique name for the node if it's not already unique?
*/
public void addEntityFromXML ( Element entityNode, Element metaInfNode , Map namesToNodes )
{
String entityName = entityNode.getAttribute("name");
//entityName = UniqueNameEnforcer.makeUnique(entityName,namesToNodes); //didn't work, because then we call initFromXML which ignores this
String entityId = entityNode.getAttribute("id");
Point coords = findCoords(metaInfNode,entityName);
int dispSize = findDisplaySize(metaInfNode,entityName);
addEntityFromXML ( entityNode , namesToNodes , dispSize , coords );
}
/**This map converts both unique names and legacy numeric ID's of entities to their associated PUCK map nodes.
* It is used for searches and to check that no two nodes are given the same unique name.*/
private Map namesToNodes = new TreeMap();
/**This map converts PUCK entity nodes to their unique names that are stored in namesToNodes (but not to numeric ID's). The
* only purpose of this map is actually to be able to update namesToNodes when a node changes its name.*/
private Map nodesToNames = new HashMap();
private Map panelsToNodes = new HashMap();
public Node nameToNode ( String name )
{
return (Node) namesToNodes.get(name);
}
public String nodeToName ( Node node )
{
return (String) nodesToNames.get(node);
}
public Node panelToNode ( EntityPanel panel )
{
return (Node) panelsToNodes.get(panel);
}
public void updateMaps ( Node node )
{
GraphElementPanel panel = node.getAssociatedPanel();
String name = node.getName(); //note that getAssociatedPanel() may set the name if this is a newly created node -> order of these two lines is important
String oldName = (String) nodesToNames.get(node);
nodesToNames.remove(node);
nodesToNames.put(node,name);
if ( oldName != null )
namesToNodes.remove(oldName);
namesToNodes.put(name,node);
panelsToNodes.remove(panel);
panelsToNodes.put(panel,node);
}
public void removeFromMaps ( Node node)
{
String name = node.getName();
GraphElementPanel panel = node.getAssociatedPanel();
nodesToNames.remove(node);
namesToNodes.remove(name);
panelsToNodes.remove(panel);
}
// from World node... the big great initializer, initializing the GEP too!!!
public void doInitFromXML ( org.w3c.dom.Node n )
{
Element e = (Element) n;
//gep.getPropertiesPanel().loadWithoutShowing(gep.getWorldNode()); //includes linkWithGraph() -> no longer
gep.getPropertiesPanel().show(gep.getWorldNode()); //else we won't init it correctly
//init tf's
Debug.println("[init world] Loading general world info...");
tfShortName.setText(e.getAttribute("worldName"));
tfLongName.setText(e.getAttribute("moduleName"));
//languages combo box
/*
if ( e.hasAttribute("language") && e.getAttribute("language").equals("en") )
cbLanguage.setSelectedIndex(1);
else if ( e.hasAttribute("language") && e.getAttribute("language").equals("eo") )
cbLanguage.setSelectedIndex(2);
else if ( e.hasAttribute("language") && e.getAttribute("language").equals("gl") )
cbLanguage.setSelectedIndex(3);
else if ( e.hasAttribute("language") && e.getAttribute("language").equals("ca") )
cbLanguage.setSelectedIndex(4);
else
cbLanguage.setSelectedIndex(0);
*/
cbLanguage.setSelectedIndex(languageToIndex(e.getAttribute("language")));
tfAuthor.setText(e.getAttribute("author"));
tfVersion.setText(e.getAttribute("version"));
tfAgeVersion.setText(e.getAttribute("parserVersion"));
tfDate.setText(e.getAttribute("date"));
tfType.setText(e.getAttribute("type"));
//bsh code panel
Debug.println("[init world] Loading world bsh code...");
NodeList codeNl = DOMUtils.getDirectChildrenElementsByTagName(e,"Code"); // e.getElementsByTagName("Code");
if ( codeNl.getLength() > 0 )
{
Element codeListElt = (Element) codeNl.item(0);
bcp.initFromXML(codeListElt);
}
//get the meta-inf
Debug.println("[init world] Loading meta-inf...");
NodeList metaInfNodes = e.getElementsByTagName("IdeMetaInf");
if ( metaInfNodes.getLength() == 0 )
System.err.println("LACKING META INF NODE");
//TODO Better error recovery here.
Element metaInfNode = (Element) metaInfNodes.item(0);
if ( metaInfNode != null )
{
NodeList viewNodes = metaInfNode.getElementsByTagName("View");
if ( viewNodes.getLength() > 0 )
{
Element viewNode = (Element) viewNodes.item(0);
try
{
gep.setViewXOffset(Double.parseDouble(viewNode.getAttribute("xoffset")));
gep.setViewYOffset(Double.parseDouble(viewNode.getAttribute("yoffset")));
gep.setViewZoom(Double.parseDouble(viewNode.getAttribute("zoom")));
}
catch ( NumberFormatException nfe )
{
System.out.println("Number format error in meta-inf's view node attributes");
}
}
}
//colors panel
Debug.println("[init world] Loading colours and fonts...");
NodeList visConfNodes = e.getElementsByTagName("VisualConfiguration");
if ( visConfNodes.getLength() > 0 )
{
Element visConfNode = (Element) visConfNodes.item(0);
//Iterator codesIter = Arrays.asList(colorCodes).iterator();
Iterator codesIter = colorsMap.keySet().iterator();
while ( codesIter.hasNext() )
{
String colorCode = (String) codesIter.next();
NodeList interestingElts = visConfNode.getElementsByTagName(colorCode);
if ( interestingElts.getLength() > 0 )
{
Element interestingElt = (Element) interestingElts.item(0);
String colorValue = interestingElt.getAttribute("color");
Color color = ColorUtils.stringToColor(colorValue);
if ( color != null )
{
colorsMap.put(colorCode,color);
JButton b = (JButton) buttonsMap.get(colorCode);
if ( "Background".equals(colorCode) )
{
/*set backgrounds of all buttons (except for "Background" button) to the background colour code*/
for ( int i = 0 ; i < colorCodes.length ; i++ )
{
JButton bToSet = (JButton) buttonsMap.get(colorCodes[i]);
if ( bToSet != b )
{
bToSet.setBackground(color);
}
}
}
else
{
b.setForeground(color);
//b.setVisible(false);
//b.setVisible(true);
//b.repaint();
//this.repaint();
}
}
}
}
this.repaint();
}
NodeList fontNodes = e.getElementsByTagName("Font");
if ( fontNodes.getLength() > 0 )
{
Element fontNode = (Element) fontNodes.item(0);
tfFontName.setText(fontNode.getAttribute("name"));
tfFontFile.setText(fontNode.getAttribute("filename"));
tfFontSize.setText(fontNode.getAttribute("size"));
}
//and now... build everything! yay!
Debug.println("[init world] Fetching entity nodes...");
NodeList roomNodes = e.getElementsByTagName("Room");
NodeList itemNodes = e.getElementsByTagName("Item");
NodeList charNodes = e.getElementsByTagName("Mobile");
NodeList abstractEntityNodes = e.getElementsByTagName("AbstractEntity");
NodeList spellNodes = e.getElementsByTagName("Spell");
//converts names of nodes (and legacy numeric ID's, if present) to nodes
namesToNodes = new HashMap();
nodesToNames = new HashMap();
panelsToNodes = new HashMap();
if ( metaInfNode == null )
{
JOptionPane.showMessageDialog(this,UIMessages.getInstance().getMessage("warning.nometa.text"),UIMessages.getInstance().getMessage("warning.nometa.title"),JOptionPane.WARNING_MESSAGE);
}
//add room nodes
Debug.println("[init world] Processing room nodes...");
for ( int i = 0 ; i < roomNodes.getLength() ; i++ )
{
Element roomNode = (Element) roomNodes.item(i);
/*
String roomName = roomNode.getAttribute("name");
String roomId = roomNode.getAttribute("id");
Point coords = findCoords(metaInfNode,roomName);
int dispSize = findDisplaySize(metaInfNode,roomName);
coords = assignRandomCoordsIfNeeded(coords);
//add the room node
RoomNode rn = new RoomNode(coords.x,coords.y);
gep.addNode(rn);
namesToNodes.put(roomName,rn);
if ( roomId.length() > 0 )
{
namesToNodes.put(roomId,rn);
//idsToNames.put(roomId,roomName);
}
if ( dispSize >= 0 ) rn.setExplicitSize(dispSize);
//rn.getAssociatedPanel().setGraphEditingPanel(gep);
gep.getPropertiesPanel().loadWithoutShowing(rn);
rn.getAssociatedPanel().initFromXML(roomNode); //panel init
*/
addEntityFromXML(roomNode,metaInfNode,namesToNodes);
}
//add char (mob) nodes
Debug.println("[init world] Processing character nodes...");
for ( int i = 0 ; i < charNodes.getLength() ; i++ )
{
Element charNode = (Element) charNodes.item(i);
/*
String charName = charNode.getAttribute("name");
String charId = charNode.getAttribute("id");
Point coords = findCoords(metaInfNode,charName);
int dispSize = findDisplaySize(metaInfNode,charName);
coords = assignRandomCoordsIfNeeded(coords);
//add the mob node
CharacterNode rn = new CharacterNode(coords.x,coords.y);
gep.addNode(rn);
namesToNodes.put(charName,rn);
if ( charId.length() > 0 )
{
namesToNodes.put(charId,rn);
idsToNames.put(charId,charName);
}
if ( dispSize >= 0 ) rn.setExplicitSize(dispSize);
//rn.getAssociatedPanel().setGraphEditingPanel(gep);
gep.getPropertiesPanel().loadWithoutShowing(rn);
rn.getAssociatedPanel().initFromXML(charNode); //panel init
*/
addEntityFromXML(charNode,metaInfNode,namesToNodes);
}
//add item nodes
Debug.println("[init world] Processing item nodes...");
for ( int i = 0 ; i < itemNodes.getLength() ; i++ )
{
Element itemNode = (Element) itemNodes.item(i);
/*
String itemName = itemNode.getAttribute("name");
String itemId = itemNode.getAttribute("id");
Point coords = findCoords(metaInfNode,itemName);
int dispSize = findDisplaySize(metaInfNode,itemName);
coords = assignRandomCoordsIfNeeded(coords);
//add the item node
ItemNode rn = new ItemNode(coords.x,coords.y);
gep.addNode(rn);
namesToNodes.put(itemName,rn);
if ( itemId.length() > 0 )
{
namesToNodes.put(itemId,rn);
idsToNames.put(itemId,itemName);
}
if ( dispSize >= 0 ) rn.setExplicitSize(dispSize);
//rn.getAssociatedPanel().setGraphEditingPanel(gep);
gep.getPropertiesPanel().loadWithoutShowing(rn);
rn.getAssociatedPanel().initFromXML(itemNode); //panel init
*/
addEntityFromXML(itemNode,metaInfNode,namesToNodes);
}
//add abstract entity nodes
Debug.println("[init world] Processing abstract entity nodes...");
for ( int i = 0 ; i < abstractEntityNodes.getLength() ; i++ )
{
Element abstractEntityNode = (Element) abstractEntityNodes.item(i);
/*
String abstractEntityName = abstractEntityNode.getAttribute("name");
String abstractEntityId = abstractEntityNode.getAttribute("id");
Point coords = findCoords(metaInfNode,abstractEntityName);
int dispSize = findDisplaySize(metaInfNode,abstractEntityName);
coords = assignRandomCoordsIfNeeded(coords);
//add the item node
AbstractEntityNode rn = new AbstractEntityNode(coords.x,coords.y);
gep.addNode(rn);
namesToNodes.put(abstractEntityName,rn);
if ( abstractEntityId.length() > 0 )
{
namesToNodes.put(abstractEntityId,rn);
idsToNames.put(abstractEntityId,abstractEntityName);
}
if ( dispSize >= 0 ) rn.setExplicitSize(dispSize);
gep.getPropertiesPanel().loadWithoutShowing(rn);
rn.getAssociatedPanel().initFromXML(abstractEntityNode); //panel init
*/
addEntityFromXML(abstractEntityNode,metaInfNode,namesToNodes);
}
//add spell nodes
Debug.println("[init world] Processing spell nodes...");
for ( int i = 0 ; i < spellNodes.getLength() ; i++ )
{
Element spellNode = (Element) spellNodes.item(i);
/*
String spellName = spellNode.getAttribute("name");
String spellId = spellNode.getAttribute("id");
Point coords = findCoords(metaInfNode,spellName);
int dispSize = findDisplaySize(metaInfNode,spellName);
coords = assignRandomCoordsIfNeeded(coords);
//add the item node
Node rn = new SpellNode(coords.x,coords.y);
gep.addNode(rn);
namesToNodes.put(spellName,rn);
if ( spellId.length() > 0 )
{
namesToNodes.put(spellId,rn);
idsToNames.put(spellId,spellName);
}
if ( dispSize >= 0 ) rn.setExplicitSize(dispSize);
gep.getPropertiesPanel().loadWithoutShowing(rn);
rn.getAssociatedPanel().initFromXML(spellNode); //panel init
*/
addEntityFromXML(spellNode,metaInfNode,namesToNodes);
}
//which chars are players?
Debug.println("[init world] Processing player list...");
NodeList playerListNodes = e.getElementsByTagName("PlayerList");
if ( playerListNodes.getLength() > 0 )
{
Element playerListNode = (Element) playerListNodes.item(0);
NodeList playerNodes = playerListNode.getElementsByTagName("Player");
for ( int i = 0 ; i < playerNodes.getLength() ; i++ )
{
Element playerNode = (Element) playerNodes.item(i);
String playerId = playerNode.getAttribute("id");
Node plNode = (Node) namesToNodes.get(playerId);
CharPanel cp = (CharPanel)plNode.getAssociatedPanel();
cp.setPlayer(true);
}
}
//add path arrows, room inventory arrows, and init panels
Debug.println("[init world] Processing room relationships...");
for ( int i = 0 ; i < roomNodes.getLength() ; i++ )
{
Element roomNode = (Element) roomNodes.item(i);
String roomName = roomNode.getAttribute("name");
Node src = (Node) namesToNodes.get(roomName);
//this map converts destinations to arrows in the context of this source node
//so that custom relationships can be added to the same arrow where structural
//relationships have been initted, if it exists
Map destNodeToArrow = new HashMap();
//structural room->room (path) relationships
NodeList pathNodes = roomNode.getElementsByTagName("Path");
for ( int j = 0 ; j < pathNodes.getLength() ; j++ )
{
Element pathNode = (Element) pathNodes.item(j);
String pathDest = pathNode.getAttribute("destination");
Node dst = (Node) namesToNodes.get(pathDest);
Arrow pathArrow = new StructuralArrow();
destNodeToArrow.put(dst,pathArrow);
pathArrow.setSource(src);
pathArrow.setDestination(dst);
src.addArrow(pathArrow);
gep.getPropertiesPanel().loadWithoutShowing(pathArrow);
//pathArrow.getAssociatedPanel().setGraphEditingPanel(gep);
//door
NodeList doorNodes = pathNode.getElementsByTagName("AssociatedItem");
if ( doorNodes.getLength() > 0 )
{
Element doorNode = (Element) doorNodes.item(0);
String doorId = doorNode.getAttribute("id");
ItemNode doorGraphNode = (ItemNode) namesToNodes.get(doorId);
((PathPanel)pathArrow.getAssociatedPanel()).setDoor(doorGraphNode);
}
pathArrow.getAssociatedPanel().initFromXML(pathNode); //panel init
}
//structural room->item (inventory) relationships
NodeList inventoryNodes = DOMUtils.getDirectChildrenElementsByTagName(roomNode,"Inventory");
Element inventoryNode = (Element) inventoryNodes.item(0);
if ( inventoryNode != null )
{
NodeList itemRefNodes = inventoryNode.getElementsByTagName("ItemRef");
for ( int j = 0 ; j < itemRefNodes.getLength() ; j++ )
{
Element itemRefNode = (Element) itemRefNodes.item(j);
String dest = itemRefNode.getAttribute("id");
Node dst = (Node) namesToNodes.get(dest);
if ( dst == null )
{
System.out.println("Warning: null destination node.");
System.out.println(itemRefNode);
System.out.println(itemRefNode.getAttribute("id"));
}
Arrow arrow = new StructuralArrow();
destNodeToArrow.put(dst,arrow);
arrow.setSource(src);
arrow.setDestination(dst);
src.addArrow(arrow);
//arrow.getAssociatedPanel().setGraphEditingPanel(gep);
gep.getPropertiesPanel().loadWithoutShowing(arrow);
arrow.getAssociatedPanel().initFromXML(itemRefNode); //panel init
}
}
//structural room->mob (mobile list) relationships
NodeList moblistNodes = roomNode.getElementsByTagName("MobileList");
if ( moblistNodes != null )
{
Element moblistNode = (Element) moblistNodes.item(0);
if ( moblistNode != null )
{
NodeList mobRefNodes = moblistNode.getElementsByTagName("MobRef");
for ( int j = 0 ; j < mobRefNodes.getLength() ; j++ )
{
Element mobRefNode = (Element) mobRefNodes.item(j);
String dest = mobRefNode.getAttribute("id");
Node dst = (Node) namesToNodes.get(dest);
if ( dst == null )
{
System.out.println("Warning: null destination node.");
System.out.println(mobRefNode);
System.out.println(mobRefNode.getAttribute("id"));
}
Arrow arrow = new StructuralArrow();
destNodeToArrow.put(dst,arrow);
arrow.setSource(src);
arrow.setDestination(dst);
src.addArrow(arrow);
//arrow.getAssociatedPanel().setGraphEditingPanel(gep);
gep.getPropertiesPanel().loadWithoutShowing(arrow);
arrow.getAssociatedPanel().initFromXML(mobRefNode); //panel init
}
}
}
//non-structural (custom) relationships
initCustomRelationshipsFromXML ( roomNode , namesToNodes , destNodeToArrow );
}
//add char arrows, init panels
Debug.println("[init world] Processing character relationships...");
for ( int i = 0 ; i < charNodes.getLength() ; i++ )
{
Element charNode = (Element) charNodes.item(i);
String charName = charNode.getAttribute("name");
Node src = (Node) namesToNodes.get(charName);
Map destNodeToArrow = new HashMap();
NodeList inventoryNodes =
DOMUtils.getDirectChildrenElementsByTagName(charNode,"Inventory");
if ( inventoryNodes.getLength() > 0 )
{
Element inventoryNode = (Element) inventoryNodes.item(0);
initEntityToItemRelationships ( namesToNodes , src , inventoryNode , destNodeToArrow , UIMessages.getInstance().getMessage("structural.char.item.carry") );
}
NodeList partsNodes =
DOMUtils.getDirectChildrenElementsByTagName(charNode,"Parts");
if ( partsNodes.getLength() > 0 )
{
Element partsNode = (Element) partsNodes.item(0);
NodeList partsInventoryNodes =
DOMUtils.getDirectChildrenElementsByTagName(partsNode,"Inventory");
if ( partsInventoryNodes.getLength() > 0 )
{
Element partsInventoryNode = (Element) partsInventoryNodes.item(0);
initEntityToItemRelationships ( namesToNodes , src , partsInventoryNode , destNodeToArrow , UIMessages.getInstance().getMessage("structural.char.item.haspart") );
}
}
/*
Element inventoryNode = (Element) inventoryNodes.item(0);
NodeList itemRefNodes = inventoryNode.getElementsByTagName("ItemRef");
for ( int j = 0 ; j < itemRefNodes.getLength() ; j++ )
{
Element itemRefNode = (Element) itemRefNodes.item(j);
String dest = itemRefNode.getAttribute("id");
Node dst = (Node) namesToNodes.get(dest);
Arrow arrow = new StructuralArrow();
arrow.setSource(src);
arrow.setDestination(dst);
src.addArrow(arrow);
//arrow.getAssociatedPanel().setGraphEditingPanel(gep);
gep.getPropertiesPanel().loadWithoutShowing(arrow);
arrow.getAssociatedPanel().initFromXML(itemRefNode); //panel init
}
*/
//structural char->spell (spell list) relationships
NodeList spellListNodes = charNode.getElementsByTagName("SpellList");
if ( spellListNodes != null )
{
Element spellListNode = (Element) spellListNodes.item(0);
if ( spellListNode != null )
{
NodeList spellRefNodes = spellListNode.getElementsByTagName("SpellRef");
for ( int j = 0 ; j < spellRefNodes.getLength() ; j++ )
{
Element spellRefNode = (Element) spellRefNodes.item(j);
String dest = spellRefNode.getAttribute("id");
Node dst = (Node) namesToNodes.get(dest);
if ( dst == null )
{
System.out.println("Warning: null destination node.");
System.out.println(spellRefNode);
System.out.println(spellRefNode.getAttribute("id"));
}
Arrow arrow = new StructuralArrow();
destNodeToArrow.put(dst,arrow);
arrow.setSource(src);
arrow.setDestination(dst);
src.addArrow(arrow);
//arrow.getAssociatedPanel().setGraphEditingPanel(gep);
gep.getPropertiesPanel().loadWithoutShowing(arrow);
arrow.getAssociatedPanel().initFromXML(spellRefNode); //panel init
}
}
}
//non-structural (custom) relationships - TODO <- but need to propagate destNodeToArrow across methods
initCustomRelationshipsFromXML ( charNode , namesToNodes , destNodeToArrow );
}
//add item arrows, init panels
Debug.println("[init world] Processing item relationships...");
for ( int i = 0 ; i < itemNodes.getLength() ; i++ )
{
Element itemNode = (Element) itemNodes.item(i);
String itemName = itemNode.getAttribute("name");
Node src = (Node) namesToNodes.get(itemName);
Map destNodeToArrow = new HashMap();
NodeList inventoryNodes =
DOMUtils.getDirectChildrenElementsByTagName(itemNode,"Inventory");
if ( inventoryNodes.getLength() > 0 )
{
Element inventoryNode = (Element) inventoryNodes.item(0);
initEntityToItemRelationships ( namesToNodes , src , inventoryNode , destNodeToArrow , UIMessages.getInstance().getMessage("structural.item.item.contain") );
/*
NodeList itemRefNodes = inventoryNode.getElementsByTagName("ItemRef");
Node src = (Node) namesToNodes.get(itemName);
for ( int j = 0 ; j < itemRefNodes.getLength() ; j++ )
{
Element itemRefNode = (Element) itemRefNodes.item(j);
String dest = itemRefNode.getAttribute("id");
Node dst = (Node) namesToNodes.get(dest);
Arrow arrow = new StructuralArrow();
arrow.setSource(src);
arrow.setDestination(dst);
src.addArrow(arrow);
//arrow.getAssociatedPanel().setGraphEditingPanel(gep);
gep.getPropertiesPanel().loadWithoutShowing(arrow);
GraphElementPanel arrowPanel = arrow.getAssociatedPanel();
if ( arrowPanel instanceof ItemHasItemPanel )
{
((ItemHasItemPanel)arrowPanel).setRelationshipType(Messages.getInstance().getMessage("structural.item.item.contain"));
}
arrow.getAssociatedPanel().initFromXML(itemRefNode); //panel init
}
*/
}
NodeList partsNodes =
DOMUtils.getDirectChildrenElementsByTagName(itemNode,"Parts");
if ( partsNodes.getLength() > 0 )
{
Element partsNode = (Element) partsNodes.item(0);
NodeList partsInventoryNodes =
DOMUtils.getDirectChildrenElementsByTagName(partsNode,"Inventory");
if ( partsInventoryNodes.getLength() > 0 )
{
Element partsInventoryNode = (Element) partsInventoryNodes.item(0);
initEntityToItemRelationships ( namesToNodes , src , partsInventoryNode , destNodeToArrow , UIMessages.getInstance().getMessage("structural.item.item.haspart") );
}
}
NodeList keysNodes =
DOMUtils.getDirectChildrenElementsByTagName(itemNode,"KeyList");
if ( keysNodes.getLength() > 0 )
{
Element keysNode = (Element) keysNodes.item(0);
NodeList keysInventoryNodes =
DOMUtils.getDirectChildrenElementsByTagName(keysNode,"Inventory");
if ( keysInventoryNodes.getLength() > 0 )
{
Element keysInventoryNode = (Element) keysInventoryNodes.item(0);
initEntityToItemRelationships ( namesToNodes , src , keysInventoryNode , destNodeToArrow , UIMessages.getInstance().getMessage("structural.item.item.haskey") );
}
}
initCustomRelationshipsFromXML ( itemNode , namesToNodes , destNodeToArrow );
}
//add spell arrows, init panels
Debug.println("[init world] Processing spell relationships...");
for ( int i = 0 ; i < spellNodes.getLength() ; i++ )
{
Element spellNode = (Element) spellNodes.item(i);
String spellName = spellNode.getAttribute("name");
Node src = (Node) namesToNodes.get(spellName);
Map destNodeToArrow = new HashMap();
NodeList effectListNodes =
DOMUtils.getDirectChildrenElementsByTagName(spellNode,"EffectList");
if ( effectListNodes != null && effectListNodes.getLength() > 0 )
{
Element effectListNode = (Element) effectListNodes.item(0);
if ( effectListNode != null )
{
NodeList effectRefNodes = effectListNode.getElementsByTagName("EffectRef");
for ( int j = 0 ; j < effectRefNodes.getLength() ; j++ )
{
Element effectRefNode = (Element) effectRefNodes.item(j);
String dest = effectRefNode.getAttribute("id");
Node dst = (Node) namesToNodes.get(dest);
if ( dst == null )
{
System.out.println("Warning: null destination node.");
System.out.println(effectRefNode);
System.out.println(effectRefNode.getAttribute("id"));
}
Arrow arrow = new StructuralArrow();
destNodeToArrow.put(dst,arrow);
arrow.setSource(src);
arrow.setDestination(dst);
src.addArrow(arrow);
//arrow.getAssociatedPanel().setGraphEditingPanel(gep);
gep.getPropertiesPanel().loadWithoutShowing(arrow);
arrow.getAssociatedPanel().initFromXML(effectRefNode); //panel init
}
}
}
initCustomRelationshipsFromXML ( spellNode , namesToNodes , destNodeToArrow );
}
//add abstract entity arrows, init panels
Debug.println("[init world] Processing abstract entity relationships...");
for ( int i = 0 ; i < abstractEntityNodes.getLength() ; i++ )
{
Element abstractEntityNode = (Element) abstractEntityNodes.item(i);
String abstractEntityName = abstractEntityNode.getAttribute("name");
Node src = (Node) namesToNodes.get(abstractEntityName);
Map destNodeToArrow = new HashMap();
//non-structural (custom) relationships
initCustomRelationshipsFromXML ( abstractEntityNode , namesToNodes , destNodeToArrow );
}
Debug.println("[init world] All done.");
//show the world node.
gep.getPropertiesPanel().show(gep.getWorldNode());
//if ( metaInfNode == null ) //rearrange nodes a bit
// new GraphArranger().arrange(gep, 250);
}
public void initEntityToItemRelationships ( Map namesToNodes , Node src , Element inventoryNode , Map destNodeToArrow , String relationshipType )
{
NodeList itemRefNodes = inventoryNode.getElementsByTagName("ItemRef");
for ( int j = 0 ; j < itemRefNodes.getLength() ; j++ )
{
Element itemRefNode = (Element) itemRefNodes.item(j);
String dest = itemRefNode.getAttribute("id");
Node dst = (Node) namesToNodes.get(dest);
if ( dst == null )
{
System.out.println("Warning: null destination node.");
System.out.println(itemRefNode);
System.out.println(itemRefNode.getAttribute("id"));
//maybe insert continue here so as to not casck in these cases, but just output the error and don't load the relationship
continue;
}
Arrow arrow = new StructuralArrow();
destNodeToArrow.put(dst,arrow);
arrow.setSource(src);
arrow.setDestination(dst);
src.addArrow(arrow);
gep.getPropertiesPanel().loadWithoutShowing(arrow);
GraphElementPanel arrowPanel = arrow.getAssociatedPanel();
if ( arrowPanel instanceof ItemHasItemPanel )
{
((ItemHasItemPanel)arrowPanel).setRelationshipType(relationshipType);
}
if ( arrowPanel instanceof CharHasItemPanel )
{
((CharHasItemPanel)arrowPanel).setRelationshipType(relationshipType);
}
arrow.getAssociatedPanel().initFromXML(itemRefNode); //panel init
}
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
}
public String getBSHCode()
{
if ( bcp == null ) forceRealInitFromXml(true); //code panel not yet initted.
return bcp.getCode();
}
}