/*******************************************************************************
* Copyright (c) 2004, 2005 Elias Volanakis and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*����Elias Volanakis - initial API and implementation
*******************************************************************************/
package com.windowtester.internal.customer.cat.shapes.parts;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import org.eclipse.draw2d.ChopboxAnchor;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.draw2d.EllipseAnchor;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.ConnectionEditPart;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.NodeEditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
import org.eclipse.gef.editpolicies.GraphicalNodeEditPolicy;
import org.eclipse.gef.requests.CreateConnectionRequest;
import org.eclipse.gef.requests.ReconnectRequest;
import com.windowtester.internal.customer.cat.shapes.model.Connection;
import com.windowtester.internal.customer.cat.shapes.model.EllipticalShape;
import com.windowtester.internal.customer.cat.shapes.model.ModelElement;
import com.windowtester.internal.customer.cat.shapes.model.RectangularShape;
import com.windowtester.internal.customer.cat.shapes.model.Shape;
import com.windowtester.internal.customer.cat.shapes.model.commands.ConnectionCreateCommand;
import com.windowtester.internal.customer.cat.shapes.model.commands.ConnectionReconnectCommand;
/**
* EditPart used for Shape instances (more specific for EllipticalShape and
* RectangularShape instances).
* <p>
* This edit part must implement the PropertyChangeListener interface, so it can
* be notified of property changes in the corresponding model element.
* </p>
*
* @author Elias Volanakis
*/
public class ShapeEditPart extends AbstractGraphicalEditPart implements
PropertyChangeListener, NodeEditPart {
private ConnectionAnchor anchor;
private static int counter = 1;
/**
* Upon activation, attach to the model element as a property change
* listener.
*/
public void activate() {
if (!isActive()) {
super.activate();
((ModelElement) getModel()).addPropertyChangeListener(this);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.gef.editparts.AbstractEditPart#createEditPolicies()
*/
protected void createEditPolicies() {
// allow removal of the associated model element
installEditPolicy(EditPolicy.COMPONENT_ROLE,
new ShapeComponentEditPolicy());
// allow the creation of connections and
// and the reconnection of connections between Shape instances
installEditPolicy(EditPolicy.GRAPHICAL_NODE_ROLE,
new GraphicalNodeEditPolicy() {
/*
* (non-Javadoc)
*
* @see org.eclipse.gef.editpolicies.GraphicalNodeEditPolicy#getConnectionCompleteCommand(org.eclipse.gef.requests.CreateConnectionRequest)
*/
protected Command getConnectionCompleteCommand(
CreateConnectionRequest request) {
ConnectionCreateCommand cmd = (ConnectionCreateCommand) request
.getStartCommand();
cmd.setTarget((Shape) getHost().getModel());
return cmd;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.gef.editpolicies.GraphicalNodeEditPolicy#getConnectionCreateCommand(org.eclipse.gef.requests.CreateConnectionRequest)
*/
protected Command getConnectionCreateCommand(
CreateConnectionRequest request) {
Shape source = (Shape) getHost().getModel();
int style = ((Integer) request.getNewObjectType())
.intValue();
ConnectionCreateCommand cmd = new ConnectionCreateCommand(
source, style);
request.setStartCommand(cmd);
return cmd;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.gef.editpolicies.GraphicalNodeEditPolicy#getReconnectSourceCommand(org.eclipse.gef.requests.ReconnectRequest)
*/
protected Command getReconnectSourceCommand(
ReconnectRequest request) {
Connection conn = (Connection) request
.getConnectionEditPart().getModel();
Shape newSource = (Shape) getHost().getModel();
ConnectionReconnectCommand cmd = new ConnectionReconnectCommand(
conn);
cmd.setNewSource(newSource);
return cmd;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.gef.editpolicies.GraphicalNodeEditPolicy#getReconnectTargetCommand(org.eclipse.gef.requests.ReconnectRequest)
*/
protected Command getReconnectTargetCommand(
ReconnectRequest request) {
Connection conn = (Connection) request
.getConnectionEditPart().getModel();
Shape newTarget = (Shape) getHost().getModel();
ConnectionReconnectCommand cmd = new ConnectionReconnectCommand(
conn);
cmd.setNewTarget(newTarget);
return cmd;
}
});
}
/*
* (non-Javadoc)
*
* @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#createFigure()
*/
protected IFigure createFigure() {
IFigure f = createFigureForModel();
f.setOpaque(true); // non-transparent figure
f.setBackgroundColor(ColorConstants.white);
f.setForegroundColor(ColorConstants.black);
return f;
}
/**
* Return a IFigure depending on the instance of the current model element.
* This allows this EditPart to be used for both sublasses of Shape.
*/
private IFigure createFigureForModel() {
if (getModel() instanceof EllipticalShape) {
MyEllipse ellipse = new MyEllipse("Ellipse " + counter);
counter++;
return ellipse;
} else if (getModel() instanceof RectangularShape) {
MyRectangle rectangle = new MyRectangle("Rectangle " + counter);
counter++;
return rectangle;
} else {
// if Shapes gets extended the conditions above must be updated
throw new IllegalArgumentException();
}
}
/**
* Upon deactivation, detach from the model element as a property change
* listener.
*/
public void deactivate() {
if (isActive()) {
super.deactivate();
((ModelElement) getModel()).removePropertyChangeListener(this);
}
}
private Shape getCastedModel() {
return (Shape) getModel();
}
protected ConnectionAnchor getConnectionAnchor() {
if (anchor == null) {
if (getModel() instanceof EllipticalShape)
anchor = new EllipseAnchor(getFigure());
else if (getModel() instanceof RectangularShape)
anchor = new ChopboxAnchor(getFigure());
else
// if Shapes gets extended the conditions above must be updated
throw new IllegalArgumentException("unexpected model");
}
return anchor;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#getModelSourceConnections()
*/
protected List getModelSourceConnections() {
return getCastedModel().getSourceConnections();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#getModelTargetConnections()
*/
protected List getModelTargetConnections() {
return getCastedModel().getTargetConnections();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.gef.NodeEditPart#getSourceConnectionAnchor(org.eclipse.gef.ConnectionEditPart)
*/
public ConnectionAnchor getSourceConnectionAnchor(
ConnectionEditPart connection) {
return getConnectionAnchor();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.gef.NodeEditPart#getSourceConnectionAnchor(org.eclipse.gef.Request)
*/
public ConnectionAnchor getSourceConnectionAnchor(Request request) {
return getConnectionAnchor();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.gef.NodeEditPart#getTargetConnectionAnchor(org.eclipse.gef.ConnectionEditPart)
*/
public ConnectionAnchor getTargetConnectionAnchor(
ConnectionEditPart connection) {
return getConnectionAnchor();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.gef.NodeEditPart#getTargetConnectionAnchor(org.eclipse.gef.Request)
*/
public ConnectionAnchor getTargetConnectionAnchor(Request request) {
return getConnectionAnchor();
}
/*
* (non-Javadoc)
*
* @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
*/
public void propertyChange(PropertyChangeEvent evt) {
String prop = evt.getPropertyName();
if (Shape.SIZE_PROP.equals(prop) || Shape.LOCATION_PROP.equals(prop)) {
refreshVisuals();
} else if (Shape.SOURCE_CONNECTIONS_PROP.equals(prop)) {
refreshSourceConnections();
} else if (Shape.TARGET_CONNECTIONS_PROP.equals(prop)) {
refreshTargetConnections();
}
}
protected void refreshVisuals() {
// notify parent container of changed position & location
// if this line is removed, the XYLayoutManager used by the parent
// container
// (the Figure of the ShapesDiagramEditPart), will not know the bounds
// of this figure
// and will not draw it correctly.
Rectangle bounds = new Rectangle(getCastedModel().getLocation(),
getCastedModel().getSize());
((GraphicalEditPart) getParent()).setLayoutConstraint(this,
getFigure(), bounds);
}
}