org.jgraph.graph.VertexView Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ingeniasjgraphmod Show documentation
Show all versions of ingeniasjgraphmod Show documentation
A modified version of some JGraph files
The newest version!
/*
* @(#)VertexView.java 1.0 03-JUL-04
*
* Copyright (c) 2001-2004 Gaudenz Alder
*
*/
package org.jgraph.graph;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.jgraph.JGraph;
import org.jgraph.plaf.GraphUI;
import org.jgraph.plaf.basic.BasicGraphUI;
/**
* The default implementation of a vertex view.
*
* @version 1.0 1/1/02
* @author Gaudenz Alder
*/
public class VertexView extends AbstractCellView {
/** Renderer for the class. */
public static transient VertexRenderer renderer;
// Headless environment does not allow vertex renderer
static {
try {
renderer = new VertexRenderer();
} catch (Error e) {
// No vertex renderer
}
}
public final static Rectangle2D defaultBounds = new Rectangle2D.Double(10,
10, 20, 20);
/** Reference to the bounds attribute */
protected Rectangle2D bounds;
/**
* Constructs an empty vertex view.
*/
public VertexView() {
super();
}
/**
* Constructs a vertex view for the specified model object and the specified
* child views.
*
* @param cell
* reference to the model object
*/
public VertexView(Object cell) {
super(cell);
}
//
// CellView Interface
//
/**
* Overrides the parent method to udpate the cached points.
*/
public void update(GraphLayoutCache cache) {
super.update(cache);
bounds = GraphConstants.getBounds(allAttributes);
if (bounds == null) {
bounds = allAttributes.createRect(defaultBounds);
GraphConstants.setBounds(allAttributes, bounds);
}
groupBounds = null;
}
public Rectangle2D getCachedBounds() {
return bounds;
}
public void setCachedBounds(Rectangle2D bounds) {
this.bounds = bounds;
}
/**
* Returns a renderer for the class.
*/
public CellViewRenderer getRenderer() {
return renderer;
}
/**
* Returns a cell handle for the view, if the graph and the view are
* sizeable.
*/
public CellHandle getHandle(GraphContext context) {
if (GraphConstants.isSizeable(getAllAttributes())
&& !GraphConstants.isAutoSize(getAllAttributes())
&& context.getGraph().isSizeable())
return new SizeHandle(this, context);
return null;
}
/**
* Returns the cached bounds for the vertex.
*/
public Rectangle2D getBounds() {
Rectangle2D rect = super.getBounds();
if (rect == null)
rect = bounds;
return rect;
}
/**
* @deprecated replaced by
* {@link AbstractCellView#getCenterPoint(CellView vertex)}
* @return the center point of this vertex
*/
public Point2D getCenterPoint() {
return AbstractCellView.getCenterPoint(this);
}
/**
* @deprecated replaced by
* {@link #getPerimeterPoint(EdgeView edge, Point2D source, Point2D p)}
*/
public Point2D getPerimeterPoint(Point2D source, Point2D p) {
return AbstractCellView.getCenterPoint(this);
}
//
// Special Methods
//
/**
* Returns the intersection of the bounding rectangle and the straight line
* between the source and the specified point p. The specified point is
* expected not to intersect the bounds. Note: You must override this method
* if you use a different renderer. This is because this method relies on
* the VertexRenderer interface, which can not be safely assumed for
* subclassers.
*/
public Point2D getPerimeterPoint(EdgeView edge, Point2D source, Point2D p) {
if (getRenderer() instanceof VertexRenderer)
return ((VertexRenderer) getRenderer()).getPerimeterPoint(this,
source, p);
return super.getPerimeterPoint(edge, source, p);
}
/** Array that holds the cursors for the different control points. */
public static transient int[] defaultCursors = new int[] {
Cursor.NW_RESIZE_CURSOR, Cursor.N_RESIZE_CURSOR,
Cursor.NE_RESIZE_CURSOR, Cursor.W_RESIZE_CURSOR,
Cursor.E_RESIZE_CURSOR, Cursor.SW_RESIZE_CURSOR,
Cursor.S_RESIZE_CURSOR, Cursor.SE_RESIZE_CURSOR };
/** Array that holds the cursors for the different control points. */
public static transient int[] xCursors = new int[] {
Cursor.W_RESIZE_CURSOR, 0, Cursor.E_RESIZE_CURSOR,
Cursor.W_RESIZE_CURSOR, Cursor.E_RESIZE_CURSOR,
Cursor.W_RESIZE_CURSOR, 0, Cursor.E_RESIZE_CURSOR };
/** Array that holds the cursors for the different control points. */
public static transient int[] yCursors = new int[] {
Cursor.N_RESIZE_CURSOR, Cursor.N_RESIZE_CURSOR,
Cursor.N_RESIZE_CURSOR, 0, 0, Cursor.S_RESIZE_CURSOR,
Cursor.S_RESIZE_CURSOR, Cursor.S_RESIZE_CURSOR };
public static class SizeHandle implements CellHandle, Serializable {
/** Reference to graph off screen graphics */
protected transient Graphics offgraphics;
protected transient boolean firstDrag = true;
protected transient JGraph graph;
/* Reference to the temporary view for this handle. */
protected transient VertexView vertex;
protected transient CellView[] portViews;
protected transient Rectangle2D cachedBounds;
/* Reference to the context for the specified view. */
protected transient GraphContext context;
protected transient Rectangle2D initialBounds;
protected transient CellView[] contextViews;
/* Index of the active control point. -1 if none is active. */
protected transient int index = -1;
/* Array of control points represented as rectangles. */
protected transient Rectangle2D[] r = new Rectangle2D[8];
protected boolean firstOverlayInvocation = true;
/** Array that holds the cursors for the different control points. */
public transient int[] cursors = null;
/**
* True if the cell is being edited.
*/
protected boolean editing = false;
public SizeHandle(VertexView vertexview, GraphContext ctx) {
graph = ctx.getGraph();
vertex = vertexview;
editing = graph.getEditingCell() == vertex.getCell();
int sizeableAxis = GraphConstants.getSizeableAxis(vertex
.getAllAttributes());
if (sizeableAxis == GraphConstants.X_AXIS)
cursors = xCursors;
else if (sizeableAxis == GraphConstants.Y_AXIS)
cursors = yCursors;
else
cursors = defaultCursors;
// PortView Preview
portViews = ctx.createTemporaryPortViews();
initialBounds = (Rectangle2D) vertex.getBounds().clone();
context = ctx;
for (int i = 0; i < r.length; i++)
r[i] = new Rectangle2D.Double();
invalidate();
}
public boolean isConstrainedSizeEvent(MouseEvent e) {
GraphUI ui = graph.getUI();
if (ui instanceof BasicGraphUI)
return ((BasicGraphUI) ui).isConstrainedMoveEvent(e);
return false;
}
public void paint(Graphics g) {
invalidate();
g.setColor((editing) ? graph.getLockedHandleColor() : graph
.getHandleColor());
for (int i = 0; i < r.length; i++) {
if (cursors[i] != 0)
g
.fill3DRect((int) r[i].getX(), (int) r[i].getY(),
(int) r[i].getWidth(), (int) r[i]
.getHeight(), true);
}
if (!graph.isXorEnabled()) {
firstOverlayInvocation = false;
overlay(g);
}
}
protected void initOffscreen() {
if (!graph.isXorEnabled()) {
return;
}
try {
offgraphics = graph.getOffgraphics();
} catch (Exception e) {
offgraphics = null;
} catch (Error e) {
offgraphics = null;
}
}
public void overlay(Graphics g) {
if (!firstOverlayInvocation) {
if (cachedBounds != null) {
g.setColor(Color.black);
Rectangle2D tmp = graph.toScreen((Rectangle2D) cachedBounds
.clone());
g.drawRect((int) tmp.getX(), (int) tmp.getY(), (int) tmp
.getWidth() - 2, (int) tmp.getHeight() - 2);
} else if (!initialBounds.equals(vertex.getBounds())) {
Graphics2D g2 = (Graphics2D) g;
AffineTransform oldTransform = g2.getTransform();
g2.scale(graph.getScale(), graph.getScale());
graph.getUI()
.paintCell(g, vertex, vertex.getBounds(), true);
if (contextViews != null) {
for (int i = 0; i < contextViews.length; i++) {
graph.getUI().paintCell(g, contextViews[i],
contextViews[i].getBounds(), true);
}
}
if (!graph.isPortsScaled())
g2.setTransform(oldTransform);
if (portViews != null && graph.isPortsVisible())
graph.getUI().paintPorts(g, portViews);
g2.setTransform(oldTransform);
}
}
firstOverlayInvocation = false;
}
/**
* Invoked when the mouse pointer has been moved on a component (with no
* buttons down).
*/
public void mouseMoved(MouseEvent event) {
if (vertex != null) {
for (int i = 0; i < r.length; i++) {
if (r[i].contains(event.getPoint())) {
graph.setCursor(new Cursor(cursors[i]));
event.consume();
return;
}
}
}
}
/** Process mouse pressed event. */
public void mousePressed(MouseEvent event) {
if (!graph.isSizeable())
return;
for (int i = 0; i < r.length; i++) {
if (r[i].contains(event.getPoint()) && cursors[i] != 0) {
Set set = new HashSet();
set.add(vertex.getCell());
contextViews = context.createTemporaryContextViews(set);
Object[] all = AbstractCellView
.getDescendantViews(new CellView[] { vertex });
if (all.length >= org.jgraph.plaf.basic.BasicGraphUI.MAXHANDLES)
cachedBounds = (Rectangle2D) initialBounds.clone();
event.consume();
index = i;
return;
}
}
}
/** Process mouse dragged event. */
public void mouseDragged(MouseEvent event) {
if (firstDrag && graph.isDoubleBuffered() && cachedBounds == null) {
initOffscreen();
firstDrag = false;
}
Rectangle2D dirty = null;
Graphics g = (offgraphics != null) ? offgraphics : graph
.getGraphics();
if (index == -1)
return;
if (offgraphics != null || !graph.isXorEnabled()) {
dirty = graph
.toScreen((Rectangle2D) vertex.getBounds().clone());
Rectangle2D t = graph.toScreen(AbstractCellView
.getBounds(contextViews));
if (t != null)
dirty.add(t);
}
Rectangle2D newBounds = computeBounds(event);
if (graph.isXorEnabled()) {
g.setColor(graph.getForeground());
g.setXORMode(graph.getBackground().darker());
overlay(g);
} else {
firstOverlayInvocation = false;
}
if (cachedBounds != null)
cachedBounds = newBounds;
else {
// Reset old Bounds
CellView[] all = AbstractCellView
.getDescendantViews(new CellView[] { vertex });
for (int i = 0; i < all.length; i++) {
CellView orig = graph.getGraphLayoutCache().getMapping(
all[i].getCell(), false);
if (orig != null) {
AttributeMap origAttr = (AttributeMap) orig
.getAllAttributes().clone();
all[i].changeAttributes(graph.getGraphLayoutCache(), origAttr);
all[i].refresh(graph.getGraphLayoutCache(), context, false);
}
}
vertex.setBounds(newBounds);
if (vertex != null)
graph.getGraphLayoutCache().update(vertex);
if (contextViews != null)
graph.getGraphLayoutCache().update(contextViews);
}
if (graph.isXorEnabled()) {
overlay(g);
}
if (offgraphics != null || !graph.isXorEnabled()) {
dirty.add(graph.toScreen((Rectangle2D) vertex.getBounds()
.clone()));
Rectangle2D t = graph.toScreen(AbstractCellView
.getBounds(contextViews));
if (t != null)
dirty.add(t);
int border = PortView.SIZE + 10;
if (graph.isPortsScaled())
border = (int) (graph.getScale() * border);
int border2 = border / 2;
dirty.setFrame(dirty.getX() - border2, dirty.getY() - border2,
dirty.getWidth() + border, dirty.getHeight() + border);
double sx1 = Math.max(0, dirty.getX());
double sy1 = Math.max(0, dirty.getY());
double sx2 = sx1 + dirty.getWidth();
double sy2 = sy1 + dirty.getHeight();
if (offgraphics != null) {
graph.drawImage((int) sx1, (int) sy1, (int) sx2, (int) sy2,
(int) sx1, (int) sy1, (int) sx2, (int) sy2);
} else {
graph.repaint((int) dirty.getX(), (int) dirty.getY(),
(int) dirty.getWidth(), (int) dirty.getHeight());
}
}
}
protected Rectangle2D computeBounds(MouseEvent event) {
double left = initialBounds.getX();
double right = initialBounds.getX() + initialBounds.getWidth() - 1;
double top = initialBounds.getY();
double bottom = initialBounds.getY() + initialBounds.getHeight()
- 1;
Point2D p = graph.fromScreen(graph.snap((Point2D) event.getPoint()
.clone()));
// Not into negative coordinates
p.setLocation(Math.max(0, p.getX()), Math.max(0, p.getY()));
// Bottom row
if (index > 4)
bottom = p.getY();
// Top row
else if (index < 3)
top = p.getY();
// Left col
if (index == 0 || index == 3 || index == 5)
left = p.getX();
// Right col
else if (index == 2 || index == 4 || index == 7)
right = p.getX();
double width = right - left;
double height = bottom - top;
if (isConstrainedSizeEvent(event)
|| GraphConstants.isConstrained(vertex.getAllAttributes())) {
if (index == 3 || index == 4 || index == 5)
height = width;
else if (index == 1 || index == 6 || index == 2 || index == 7)
width = height;
else {
height = width;
top = bottom - height;
}
}
if (width < 0) { // Flip over left side
left += width;
width = Math.abs(width);
}
if (height < 0) { // Flip over top side
top += height;
height = Math.abs(height);
}
return new Rectangle2D.Double(left, top, width + 1, height + 1);
}
// Dispatch the edit event
public void mouseReleased(MouseEvent e) {
if (index != -1) {
cachedBounds = computeBounds(e);
vertex.setBounds(cachedBounds);
CellView[] views = AbstractCellView
.getDescendantViews(new CellView[] { vertex });
Map attributes = GraphConstants.createAttributes(views, null);
graph.getGraphLayoutCache().edit(attributes, null, null, null);
}
e.consume();
cachedBounds = null;
initialBounds = null;
firstDrag = true;
}
protected void invalidate() {
// Retrieve current bounds and set local vars
Rectangle2D tmp = graph.getCellBounds(vertex.getCell());
if (tmp != null) {
tmp = (Rectangle2D) tmp.clone();
graph.toScreen(tmp);
int handlesize = graph.getHandleSize();
int s2 = 2 * handlesize;
double left = tmp.getX() - handlesize;
double top = tmp.getY() - handlesize;
double w2 = tmp.getX() + (tmp.getWidth() / 2) - handlesize;
double h2 = tmp.getY() + (tmp.getHeight() / 2) - handlesize;
double right = tmp.getX() + tmp.getWidth() - handlesize;
double bottom = tmp.getY() + tmp.getHeight() - handlesize;
// Update control point positions
r[0].setFrame(left, top, s2, s2);
r[1].setFrame(w2, top, s2, s2);
r[2].setFrame(right, top, s2, s2);
r[3].setFrame(left, h2, s2, s2);
r[4].setFrame(right, h2, s2, s2);
r[5].setFrame(left, bottom, s2, s2);
r[6].setFrame(w2, bottom, s2, s2);
r[7].setFrame(right, bottom, s2, s2);
}
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy