/*
* (c) 2005-2009 Carlos Gómez, todos los derechos reservados / all rights reserved.
* Licencia en license/bsd.txt / License in license/bsd.txt
*
* Created at regulus on 19-jul-2005 19:31:22
* as file GraphEditingPanel.java on package org.f2o.absurdum.puck.gui.graph
*/
package org.f2o.absurdum.puck.gui.graph;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.JComboBox;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JSeparator;
import javax.swing.MutableComboBoxModel;
import javax.swing.event.ListDataListener;
import javax.xml.parsers.DocumentBuilderFactory;
import org.f2o.absurdum.puck.gui.AddNodeTool;
import org.f2o.absurdum.puck.gui.CopyNodeAction;
import org.f2o.absurdum.puck.gui.CutNodeAction;
import org.f2o.absurdum.puck.gui.DefaultMouseMotionListener;
import org.f2o.absurdum.puck.gui.DeleteArrowAction;
import org.f2o.absurdum.puck.gui.DeleteNodeAction;
import org.f2o.absurdum.puck.gui.PasteNodeAction;
import org.f2o.absurdum.puck.gui.PropertiesPanel;
import org.f2o.absurdum.puck.gui.PuckFrame;
import org.f2o.absurdum.puck.gui.TranslateTool;
import org.f2o.absurdum.puck.gui.config.PuckConfiguration;
import org.f2o.absurdum.puck.gui.panels.EntityPanel;
import org.f2o.absurdum.puck.gui.panels.RoomPanel;
import org.f2o.absurdum.puck.gui.panels.WorldPanel;
import org.f2o.absurdum.puck.i18n.UIMessages;
import org.f2o.absurdum.puck.util.ColorUtils;
import org.w3c.dom.Document;
//class
/**
* @author carlos
*
* Created at regulus, 19-jul-2005 19:31:22
*/
public class GraphEditingPanel extends JPanel implements MouseListener, MouseMotionListener, MouseWheelListener, KeyListener
{
private MouseListener toolListener = null;
private MouseMotionListener toolMotionListener = null;
private Vector nodes = new Vector(); //of Node
private Node specialNode;
private Arrow specialArrow;
private PropertiesPanel propP;
private boolean enableGrid = true;
private boolean snapToGrid = true;
private WorldNode worldN = new WorldNode(new WorldPanel(this));
/**Experimental**/
/**For Combo Boxes**/
private Vector roomNodes = new Vector();
private Vector itemNodes = new Vector();
private Vector charNodes = new Vector();
private Map nodeListsByClass = new HashMap(); //of Vectors (with room nodes, item nodes, etc.)
private Map nodeListsByClassN = new HashMap(); //of Vectors (with room nodes, item nodes, etc.) including null
/**
* Obtains the color setting with the given name.
* @param name
* @return
*/
public Color getColorSetting ( String name )
{
return GraphColorSettings.getInstance().getColorSetting(name);
}
/**
* Sets the given color setting. Also sets it in the configuration file.
* @param name
* @param color
*/
public void setColorSetting ( String name , Color color )
{
GraphColorSettings.getInstance().setColorSetting(name,color);
if ( name.equals("background") ) //this has to be applied immediately, others are applied on repainting
setBackground(color);
//repaint(); //done by callers
}
public boolean isSnapToGridEnabled()
{
return snapToGrid;
}
public boolean isGridEnabled()
{
return enableGrid;
}
public void setSnapToGrid ( boolean value )
{
this.snapToGrid = value;
}
public void setGrid ( boolean value )
{
this.enableGrid = value;
}
public void clear()
{
nodes = new Vector();
specialNode = null;
specialArrow = null;
worldN = new WorldNode(new WorldPanel(this));
roomNodes = new Vector();
itemNodes = new Vector();
charNodes = new Vector();
resetNodeLists();
/*
roomNodes.add(Messages.getInstance().getMessage("none"));
itemNodes.add(Messages.getInstance().getMessage("none"));
charNodes.add(Messages.getInstance().getMessage("none"));
*/
}
public void resetNodeLists()
{
//lists including null
nodeListsByClassN = new HashMap();
Vector roomVecN = new Vector();
roomVecN.add(UIMessages.getInstance().getMessage("none"));
nodeListsByClassN.put(RoomNode.class,roomVecN);
Vector itemVecN = new Vector();
itemVecN.add(UIMessages.getInstance().getMessage("none"));
nodeListsByClassN.put(ItemNode.class,itemVecN);
Vector charVecN = new Vector();
charVecN.add(UIMessages.getInstance().getMessage("none"));
nodeListsByClassN.put(CharacterNode.class,charVecN);
Vector spellVecN = new Vector();
spellVecN.add(UIMessages.getInstance().getMessage("none"));
nodeListsByClassN.put(SpellNode.class,spellVecN);
Vector abstractVecN = new Vector();
abstractVecN.add(UIMessages.getInstance().getMessage("none"));
nodeListsByClassN.put(AbstractEntityNode.class,abstractVecN);
//lists not including null
nodeListsByClass = new HashMap();
Vector roomVec = new Vector();
nodeListsByClass.put(RoomNode.class,roomVec);
Vector itemVec = new Vector();
nodeListsByClass.put(ItemNode.class,itemVec);
Vector charVec = new Vector();
nodeListsByClass.put(CharacterNode.class,charVec);
Vector spellVec = new Vector();
nodeListsByClass.put(SpellNode.class,spellVec);
Vector abstractVec = new Vector();
nodeListsByClass.put(AbstractEntityNode.class,abstractVec);
}
public Vector getNodes()
{
return nodes;
}
public Vector getNodes ( Class cl , boolean includeNull )
{
if ( includeNull )
return (Vector) nodeListsByClassN.get(cl);
else
return (Vector) nodeListsByClass.get(cl);
}
public Vector getRoomNodes(boolean includeNull)
{
return getNodes(RoomNode.class,includeNull);
//return (Vector) nodeListsByClass.get(RoomNode.class);
}
public Vector getItemNodes(boolean includeNull)
{
return getNodes(ItemNode.class,includeNull);
//return (Vector) nodeListsByClass.get(ItemNode.class);
}
public Vector getCharNodes(boolean includeNull)
{
return getNodes(CharacterNode.class,includeNull);
//return (Vector) nodeListsByClass.get(CharacterNode.class);
}
public WorldNode getWorldNode()
{
return worldN;
}
public void setWorldNode(WorldNode wn)
{
worldN = wn;
}
/**The following method is totally experimental**/
//unused as of 2009-04-11
public JComboBox buildRoomNamesBox()
{
MutableComboBoxModel mcbm = new MutableComboBoxModel()
{
Object sel;
public void removeElementAt(int arg0) {
}
public void addElement(Object arg0) {
}
public void removeElement(Object arg0) {
}
public void insertElementAt(Object arg0, int arg1) {
}
public Object getSelectedItem() {
return sel;
}
public void setSelectedItem(Object arg0) {
sel = arg0;
}
public int getSize() {
return getRoomNames().size();
}
public Object getElementAt(int arg0) {
return getRoomNames().get(arg0);
}
public void addListDataListener(ListDataListener arg0) {
// TODO Hmm.
}
public void removeListDataListener(ListDataListener arg0) {
// TODO Auto-generated method stub
}
};
return new JComboBox ( mcbm );
}
public PropertiesPanel getPropertiesPanel()
{
return propP;
}
public List getRoomNames()
{
ArrayList names = new ArrayList();
for ( int i = 0 ; i < nodes.size() ; i++ )
{
Node n = (Node) nodes.get(i);
if ( n instanceof RoomNode )
{
RoomNode rn = (RoomNode) n;
names.add ( rn.getName() );
}
}
return names;
}
public void setSpecialNode ( Node n )
{
if ( specialNode != null ) specialNode.setHighlighted(false);
specialNode = n;
if ( n != null ) n.setHighlighted(true);
}
public Node getSpecialNode ()
{
return specialNode;
}
public void setSpecialArrow ( Arrow a )
{
if ( specialArrow != null ) specialArrow.setHighlighted(false);
specialArrow = a;
if ( a != null ) a.setHighlighted(true);
}
public Arrow getSpecialArrow ()
{
return specialArrow;
}
public void addNode ( Node n )
{
nodes.add(n);
Vector nodeVector = (Vector) nodeListsByClass.get(n.getClass());
Vector nodeVectorN = (Vector) nodeListsByClassN.get(n.getClass());
if ( nodeVector == null )
{
nodeVector = new Vector();
nodeVector.add( UIMessages.getInstance().getMessage("none") );
nodeListsByClass.put(n.getClass(),nodeVector);
}
nodeVector.add(n);
if ( nodeVectorN == null )
{
nodeVectorN = new Vector();
nodeVectorN.add( UIMessages.getInstance().getMessage("none") );
nodeListsByClassN.put(n.getClass(),nodeVectorN);
}
nodeVectorN.add(n);
/*
if ( n instanceof RoomNode )
roomNodes.add(n);
if ( n instanceof ItemNode )
itemNodes.add(n);
if ( n instanceof CharacterNode )
charNodes.add(n);
*/
WorldPanel wp = (WorldPanel) this.getWorldNode().getAssociatedPanel();
wp.updateMaps(n);
}
public void removeNode ( Node n )
{
nodes.remove(n);
Vector nodeVector = (Vector) nodeListsByClass.get(n.getClass());
if ( nodeVector != null )
{
nodeVector.remove(n);
}
Vector nodeVectorN = (Vector) nodeListsByClassN.get(n.getClass());
if ( nodeVectorN != null )
{
nodeVectorN.remove(n);
}
WorldPanel wp = (WorldPanel) this.getWorldNode().getAssociatedPanel();
wp.removeFromMaps(n);
}
public void totallyRemoveNode ( Node n )
{
nodes.remove(n);
Vector nodeVector = (Vector) nodeListsByClass.get(n.getClass());
if ( nodeVector != null )
{
nodeVector.remove(n);
}
Vector nodeVectorN = (Vector) nodeListsByClassN.get(n.getClass());
if ( nodeVectorN != null )
{
nodeVectorN.remove(n);
}
//remove arrows pointing to this node
for ( int i = 0 ; i < nodes.size() ; i++ )
{
Node no = (Node) nodes.get(i);
List arrows = no.getArrows();
for ( int j = 0 ; j < arrows.size() ; j++ )
{
Arrow a = (Arrow) arrows.get(j);
if ( a.getDestination() == n )
no.removeArrow(a);
}
}
WorldPanel wp = (WorldPanel) this.getWorldNode().getAssociatedPanel();
wp.removeFromMaps(n);
}
private Image buffer;
public double mapToPanelX ( double xcoord )
{
return (xcoord-viewXOffset)*viewZoom;
}
public double mapToPanelY ( double ycoord )
{
return (ycoord-viewYOffset)*viewZoom;
}
public int mapToPanelX ( int xcoord )
{
return (int) ((xcoord-viewXOffset)*viewZoom);
}
public int mapToPanelY ( int ycoord )
{
return (int)((ycoord-viewYOffset)*viewZoom);
}
public double panelToMapX ( double xcoord )
{
return viewXOffset + xcoord/viewZoom;
}
public double panelToMapY ( double ycoord )
{
return viewYOffset + ycoord/viewZoom;
}
public int panelToMapX ( int xcoord )
{
return (int) ( viewXOffset + xcoord/viewZoom );
}
public int panelToMapY ( int ycoord )
{
return (int) ( viewYOffset + ycoord/viewZoom );
}
private double viewZoom=2.0;
private double viewXOffset=0;
private double viewYOffset=0;
private int bufferW = 5000;
private int bufferH = 5000;
/*
System.out.println("*"+panelToMapX(arg0.getX()));
System.out.println("#"+getWidth());
System.out.println(viewXOffset+","+viewYOffset);
viewXOffset = -this.getWidth()/2/viewZoom + panelToMapX(arg0.getX());
viewYOffset = -this.getHeight()/2/viewZoom + panelToMapY(arg0.getY());
if ( viewXOffset < 0 ) viewXOffset = 0;
if ( viewYOffset < 0 ) viewYOffset = 0;
System.out.println("*"+panelToMapX(arg0.getX()));
System.out.println(viewXOffset+","+viewYOffset);
repaint();
*/
//public void centerOn ( int map)
public void multiplyZoom ( double factor )
{
double oldZoom = viewZoom;
viewZoom*=factor;
{
viewXOffset = viewXOffset + ((1.0/2.0)*this.getWidth()-(1.0/(2.0*factor))*this.getWidth())/oldZoom;
viewYOffset = viewYOffset + ((1.0/2.0)*this.getWidth()-(1.0/(2.0*factor))*this.getWidth())/oldZoom;
}
}
public void paintComponent ( Graphics g )
{
super.paintComponent(g);
((Graphics2D)g).setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
if ( buffer == null || buffer.getWidth(this) != this.getWidth() || buffer.getHeight(this) != this.getHeight() )
buffer = this.createImage ( this.getWidth() , this.getHeight() );
Graphics g2 = buffer.getGraphics();
doPaintComponentInBuffer ( g2 );
g.drawImage(buffer,0,0,Color.RED,this);
}
public void paintComponentOld ( Graphics g )
{
super.paintComponent(g);
//Si el buffer no est� correctamente inicializado, lo (re)creamos
if ( buffer == null ||
buffer.getWidth(this) != bufferW ||
buffer.getHeight(this) != bufferH )
buffer = this.createImage ( bufferW , bufferH );
Graphics g2 = buffer.getGraphics();
doPaintComponent ( g2 );
g.drawImage(buffer,0,0,this.size().width,this.size().height,(int)viewXOffset,(int)viewYOffset,(int)viewXOffset+(int)(this.size().width/viewZoom),(int)viewYOffset+(int)(this.size().height/viewZoom),Color.BLACK,this);
}
public void doPaintComponentInBuffer ( Graphics g )
{
super.paintComponent(g);
//paint grid
if ( enableGrid )
{
paintGrid( g );
}
//paint nodes and arrows
for ( int i = 0 ; i < nodes.size() ; i++ )
{
Node n = (Node) nodes.get(i);
n.paintToView(g,viewZoom,(int)viewXOffset,(int)viewYOffset);
if ( n.isHighlighted() && !n.isSelected() ) drawNodeHighlight(g,n,new Color(0.8F,0.8F,0.0F,0.2F));
if ( n.isSelected() ) drawNodeHighlight(g,n,new Color(1.0F,0.6F,0.0F,0.3F));
List arrows = n.getArrows();
for ( int j = 0 ; j < arrows.size() ; j++ )
{
Arrow a = (Arrow) arrows.get(j);
a.paintToView(g,viewZoom,(int)viewXOffset,(int)viewYOffset);
if ( a.isHighlighted() && !a.isSelected() ) drawArrowHighlight(g,a,new Color(0.8F,0.8F,0.0F,0.2F));
if ( a.isSelected() ) drawArrowHighlight(g,a,new Color(1.0F,0.6F,0.0F,0.3F));
}
}
//paint special node
if ( specialNode != null )
{
specialNode.paintToView(g,viewZoom,(int)viewXOffset,(int)viewYOffset);
if ( !(specialNode instanceof InvisibleNode) )
{
if ( specialNode.isHighlighted() && !specialNode.isSelected() ) drawNodeHighlight(g,specialNode,new Color(0.8F,0.8F,0.0F,0.2F));
if ( specialNode.isSelected() ) drawNodeHighlight(g,specialNode,new Color(1.0F,0.6F,0.0F,0.3F));
}
List arrows = specialNode.getArrows();
for ( int j = 0 ; j < arrows.size() ; j++ )
{
Arrow a = (Arrow) arrows.get(j);
a.paintToView(g,viewZoom,(int)viewXOffset,(int)viewYOffset);
if ( a.isHighlighted() && !a.isSelected() ) drawArrowHighlight(g,a,new Color(0.8F,0.8F,0.0F,0.2F));
if ( a.isSelected() ) drawArrowHighlight(g,a,new Color(1.0F,0.6F,0.0F,0.3F));
}
}
//paint special arrow
if ( specialArrow != null )
{
specialArrow.paintToView(g,viewZoom,(int)viewXOffset,(int)viewYOffset);
if ( specialArrow.isHighlighted() && !specialArrow.isSelected() ) drawArrowHighlight(g,specialArrow,new Color(0.8F,0.8F,0.0F,0.2F));
if ( specialArrow.isSelected() ) drawArrowHighlight(g,specialArrow,new Color(1.0F,0.6F,0.0F,0.3F));
}
}
private void drawNodeHighlight ( Graphics g , Node theNode , Color color )
{
int viewXCoord = (int)(( (int) theNode.getBounds().getX() - viewXOffset ) * viewZoom);
int viewYCoord = (int)(( (int) theNode.getBounds().getY() - viewYOffset ) * viewZoom);
int viewHeight = (int)(( (int) theNode.getBounds().getHeight() ) * viewZoom);
int viewWidth = (int)(( (int) theNode.getBounds().getWidth() ) * viewZoom);
Color old = g.getColor();
g.setColor(color);
g.fillOval(viewXCoord-20,viewYCoord-20,(int)(viewHeight+40),(int)(viewWidth+40));
g.setColor(old);
}
private void drawArrowHighlight ( Graphics g , Arrow theArrow , Color color )
{
int [] coords = theArrow.getPaintingCoords();
//transform coords
//source x,y
coords[0] = (int)(( (int) coords[0] - viewXOffset ) * viewZoom);
coords[1] = (int)(( (int) coords[1] - viewYOffset ) * viewZoom);
//destination x,y
coords[2] = (int)(( (int) coords[2] - viewXOffset ) * viewZoom);
coords[3] = (int)(( (int) coords[3] - viewYOffset ) * viewZoom);
Graphics2D g2d = (Graphics2D)g;
Stroke oldStroke = g2d.getStroke();
Color oldColor = g2d.getColor();
g2d.setStroke(new BasicStroke(15.0F));
g2d.setColor(color);
g2d.drawLine(coords[0],coords[1],coords[2],coords[3]);
g2d.setStroke(oldStroke);
g2d.setColor(oldColor);
}
public void paintGrid( Graphics g )
{
//draw vertical lines
int leftMapX = this.panelToMapX(0);
int leftMapXRounded = (leftMapX/20)*20;
boolean finished = false;
int currentX = leftMapXRounded;
while ( !finished )
{
Color prevColor = g.getColor();
//g.setColor(new Color((float)0.95,(float)0.95,(float)0.95));
g.setColor(getColorSetting("grid"));
//g.setColor(Color.LIGHT_GRAY);
g.drawLine(mapToPanelX(currentX),0,mapToPanelX(currentX),this.getHeight());
g.setColor(prevColor);
if ( mapToPanelX(currentX) > this.getWidth() )
finished = true;
currentX += 20;
}
//draw horizontal lines
int leftMapY = this.panelToMapY(0);
int leftMapYRounded = (leftMapY/20)*20;
finished = false;
int currentY = leftMapYRounded;
while ( !finished )
{
Color prevColor = g.getColor();
//g.setColor(Color.LIGHT_GRAY);
g.setColor(getColorSetting("grid"));
g.drawLine(0,mapToPanelY(currentY),this.getWidth(),mapToPanelY(currentY));
g.setColor(prevColor);
if ( mapToPanelY(currentY) > this.getHeight() )
finished = true;
currentY += 20;
}
}
public void doPaintComponent ( Graphics g )
{
super.paintComponent(g);
for ( int i = 0 ; i < nodes.size() ; i++ )
{
Node n = (Node) nodes.get(i);
n.paint(g);
List arrows = n.getArrows();
for ( int j = 0 ; j < arrows.size() ; j++ )
{
Arrow a = (Arrow) arrows.get(j);
a.paint(g);
}
}
if ( specialNode != null )
{
specialNode.paint(g);
List arrows = specialNode.getArrows();
for ( int j = 0 ; j < arrows.size() ; j++ )
{
Arrow a = (Arrow) arrows.get(j);
a.paint(g);
}
}
if ( specialArrow != null )
{
specialArrow.paint(g);
}
}
public Node nodeAt ( int x , int y )
{
for ( int i = 0 ; i < nodes.size() ; i++ )
{
Node n = (Node) nodes.get(i);
Rectangle r = n.getBounds();
if ( r.contains(x,y) )
return n;
}
return null;
}
private double ARROWAT_TOLERANCE = 5;
public Arrow arrowAt ( int x , int y )
{
Arrow best = null;
double bestDist = 999.99;
for ( int i = 0 ; i < nodes.size() ; i++ )
{
List arrows = ((Node)nodes.get(i)).getArrows();
for ( int j = 0 ; j < arrows.size() ; j++ )
{
Arrow a = (Arrow) arrows.get(j);
int[] coords = a.getPaintingCoords();
Line2D l = new Line2D.Float((float)coords[0],(float)coords[1],(float)coords[2],(float)coords[3]);
double dist = l.ptLineDist((double)x,(double)y);
if ( dist < ARROWAT_TOLERANCE && dist < bestDist
&& x <= Math.max((float)coords[0],(float)coords[2])+ARROWAT_TOLERANCE
&& x >= Math.min((float)coords[0],(float)coords[2])-ARROWAT_TOLERANCE
&& y <= Math.max((float)coords[1],(float)coords[3])+ARROWAT_TOLERANCE
&& y >= Math.min((float)coords[1],(float)coords[3])-ARROWAT_TOLERANCE
)
{
best = a;
bestDist = dist;
}
}
}
return best;
}
private Node selectedNode = null;
private Arrow selectedArrow = null;
public Node getSelectedNode()
{
return selectedNode;
}
public void resetSelections()
{
if ( selectedNode != null ) selectedNode.setSelected(false);
if ( selectedArrow != null ) selectedArrow.setSelected(false);
selectedNode = null;
selectedArrow = null;
}
public void selectNode ( Node n )
{
selectedNode = n;
n.setSelected(true);
requestFocus();
}
public void selectArrow ( Arrow a )
{
selectedArrow = a;
a.setSelected(true);
requestFocus();
}
public void focusOnNode ( Node n , boolean showPropertiesPanel )
{
resetSelections();
selectNode(n);
if ( showPropertiesPanel )
getPropertiesPanel().show(n);
centerViewOn(n);
repaint();
}
public void mouseClicked(MouseEvent arg0)
{
if ( toolListener != null )
toolListener.mouseClicked(arg0);
else
{
Node n = nodeAt(panelToMapX(arg0.getX()),panelToMapY(arg0.getY()));
if ( n != null )
{
propP.show(n);
resetSelections();
selectNode(n);
showNodeMenuIfApplicable(arg0,n);
}
else
{
Arrow a = arrowAt(panelToMapX(arg0.getX()),panelToMapY(arg0.getY()));
if ( a != null )
{
propP.show(a);
resetSelections();
selectArrow(a);
showArrowMenuIfApplicable(arg0,a);
}
else
{
resetSelections();
propP.show(worldN);
showEmptySpaceMenuIfApplicable(arg0);
}
}
}
repaint();
/*
else
{
if ( specialNode == null )
{
Node n = nodeAt(arg0.getX(),arg0.getY());
if ( n != null )
{
removeNode(n);
setSpecialNode(n);
}
}
else
{
System.out.println("Dropped: " +specialNode + specialNode.getBounds());
specialNode.setLocation(arg0.getX(),arg0.getY());
addNode(specialNode);
setSpecialNode(null);
repaint();
}
}
*/
}
public void mouseEntered(MouseEvent arg0)
{
if ( toolListener != null )
toolListener.mouseEntered(arg0);
else
setBorder(BorderFactory.createLineBorder(Color.red));
}
public void mouseExited(MouseEvent arg0)
{
if ( toolListener != null )
toolListener.mouseExited(arg0);
else
setBorder(null);
}
double lastPressX = 0.0;
double lastPressY = 0.0;
public void showEmptySpaceMenuIfApplicable ( MouseEvent arg0 )
{
if ( arg0.isPopupTrigger() )
{
JPopupMenu jpm = new JPopupMenu();
JMenuItem pasteItem = new JMenuItem(new PasteNodeAction(this));
jpm.add(pasteItem);
jpm.show(this,arg0.getX(),arg0.getY());
}
}
public void showArrowMenuIfApplicable( MouseEvent arg0 , Arrow a )
{
if ( arg0.isPopupTrigger() )
{
JPopupMenu jpm = new JPopupMenu();
JMenuItem delItem = new JMenuItem(new DeleteArrowAction(a,this));
jpm.add(delItem);
jpm.show(this,arg0.getX(),arg0.getY());
}
}
public void showNodeMenuIfApplicable ( MouseEvent arg0 , Node n )
{
if ( arg0.isPopupTrigger() )
{
JPopupMenu jpm = new JPopupMenu();
JMenuItem cutItem = new JMenuItem(new CutNodeAction(n,this));
jpm.add(cutItem);
JMenuItem copyItem = new JMenuItem(new CopyNodeAction(n,this));
jpm.add(copyItem);
jpm.add(new JSeparator());
JMenuItem delItem = new JMenuItem(new DeleteNodeAction(n,this));
jpm.add(delItem);
jpm.show(this,arg0.getX(),arg0.getY());
}
}
public void mousePressed(MouseEvent arg0)
{
lastPressX = arg0.getX();
lastPressY = arg0.getY();
if ( toolListener != null )
toolListener.mousePressed(arg0);
else
{
Node n = nodeAt(panelToMapX(arg0.getX()),panelToMapY(arg0.getY()));
if ( n != null )
{
propP.show(n);
resetSelections();
selectNode(n);
showNodeMenuIfApplicable(arg0,n);
}
else
{
Arrow a = arrowAt(panelToMapX(arg0.getX()),panelToMapY(arg0.getY()));
if ( a != null )
{
propP.show(a);
resetSelections();
selectArrow(a);
//if ( arg0.getButton() == MouseEvent.BUTTON3 )
showArrowMenuIfApplicable(arg0,a);
}
else
{
propP.show(worldN);
resetSelections();
showEmptySpaceMenuIfApplicable(arg0);
}
}
}
repaint();
}
public void mouseReleased(MouseEvent arg0)
{
if ( toolListener != null )
toolListener.mouseReleased(arg0);
else if ( specialNode != null )
{
int newLocationX = panelToMapX(arg0.getX());
int newLocationY = panelToMapY(arg0.getY());
if ( isSnapToGridEnabled( ))
{
newLocationX = (newLocationX/20)*20;
newLocationY = (newLocationY/20)*20;
}
specialNode.setLocation(newLocationX,newLocationY);
addNode(specialNode);
setSpecialNode(null);
repaint();
}
else
{
Node n = nodeAt(panelToMapX(arg0.getX()),panelToMapY(arg0.getY()));
if ( n!=null ) showNodeMenuIfApplicable(arg0,n);
else
{
Arrow a = arrowAt(panelToMapX(arg0.getX()),panelToMapY(arg0.getY()));
if ( a != null ) showArrowMenuIfApplicable(arg0,a);
else showEmptySpaceMenuIfApplicable(arg0);
}
}
}
public void mouseDragged(MouseEvent arg0)
{
if ( toolMotionListener != null )
toolMotionListener.mouseDragged(arg0);
else
{
if ( specialNode == null )
{
Node n = nodeAt(panelToMapX(arg0.getX()),panelToMapY(arg0.getY()));
if ( n != null && n.isSelected() )
{
removeNode(n);
setSpecialNode(n);
}
else
{
//view translation function (center view on cursor)
//TODO
double xDrag = arg0.getX() - lastPressX;
double yDrag = arg0.getY() - lastPressY;
if ( "push".equals(PuckConfiguration.getInstance().getProperty("translateMode")) )
{
viewXOffset += Math.ceil(xDrag/viewZoom);
viewYOffset += Math.ceil(yDrag/viewZoom);
}
else //"hold"
{
viewXOffset -= Math.ceil(xDrag/viewZoom);
viewYOffset -= Math.ceil(yDrag/viewZoom);
}
/*
if ( viewXOffset < 0 ) viewXOffset = 0;
if ( viewYOffset < 0 ) viewYOffset = 0;
if ( viewXOffset + this.getWidth()/viewZoom > bufferW-10 )
viewXOffset = bufferW-10-this.getWidth()/viewZoom;
if ( viewYOffset + this.getWidth()/viewZoom > bufferH-10 )
viewYOffset = bufferH-10-this.getWidth()/viewZoom;
*/
lastPressX = arg0.getX();
lastPressY = arg0.getY();
repaint();
/*
System.out.println("*"+panelToMapX(arg0.getX()));
System.out.println("#"+getWidth());
System.out.println(viewXOffset+","+viewYOffset);
viewXOffset = -this.getWidth()/2/viewZoom + panelToMapX(arg0.getX());
viewYOffset = -this.getHeight()/2/viewZoom + panelToMapY(arg0.getY());
if ( viewXOffset < 0 ) viewXOffset = 0;
if ( viewYOffset < 0 ) viewYOffset = 0;
System.out.println("*"+panelToMapX(arg0.getX()));
System.out.println(viewXOffset+","+viewYOffset);
repaint();
*/
}
}
else
{
//if ( snapToGrid )
// specialNode.setLocation((panelToMapX(arg0.getX())/20)*20,(panelToMapY(arg0.getY())/20)*20);
//else
int newLocationX = panelToMapX(arg0.getX());
int newLocationY = panelToMapY(arg0.getY());
if ( isSnapToGridEnabled( ))
{
newLocationX = (newLocationX/20)*20;
newLocationY = (newLocationY/20)*20;
}
specialNode.setLocation(newLocationX,newLocationY);
repaint();
}
}
/*
else if ( specialNode != null )
{
System.out.println("Dropped: " +specialNode + specialNode.getBounds());
specialNode.setLocation(arg0.getX(),arg0.getY());
addNode(specialNode);
setSpecialNode(null);
repaint();
}
*/
/*
else
{
if ( specialNode != null )
{
specialNode.setLocation(arg0.getX(),arg0.getY());
repaint();
}
}
*/
}
private Node currentHighlightedNode = null;
private Arrow currentHighlightedArrow = null;
public void mouseMoved(MouseEvent arg0)
{
if ( toolMotionListener != null )
toolMotionListener.mouseMoved(arg0);
else
{
Node n = nodeAt(panelToMapX(arg0.getX()),panelToMapY(arg0.getY()));
if ( currentHighlightedNode != null && currentHighlightedNode != n )
{
currentHighlightedNode.setHighlighted ( false );
currentHighlightedNode = null;
repaint();
}
if ( n != null && currentHighlightedNode != n )
{
n.setHighlighted ( true );
currentHighlightedNode = n;
repaint();
}
Arrow a = arrowAt(panelToMapX(arg0.getX()),panelToMapY(arg0.getY()));
if ( currentHighlightedArrow != null && currentHighlightedArrow != a )
{
currentHighlightedArrow.setHighlighted ( false );
currentHighlightedArrow = null;
repaint();
}
if ( a != null && currentHighlightedArrow != a )
{
a.setHighlighted ( true );
currentHighlightedArrow = a;
repaint();
}
}
/*
else
{
if ( specialNode != null )
{
specialNode.setLocation(arg0.getX(),arg0.getY());
repaint();
}
}
*/
}
private static double MOUSE_WHEEL_VIEW_MOVEMENT_SPEED = 50.0;
public void mouseWheelMoved ( MouseWheelEvent e )
{
if ( e.isControlDown() ) //zoom with Ctrl+mouse wheel
{
int rotation = e.getWheelRotation(); //negative: up (zoom in), positive: down (zoom out)
if ( rotation < 0 )
{
multiplyZoom ( Math.pow(1.1,Math.abs(rotation)) );
}
else
{
multiplyZoom ( 1.0/Math.pow(1.1,Math.abs(rotation)) );
}
repaint();
}
else if ( e.isShiftDown() ) //horizontal movement with Shift+mouse wheel
{
int rotation = e.getWheelRotation(); //negative: up (go up), positive: down (go down)
setViewXOffset( getViewXOffset() + Math.round(rotation / getViewZoom() * MOUSE_WHEEL_VIEW_MOVEMENT_SPEED));
repaint();
}
else //if ( e.isAltDown() ) //vertical movement with Alt+mouse wheel
{
int rotation = e.getWheelRotation(); //negative: up (go up), positive: down (go down)
setViewYOffset( getViewYOffset() + Math.round(rotation / getViewZoom() * MOUSE_WHEEL_VIEW_MOVEMENT_SPEED));
repaint();
}
}
public boolean confirmDeletion ( Object obj )
{
int option = JOptionPane.showConfirmDialog( null , UIMessages.getInstance().getMessage("confirm.delete.element.message") , UIMessages.getInstance().getMessage("confirm.delete.element.title") + " " + obj , JOptionPane.OK_CANCEL_OPTION , JOptionPane.QUESTION_MESSAGE );
return ( option == JOptionPane.OK_OPTION );
}
public void keyPressed ( KeyEvent evt ) {}
public void keyReleased ( KeyEvent evt )
{
//System.err.println("Released " + evt.getKeyCode() + " vs " + KeyEvent.VK_DELETE );
if ( evt.getKeyCode() == KeyEvent.VK_DELETE )
{
if ( selectedNode != null && confirmDeletion(selectedNode.getName()) )
{
totallyRemoveNode(selectedNode);
}
else if ( selectedArrow != null && confirmDeletion(selectedArrow.getName()) )
{
selectedArrow.getSource().removeArrow(selectedArrow);
}
repaint();
}
}
public void keyTyped ( KeyEvent evt )
{
/*
System.err.println("Typed " + evt.getKeyCode() + " vs " + KeyEvent.VK_DELETE );
if ( evt.getKeyCode() == KeyEvent.VK_DELETE )
{
if ( selectedNode != null )
{
totallyRemoveNode(selectedNode);
}
else if ( selectedArrow != null )
{
selectedArrow.getSource().removeArrow(selectedArrow);
}
}
*/
}
public GraphEditingPanel( PropertiesPanel propP )
{
setBackground(getColorSetting("background"));
addMouseListener(this);
addMouseMotionListener(this);
addMouseWheelListener(this);
setFocusable(true); //will generate key evts.
addKeyListener(this);
setVisible(true);
this.propP = propP;
roomNodes.add(UIMessages.getInstance().getMessage("none"));
itemNodes.add(UIMessages.getInstance().getMessage("none"));
charNodes.add(UIMessages.getInstance().getMessage("none"));
resetNodeLists();
}
public void setToolListener ( MouseListener ml )
{
toolListener = ml;
}
public void setToolMotionListener ( MouseMotionListener ml )
{
toolMotionListener = ml;
}
public void resetToolListeners ( )
{
toolListener = null;
//toolMotionListener = new DefaultMouseMotionListener(this);
toolMotionListener = null;
}
public void centerViewOn(Node n)
{
double nodeX = mapToPanelX ( n.getBounds().getCenterX() );
double nodeY = mapToPanelY ( n.getBounds().getCenterY() );
double viewCenterX = this.getWidth() / 2;
double viewCenterY = this.getHeight() / 2;
viewXOffset += ((nodeX-viewCenterX)/viewZoom);
viewYOffset += ((nodeY-viewCenterY)/viewZoom);
}
/**
* @return Returns the viewXOffset.
*/
public double getViewXOffset() {
return viewXOffset;
}
/**
* @param viewXOffset The viewXOffset to set.
*/
public void setViewXOffset(double viewXOffset) {
this.viewXOffset = viewXOffset;
}
/**
* @return Returns the viewYOffset.
*/
public double getViewYOffset() {
return viewYOffset;
}
/**
* @param viewYOffset The viewYOffset to set.
*/
public void setViewYOffset(double viewYOffset) {
this.viewYOffset = viewYOffset;
}
/**
* @return Returns the viewZoom.
*/
public double getViewZoom() {
return viewZoom;
}
/**
* @param viewZoom The viewZoom to set.
*/
public void setViewZoom(double viewZoom) {
this.viewZoom = viewZoom;
}
}