/*
* NexsmRenderersGraphMousePlugin.java
*
* Copyright (C) 2006 Sergio Guzman Lorz <sergio AT gridshield.net>
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
* Created on April 20, 2006, 11:57 AM
*/
package net.gridshield.nexsm.graphmanager;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Rectangle;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import javax.swing.JColorChooser;
import javax.swing.JComponent;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import net.gridshield.nexsm.graphics.NexsmPaintable;
import net.gridshield.nexsm.graphics.NexsmPaintableLine;
import net.gridshield.nexsm.graphics.NexsmPaintableText;
/**
*
* @author Sergio Guzmán Lorz
*/
public class NexsmRenderersGraphMousePlugin extends NexsmGraphMousePlugin implements
MouseListener, MouseMotionListener {
protected int addToSelectionModifiers;
NexsmPaintable selectedRenderer = null;
List<NexsmPaintable> possibleRenderers = null;
VisualizationViewer selectedVV = null;
JPopupMenu jpm = null;
LensCorners corners;
boolean dragging = false;
boolean added = false;
Point2D down;
int corner = -1;
JMenuItem fontsize = null;
JMenuItem jtext = null;
JMenuItem thick = null;
LinkedList <NexsmPaintable>selectedRenderers = null;
LinkedList <LensCorners>lenscorners;
private static int mask = MouseEvent.BUTTON3_MASK;
private static int btn = MouseEvent.BUTTON3_MASK;
static {
if(System.getProperty("os.name").startsWith("Mac")) {
mask = (MouseEvent.CTRL_MASK | MouseEvent.BUTTON1_MASK);
}
}
ActionListener jpopupmenulistener = null;
/** Creates a new instance of NexsmRenderersGraphMousePlugin */
public NexsmRenderersGraphMousePlugin() {
this(mask, InputEvent.BUTTON1_MASK | InputEvent.SHIFT_MASK);
this.cursor = Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR);
}
public NexsmRenderersGraphMousePlugin(int modifiers, int addToSelectionModifiers) {
super(modifiers);
this.addToSelectionModifiers = addToSelectionModifiers;
possibleRenderers = new LinkedList<NexsmPaintable>();
jpopupmenulistener = new NexsmRenderersJPopupMenuListener();
corners = new LensCorners();
initJPopupMenu();
selectedRenderers = new LinkedList<NexsmPaintable>();
lenscorners = new LinkedList<LensCorners>();
}
private void initJPopupMenu() {
jpm = new JPopupMenu();
JMenuItem jmei = jpm.add("Delete");
jmei.setActionCommand("delete");
jmei.addActionListener(jpopupmenulistener);
jtext = jpm.add("Change Text");
jmei = jtext;
jmei.setActionCommand("text");
jmei.addActionListener(jpopupmenulistener);
jmei = jpm.add("Change color");
jmei.setActionCommand("color");
jmei.addActionListener(jpopupmenulistener);
fontsize = jpm.add("Font Size");
jmei = fontsize;
jmei.setActionCommand("size");
jmei.addActionListener(jpopupmenulistener);
thick = jpm.add("Thickness");
jmei = thick;
jmei.setActionCommand("thick");
jmei.addActionListener(jpopupmenulistener);
jmei = jpm.add("Copy");
jmei.setActionCommand("copy");
jmei.addActionListener(jpopupmenulistener);
}
public void clearSelected() {
if (selectedRenderer != null) {
selectedRenderer = null;
}
if (selectedVV != null) {
if (corners != null) {
selectedVV.removePreRenderPaintable(corners);
}
selectedVV.getPickedState().clearPickedEdges();
}
}
public void mouseReleased(MouseEvent e) {
if (selectedVV != null &&
selectedRenderer == null) {
selectedVV.removePreRenderPaintable(corners);
added = false;
}
((JComponent)e.getSource()).setCursor(Cursor.getDefaultCursor());
corner = -1;
}
public void mousePressed(MouseEvent e) {
down = e.getPoint();
selectedVV = (VisualizationViewer)e.getSource();
Point2D q = selectedVV.inverseViewTransform(down);
if (e.getModifiers() == MouseEvent.BUTTON1_MASK) {
if (corners.cornerIndex(q) < 0) {
corner = -1;
ArrayList<NexsmPaintable> rs = gm.getRenderers(selectedVV.getName());
possibleRenderers.clear();
if (rs != null) {
for (NexsmPaintable np: rs) {
if (np.contains(q)) {
possibleRenderers.add(0, np);
}
}
}
if (!possibleRenderers.isEmpty()) {
if (selectedVV != null) {
selectedRenderer = possibleRenderers.get(0);
corners.setCorners(selectedRenderer.getRectangle());
if (!added) {
selectedVV.addPreRenderPaintable(corners);
added = true;
}
((JComponent)e.getSource()).setCursor(cursor);
// selectedVV.add(jpm);
// jpm.setLocation((int)p.getX(), (int)p.getY());
}
} else {
selectedVV.removePreRenderPaintable(corners);
added = false;
selectedRenderer = null;
corner = -1;
}
} else {
corner = corners.cornerIndex(q);
}
} else if (e.getModifiers() == this.addToSelectionModifiers) {
}
if ((checkModifiers(e) || e.getModifiers() == btn)&& selectedRenderer != null) {
if (selectedRenderer.contains(q)) {
if (selectedRenderer instanceof NexsmPaintableText) {
jtext.setVisible(true);
fontsize.setVisible(true);
} else if (selectedRenderer instanceof NexsmPaintableLine) {
thick.setVisible(true);
} else {
jtext.setVisible(false);
fontsize.setVisible(false);
thick.setVisible(false);
}
jpm.show(selectedVV,(int)down.getX(), (int)down.getY());
}
}
}
public void mouseMoved(MouseEvent e) {
JComponent c = (JComponent)e.getSource();
int i = -1;
if (selectedVV != null) {
Point2D q = selectedVV.inverseViewTransform(e.getPoint());
if (corners != null && selectedRenderer != null) {
if ((i = corners.cornerIndex(q)) >= 0) {
if (i == 0 || i == 3) {
c.setCursor(Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR));
} else {
c.setCursor(Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR));
}
} else {
c.setCursor(Cursor.getDefaultCursor());
}
}
}
}
public void mouseExited(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseDragged(MouseEvent e) {
if (e.getModifiers() == MouseEvent.BUTTON1_MASK) {
if (selectedVV != null && selectedRenderer != null) {
Point2D p = selectedVV.inverseTransform(e.getPoint());
//change size using corners
if (corner >= 0) {
if (selectedRenderer.getP2() != null) {
if (corner == 0) {
selectedRenderer.setP1(p);
} else if (corner == 3) {
selectedRenderer.setP2(p);
} else if (corner == 1) {
Point2D q = new Point2D.Double(selectedRenderer.getP1().getX(), p.getY());
selectedRenderer.setP1(q);
q = new Point2D.Double(p.getX(), selectedRenderer.getP2().getY());
selectedRenderer.setP2(q);
} else if (corner == 2) {
Point2D q = new Point2D.Double(selectedRenderer.getP2().getX(), p.getY());
selectedRenderer.setP2(q);
q = new Point2D.Double(p.getX(), selectedRenderer.getP1().getY());
selectedRenderer.setP1(q);
}
}
} else { //move to not using corners
Point2D q1 = selectedRenderer.getP1();
Point2D q2 = selectedRenderer.getP2();
Point2D myDown = selectedVV.inverseTransform(down);
double xdif = p.getX() - myDown.getX();
double ydif = p.getY() - myDown.getY();
q1.setLocation(q1.getX() + xdif, q1.getY() + ydif);
if (q2 != null) {
q2.setLocation(q2.getX() + xdif, q2.getY() + ydif);
}
down = e.getPoint();
}
corners.setCorners(selectedRenderer.getRectangle());
}
}
}
public void mouseClicked(MouseEvent e) {
}
private boolean heyThatsTooClose(Point2D p, Point2D q, double min) {
return Math.abs(p.getX()-q.getX()) < min &&
Math.abs(p.getY()-q.getY()) < min;
}
private class NexsmRenderersJPopupMenuListener implements ActionListener {
JMenuItem jmei = null;
public void actionPerformed(java.awt.event.ActionEvent e) {
jmei = (JMenuItem)e.getSource();
if (jmei.getActionCommand().equals("delete")) {
gm.removeRenderer(selectedVV.getName(), selectedRenderer);
if (selectedVV != null && corners != null) {
selectedVV.removePreRenderPaintable(corners);
}
selectedRenderer = null;
} else if (jmei.getActionCommand().equals("color")) {
Color newColor = JColorChooser.showDialog(selectedVV, "Choose new color", selectedRenderer.getColor());
if (newColor != null) {
selectedRenderer.setColor(newColor);
}
} else if (jmei.getActionCommand().equals("copy")) {
NexsmPaintable np = (NexsmPaintable)selectedRenderer.clone();
gm.putRenderer(selectedVV.getName(), np);
} else if (jmei.getActionCommand().equals("size")) {
if (selectedRenderer instanceof NexsmPaintableText) {
int size = ((NexsmPaintableText)selectedRenderer).getFontSize();
String s = JOptionPane.showInputDialog(selectedVV, "Font Size", (Object)("" + size));
if (s != null) {
try {
size = Integer.parseInt(s);
} catch (NumberFormatException nfe) {
JOptionPane.showMessageDialog(selectedVV, "Invalid number ("+s+")");
}
((NexsmPaintableText)selectedRenderer).setFontSize(size);
}
}
} else if (jmei.getActionCommand().equals("text")) {
if (selectedRenderer instanceof NexsmPaintableText) {
String actualValue = ((NexsmPaintableText)selectedRenderer).getText();
String s = JOptionPane.showInputDialog(selectedVV, "Text", (Object)actualValue);
if (s != null && s.length() > 0) {
((NexsmPaintableText)selectedRenderer).setText(s);
}
}
} else if (jmei.getActionCommand().equals("thick")) {
if (selectedRenderer instanceof NexsmPaintableLine) {
int size = ((NexsmPaintableLine)selectedRenderer).getThickness();
String s = JOptionPane.showInputDialog(selectedVV, "Thickness", (Object)("" + size));
if (s != null) {
try {
size = Integer.parseInt(s);
} catch (NumberFormatException nfe) {
JOptionPane.showMessageDialog(selectedVV, "Invalid number ("+s+")");
}
((NexsmPaintableLine)selectedRenderer).setThickness(size);
}
}
}
}
}
private class LensCorners implements VisualizationViewer.Paintable {
Point2D corners[] = new Point2D.Float[4];
Point2D temp;
Color c = Color.blue;
public LensCorners() {
for (int i = 0; i < 4; i++) {
corners[i] = new Point2D.Float();
}
}
public void paint(java.awt.Graphics g) {
Color oldColor = g.getColor();
g.setColor(c);
for (int i = 0; i < 4; i++) {
g.fillRect((int)corners[i].getX(), (int)corners[i].getY(), 3, 3);
}
g.setColor(oldColor);
}
public void setCorners(Rectangle r) {
corners[0] = new Point2D.Float((float)r.getX(), (float)r.getY());
corners[1] = new Point2D.Float((float)(r.getX() + r.getWidth()), (float)r.getY());
corners[2] = new Point2D.Float((float)r.getX(), (float)(r.getY() + r.getHeight()));
corners[3] = new Point2D.Float((float)(r.getX() + r.getWidth()), (float)(r.getY() + r.getHeight()));
}
public int cornerIndex(Point2D p) {
int index = -1;
for (int i = 0; i < 4; i++) {
if (heyThatsTooClose(p, corners[i], 5)) {
index = i;
break;
}
}
return index;
}
public boolean useTransform() {
return true;
}
}
}