|
What this is
Other links
The source code
// $Id: ModeCreateEdgeAndNode.java,v 1.27 2004/10/03 17:50:19 mvw Exp $
// Copyright (c) 1996-99 The Regents of the University of California. All
// Rights Reserved. Permission to use, copy, modify, and distribute this
// software and its documentation without fee, and without a written
// agreement is hereby granted, provided that the above copyright notice
// and this paragraph appear in all copies. This software program and
// documentation are copyrighted by The Regents of the University of
// California. The software program and documentation are supplied "AS
// IS", without any accompanying services from The Regents. The Regents
// does not warrant that the operation of the program will be
// uninterrupted or error-free. The end-user understands that the program
// was developed for research purposes and is advised not to rely
// exclusively on the program for any reason. IN NO EVENT SHALL THE
// UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
// SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
// ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
// THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
// PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
// CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
// File: ModeCreateEdgeAndNode.java
// Classes: ModeCreateEdgeAndNode
// Original Author: jrobbins
// $Id: ModeCreateEdgeAndNode.java,v 1.27 2004/10/03 17:50:19 mvw Exp $
package org.argouml.uml.diagram.ui;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Collection;
import java.util.Iterator;
import org.apache.log4j.Logger;
import org.argouml.model.ModelFacade;
import org.argouml.model.uml.UmlFactory;
import org.tigris.gef.base.Editor;
import org.tigris.gef.base.Globals;
import org.tigris.gef.base.Layer;
import org.tigris.gef.base.LayerManager;
import org.tigris.gef.base.ModeCreate;
import org.tigris.gef.graph.GraphModel;
import org.tigris.gef.graph.GraphNodeHooks;
import org.tigris.gef.graph.GraphNodeRenderer;
import org.tigris.gef.graph.MutableGraphModel;
import org.tigris.gef.presentation.Fig;
import org.tigris.gef.presentation.FigEdge;
import org.tigris.gef.presentation.FigNode;
import org.tigris.gef.presentation.FigPoly;
import org.tigris.gef.presentation.Handle;
/** A Mode to interpret user input while creating an edge. Basically
* mouse down starts creating an edge from a source port Fig, mouse
* motion paints a rubberband line, mouse up finds the destination port
* and finishes creating the edge and makes an FigEdge and sends
* it to the back of the Layer.
*
* The argument "edgeClass" determines the type if edge to suggest
* that the Editor's GraphModel construct. The GraphModel is
* responsible for acutally making an edge in the underlying model
* and connecting it to other model elements. */
public class ModeCreateEdgeAndNode extends ModeCreate {
private static final Logger LOG =
Logger.getLogger(ModeCreateEdgeAndNode.class);
////////////////////////////////////////////////////////////////
// static variables
private static int dragsToExisting = 0;
private static int dragsToNew = 0;
////////////////////////////////////////////////////////////////
// instance variables
/** The NetPort where the arc is paintn from */
private Object startPort;
/** The Fig that presents the starting NetPort */
private Fig startPortFig;
/** The FigNode on the NetNode that owns the start port */
private FigNode sourceFigNode;
/** The new NetEdge that is being created */
private Object newEdge;
/** False if drawing from source and destination. True if drawing
* from destination to source. */
private boolean destToSource = false;
/** The number of points added so far. */
//protected int _npoints = 0;
private Handle handle = new Handle(-1);
private FigNode fn;
private FigEdge fe;
private boolean postProcessEdge = false;
/**
* The constructor.
*
*/
public ModeCreateEdgeAndNode() {
super();
}
/**
* The constructor.
*
* @param ed the parent editor of this mode. Each Mode instance belongs to
* exactly one Editor instance.
* @param edgeClass the class of the edge
* @param nodeClass the class of the node
* @param post if true, then the edge is postprocessed.
* See postProcessEdge().
*/
public ModeCreateEdgeAndNode(
Editor ed,
Class edgeClass,
Class nodeClass,
boolean post) {
super(ed);
setArg("edgeClass", edgeClass);
setArg("nodeClass", nodeClass);
postProcessEdge = post;
LOG.debug("postprocessing: " + postProcessEdge);
}
////////////////////////////////////////////////////////////////
// accessors
/**
* @param fignode the source fignode
* @param port the port
* @param x the x to start from
* @param y the y to start from
* @param reverse true if the direction is reversed, i.e.
* from destination to source
*/
public void setup(FigNode fignode, Object port, int x, int y,
boolean reverse) {
start();
sourceFigNode = fignode;
startPortFig = fignode.getPortFig(port);
startPort = port;
_newItem = createNewItem(null, x, y);
destToSource = reverse;
setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
}
////////////////////////////////////////////////////////////////
// Mode API
/**
* @see org.tigris.gef.base.FigModifyingMode#instructions()
*/
public String instructions() {
return "Drag to define an edge (and a new node)";
}
////////////////////////////////////////////////////////////////
// ModeCreate API
/**
* Create the new item that will be drawn. In this case I would
* rather create the FigEdge when I am done. Here I just
* create a rubberband FigLine to show during dragging.
*
* @see org.tigris.gef.base.ModeCreate#createNewItem(
* java.awt.event.MouseEvent, int, int)
*/
public Fig createNewItem(MouseEvent me, int snapX, int snapY) {
FigPoly p = new FigPoly(snapX, snapY);
p.setLineColor(Globals.getPrefs().getRubberbandColor());
p.setFillColor(null);
p.addPoint(snapX, snapY); // add the first point twice
//_npoints = 2;
return p;
}
/**
* @see org.tigris.gef.base.Mode#done()
*/
public void done() {
super.done();
if (_newItem != null)
editor.damaged(_newItem);
_newItem = null; // use this as the fig for the new FigEdge
sourceFigNode = null;
startPort = null;
startPortFig = null;
}
////////////////////////////////////////////////////////////////
// mouse event handlers
/**
* On mousePressed determine what port the user is dragging from.
* The mousePressed event is sent via ModeSelect.
*
* @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
*/
public void mousePressed(MouseEvent me) {
}
/**
* On mouseReleased, find the destination port, ask the GraphModel
* to connect the two ports. If that connection is allowed, then
* construct a new FigEdge and add it to the Layer and send it to
* the back.
*
* @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)
*/
public void mouseReleased(MouseEvent me) {
if (me.isConsumed())
return;
if (sourceFigNode == null) {
done();
return;
}
boolean nodeWasCreated = false;
int x = me.getX(), y = me.getY();
Class arcClass;
Editor ce = Globals.curEditor();
Fig f = ce.hit(x, y);
if (f == null) {
f = ce.hit(x - 16, y - 16, 32, 32);
}
GraphModel gm = ce.getGraphModel();
if (!(gm instanceof MutableGraphModel))
f = null;
MutableGraphModel mgm = (MutableGraphModel) gm;
// TODO: potential class cast exception
if (f == null) {
LOG.debug("make new node");
dragsToNew++;
Object newNode = null;
Class nodeClass = (Class) getArg("nodeClass");
try {
newNode = nodeClass.newInstance();
} catch (java.lang.IllegalAccessException ignore) {
LOG.error(ignore);
return;
} catch (java.lang.InstantiationException ignore) {
LOG.error(ignore);
return;
}
if (newNode instanceof GraphNodeHooks)
((GraphNodeHooks) newNode).initialize(_args);
UmlFactory.getFactory().addListenersToModelElement(newNode);
if (mgm.canAddNode(newNode)) {
GraphNodeRenderer renderer = editor.getGraphNodeRenderer();
Layer lay = editor.getLayerManager().getActiveLayer();
fn = renderer.getFigNodeFor(gm, lay, newNode);
editor.add(fn);
mgm.addNode(newNode);
Fig encloser = null;
Rectangle bbox = fn.getBounds();
Collection otherFigs = lay.getContents(null);
Iterator others = otherFigs.iterator();
while (others.hasNext()) {
Fig otherFig = (Fig) others.next();
if (!(otherFig instanceof FigNode))
continue;
if (otherFig.equals(fn))
continue;
Rectangle trap = otherFig.getTrapRect();
if (trap != null && (trap.contains(bbox.x, bbox.y)
&& trap.contains(bbox.x + bbox.width,
bbox.y + bbox.height)))
encloser = otherFig;
}
fn.setEnclosingFig(encloser);
if (newNode instanceof GraphNodeHooks)
((GraphNodeHooks) newNode).postPlacement(editor);
editor.getSelectionManager().select(fn);
nodeWasCreated = true;
f = fn;
f.setLocation(x - f.getWidth() / 2, y - f.getHeight() / 2);
}
} else {
dragsToExisting++;
}
if (f instanceof FigNode) {
FigNode destFigNode = (FigNode) f;
// If its a FigNode, then check within the
// FigNode to see if a port exists
Object foundPort = destFigNode.deepHitPort(x, y);
if (foundPort == null) {
Iterator it = destFigNode.getPortFigs().iterator();
if (it.hasNext()) {
foundPort = ((Fig) it.next()).getOwner();
}
}
FigPoly p = (FigPoly) _newItem;
editor.damaged(p);
p._isComplete = true;
if (foundPort != null && foundPort != startPort) {
Fig destPortFig = destFigNode.getPortFig(foundPort);
Class edgeClass = (Class) getArg("edgeClass");
if (destToSource) {
Object temp = startPort;
startPort = foundPort;
foundPort = temp;
FigNode tempFN = destFigNode;
destFigNode = sourceFigNode;
sourceFigNode = tempFN;
Fig tempFigPort = startPortFig;
startPortFig = destPortFig;
destPortFig = tempFigPort;
}
if (edgeClass != null) {
newEdge = mgm.connect(startPort, foundPort, edgeClass);
} else
newEdge = mgm.connect(startPort, foundPort);
// Calling connect() will add the edge to the GraphModel and
// any LayerPersectives on that GraphModel will get a
// edgeAdded event and will add an appropriate FigEdge
// (determined by the GraphEdgeRenderer).
if (newEdge != null) {
if (postProcessEdge) {
LOG.debug("postprocess edge.");
postProcessEdge();
}
ce.damaged(_newItem);
sourceFigNode.damage();
destFigNode.damage();
LayerManager lm = ce.getLayerManager();
fe = (FigEdge) lm.getActiveLayer().presentationFor(newEdge);
_newItem.setLineColor(Color.black);
fe.setLineColor(Color.black);
fe.setFig(_newItem);
fe.setSourcePortFig(startPortFig);
fe.setSourceFigNode(sourceFigNode);
fe.setDestPortFig(destPortFig);
fe.setDestFigNode(destFigNode);
fe.setSourcePortFig(startPortFig);
fe.setSourceFigNode(sourceFigNode);
fe.setDestPortFig(destPortFig);
fe.setDestFigNode(destFigNode);
if (fe != null && !nodeWasCreated)
ce.getSelectionManager().select(fe);
done();
//me.consume();
_newItem = null;
if (fe instanceof MouseListener)
((MouseListener) fe).mouseReleased(me);
// set the new edge in place
if (sourceFigNode != null)
sourceFigNode.updateEdges();
if (destFigNode != null)
destFigNode.updateEdges();
return;
} else
LOG.warn("connection return null");
} else
LOG.warn("in dest node but no port");
}
sourceFigNode.damage();
ce.damaged(_newItem);
_newItem = null;
done();
}
/**
* @see java.awt.event.MouseMotionListener#mouseMoved(java.awt.event.MouseEvent)
*/
public void mouseMoved(MouseEvent me) {
mouseDragged(me);
}
/**
* @see java.awt.event.MouseMotionListener#mouseDragged(java.awt.event.MouseEvent)
*/
public void mouseDragged(MouseEvent me) {
if (me.isConsumed())
return;
int x = me.getX(), y = me.getY();
//if (_npoints == 0) { me.consume(); return; }
if (_newItem == null) {
me.consume();
return;
}
FigPoly p = (FigPoly) _newItem;
editor.damaged(_newItem); // startTrans?
Point snapPt = new Point(x, y);
editor.snap(snapPt);
handle.index = p.getNumPoints() - 1;
p.moveVertex(handle, snapPt.x, snapPt.y, true);
editor.damaged(_newItem); // endTrans?
me.consume();
}
////////////////////////////////////////////////////////////////
// key events
/**
* @see java.awt.event.KeyListener#keyTyped(java.awt.event.KeyEvent)
*/
public void keyTyped(KeyEvent ke) {
if (ke.getKeyChar() == '') { // escape
done();
ke.consume();
}
}
////////////////////////////////////////////////////////////////
// internal methods
private void postProcessEdge() {
LOG.debug("postprocessing " + newEdge);
if (ModelFacade.isAAssociation(newEdge)) {
Collection conns = ModelFacade.getConnections(newEdge);
Iterator iter = conns.iterator();
Object associationEnd0 = iter.next();
ModelFacade.setAggregation(associationEnd0,
ModelFacade.COMPOSITE_AGGREGATIONKIND);
}
}
static final long serialVersionUID = -427957543380196265L;
} /* end class ModeCreateEdgeAndNode */
|
| ... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.