graphpanel.java
来自「用java实现UML建模,由高手编写..适合有一定能力的java程序员学习」· Java 代码 · 共 624 行 · 第 1/2 页
JAVA
624 行
/*
Violet - A program for editing UML diagrams.
Copyright (C) 2002 Cay S. Horstmann (http://horstmann.com)
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.horstmann.violet.framework;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Point2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JPanel;
import javax.swing.JOptionPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.ResourceBundle;
import java.util.Set;
/**
* A panel to draw a graph
*/
public class GraphPanel extends JPanel
{
/**
* Constructs a graph.
* @param aToolBar the tool bar with the node and edge tools
*/
public GraphPanel(ToolBar aToolBar)
{
grid = new Grid();
gridSize = GRID;
grid.setGrid((int) gridSize, (int) gridSize);
zoom = 1;
toolBar = aToolBar;
setBackground(Color.WHITE);
selectedItems = new HashSet();
addMouseListener(new MouseAdapter()
{
public void mousePressed(MouseEvent event)
{
requestFocus();
final Point2D mousePoint = new Point2D.Double(event.getX() / zoom,
event.getY() / zoom);
boolean isCtrl = (event.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0;
Node n = graph.findNode(mousePoint);
Edge e = graph.findEdge(mousePoint);
Object tool = toolBar.getSelectedTool();
if (event.getClickCount() > 1
|| (event.getModifiers() & InputEvent.BUTTON1_MASK) == 0)
// double/right-click
{
if (e != null)
{
setSelectedItem(e);
editSelected();
}
else if (n != null)
{
setSelectedItem(n);
editSelected();
}
else
{
toolBar.showPopup(GraphPanel.this, mousePoint,
new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
Object tool = toolBar.getSelectedTool();
if (tool instanceof Node)
{
Node prototype = (Node) tool;
Node newNode = (Node) prototype.clone();
boolean added = graph.add(newNode, mousePoint);
if (added)
{
setModified(true);
setSelectedItem(newNode);
}
}
}
});
}
}
else if (tool == null) // select
{
if (e != null)
{
setSelectedItem(e);
}
else if (n != null)
{
if (isCtrl)
addSelectedItem(n);
else if (!selectedItems.contains(n))
setSelectedItem(n);
dragMode = DRAG_MOVE;
}
else
{
if (!isCtrl)
clearSelection();
dragMode = DRAG_LASSO;
}
}
else if (tool instanceof Node)
{
Node prototype = (Node) tool;
Node newNode = (Node) prototype.clone();
boolean added = graph.add(newNode, mousePoint);
if (added)
{
setModified(true);
setSelectedItem(newNode);
dragMode = DRAG_MOVE;
}
else if (n != null)
{
if (isCtrl)
addSelectedItem(n);
else if (!selectedItems.contains(n))
setSelectedItem(n);
dragMode = DRAG_MOVE;
}
}
else if (tool instanceof Edge)
{
if (n != null) dragMode = DRAG_RUBBERBAND;
}
lastMousePoint = mousePoint;
mouseDownPoint = mousePoint;
repaint();
}
public void mouseReleased(MouseEvent event)
{
Point2D mousePoint = new Point2D.Double(event.getX() / zoom,
event.getY() / zoom);
Object tool = toolBar.getSelectedTool();
if (dragMode == DRAG_RUBBERBAND)
{
Edge prototype = (Edge) tool;
Edge newEdge = (Edge) prototype.clone();
if (mousePoint.distance(mouseDownPoint) > CONNECT_THRESHOLD
&& graph.connect(newEdge, mouseDownPoint, mousePoint))
{
setModified(true);
setSelectedItem(newEdge);
}
}
else if (dragMode == DRAG_MOVE)
{
graph.layout();
setModified(true);
}
dragMode = DRAG_NONE;
revalidate();
repaint();
}
});
addMouseMotionListener(new MouseMotionAdapter()
{
public void mouseDragged(MouseEvent event)
{
Point2D mousePoint = new Point2D.Double(event.getX() / zoom,
event.getY() / zoom);
boolean isCtrl = (event.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0;
if (dragMode == DRAG_MOVE && lastSelected instanceof Node)
{
Node lastNode = (Node) lastSelected;
Rectangle2D bounds = lastNode.getBounds();
double dx = mousePoint.getX() - lastMousePoint.getX();
double dy = mousePoint.getY() - lastMousePoint.getY();
// we don't want to drag nodes into negative coordinates
// particularly with multiple selection, we might never be
// able to get them back.
Iterator iter = selectedItems.iterator();
while (iter.hasNext())
{
Object selected = iter.next();
if (selected instanceof Node)
{
Node n = (Node) selected;
bounds.add(n.getBounds());
}
}
dx = Math.max(dx, -bounds.getX());
dy = Math.max(dy, -bounds.getY());
iter = selectedItems.iterator();
while (iter.hasNext())
{
Object selected = iter.next();
if (selected instanceof Node)
{
Node n = (Node) selected;
n.translate(dx, dy);
}
}
// we don't want continuous layout any more because of multiple selection
// graph.layout();
}
else if (dragMode == DRAG_LASSO)
{
double x1 = mouseDownPoint.getX();
double y1 = mouseDownPoint.getY();
double x2 = mousePoint.getX();
double y2 = mousePoint.getY();
Rectangle2D.Double lasso = new Rectangle2D.Double(Math.min(x1, x2),
Math.min(y1, y2), Math.abs(x1 - x2) , Math.abs(y1 - y2));
Iterator iter = graph.getNodes().iterator();
while (iter.hasNext())
{
Node n = (Node) iter.next();
Rectangle2D bounds = n.getBounds();
if (!isCtrl && !lasso.contains(n.getBounds()))
{
removeSelectedItem(n);
}
else if (lasso.contains(n.getBounds()))
{
addSelectedItem(n);
}
}
}
lastMousePoint = mousePoint;
repaint();
}
});
}
/**
* Edits the properties of the selected graph element.
*/
public void editSelected()
{
Object edited = lastSelected;
if (lastSelected == null)
{
if (selectedItems.size() == 1)
edited = selectedItems.iterator().next();
else
return;
}
PropertySheet sheet = new PropertySheet(edited, this);
sheet.addChangeListener(new ChangeListener()
{
public void stateChanged(ChangeEvent event)
{
graph.layout();
repaint();
}
});
JOptionPane.showInternalMessageDialog(this, sheet,
ResourceBundle.getBundle("com.horstmann.violet.framework.EditorStrings").getString("dialog.properties"),
JOptionPane.QUESTION_MESSAGE);
setModified(true);
}
/**
* Removes the selected nodes or edges.
*/
public void removeSelected()
{
Iterator iter = selectedItems.iterator();
while (iter.hasNext())
{
Object selected = iter.next();
if (selected instanceof Node)
{
graph.removeNode((Node) selected);
}
else if (selected instanceof Edge)
{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?