/*
PseudoCode Interpreted Language (PCIL): Part of the algoviz@vt collection of algorithm visualizations.
Copyright (C) 2008 Brandon Malone, Frank Hadlock
This file is part of the PseudoCode Interpreted Language.
PseudoCode Interpreted Language 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 3 of the License,
or (at your option) any later version.
PseudoCode Interpreted Language 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
PseudoCode Interpreted Language. If not, see
.
*/
/*
* PrimitiveEdge.java
*
* Created on March 6, 2008, 6:50 PM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package dynamicmvc;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.util.ArrayList;
import java.util.HashMap;
import javax.swing.JComponent;
import javax.swing.JPanel;
/**
*
* @author Brandon
*/
public class PrimitiveEdge extends Primitive {
public static String pseudocodeTypeName() {
return "Edge";
}
public String getType() {
return pseudocodeTypeName();
}
//
private String value;
private String name;
private String color;
private PrimitivePointer weight;
private PrimitivePointer first;
private PrimitivePointer second;
private PrimitivePointer g;
//
//
public Primitive copy() {
PrimitiveEdge i = new PrimitiveEdge(getName(), getValue(), getColor(), getFirst(), getSecond(), getWeight());
return i;
}
public Primitive deepCopy(HashMap alreadyCopiedAddresses) throws DynamicMVCException {
PrimitivePointer p = getPointer();
if (alreadyCopiedAddresses.containsKey(Integer.valueOf(p.getAddress()))) {
return PrimitiveFactory.getFromMemory(alreadyCopiedAddresses.get(p.getAddress()));
}
PrimitivePointer pp = PrimitiveFactory.create(pseudocodeTypeName(), name);
alreadyCopiedAddresses.put(p.getAddress(), pp.getAddress());
PrimitiveEdge i = (PrimitiveEdge) pp.dereference();
i.setName(name);
i.setValue(value);
i.setColor(color);
i.setFirst(first.deepCopy(alreadyCopiedAddresses));
i.setSecond(second.deepCopy(alreadyCopiedAddresses));
i.setWeight(weight.deepCopy(alreadyCopiedAddresses));
if (g != null) {
i.setG(g.deepCopy(alreadyCopiedAddresses));
}
deepCopyDefinedProperties(i, alreadyCopiedAddresses);
return i;
}
public boolean deepEquals(Primitive p) throws DynamicMVCException {
if (!(p instanceof PrimitiveEdge)) {
DynamicController.errorMessage = "Expecting Edge, but found " + p.getType();
return false;
}
PrimitiveEdge e = (PrimitiveEdge) p;
if (!first.deepEquals(e.getFirst())) {
return false;
}
if (!second.deepEquals(e.getSecond())) {
return false;
}
if (!weight.deepEquals(e.getWeight())) {
return false;
}
return super.deepEqualsDefinedProperties(p);
}
public PrimitivePointer get(String name) throws DynamicMVCException {
if (name.equalsIgnoreCase("edges")) {
return getEdges();
}
return super.get(name);
}
public void set(Primitive other) throws DynamicMVCException {
// if other is an integer, copy its values
if (other instanceof PrimitiveEdge) {
PrimitiveEdge o = (PrimitiveEdge) other;
//setName(o.getName());
setValue(o.getValue());
setName(o.getName());
setColor(o.getColor());
setFirst(o.getFirst());
setSecond(o.getSecond());
setWeight(o.getWeight());
} else {
// otherwise, throw an DynamicMVCException
throw new DynamicMVCException("Invalid assignment.");
}
}
/** Creates a new instance of PrimitiveEdge */
public PrimitiveEdge(String name, String value, String color, PrimitivePointer first, PrimitivePointer second, PrimitivePointer weight) {
super();
PrimitivePointer f = first.copy();
PrimitivePointer s = second.copy();
PrimitivePointer w = weight.copy();
f.setName("first");
s.setName("second");
w.setName("weight");
setName(name);
setValue(value);
setColor(color);
setFirst(f);
setSecond(s);
setWeight(w);
}
/** Creates a new instance of PrimitiveEdge */
public PrimitiveEdge(PrimitivePointer first, PrimitivePointer second) {
super();
PrimitivePointer f = first.copy();
PrimitivePointer s = second.copy();
f.setName("first");
s.setName("second");
setName("");
setValue("");
setColor("");
setFirst(f);
setSecond(s);
}
public PrimitiveEdge(String value) {
super();
setName("");
setValue(value);
}
public PrimitiveEdge() {
super();
setName("");
setValue("");
setFirst(PrimitiveFactory.create(PrimitiveVertex.pseudocodeTypeName(), "first"));
setSecond(PrimitiveFactory.create(PrimitiveVertex.pseudocodeTypeName(), "second"));
setWeight(PrimitiveFactory.create(PrimitiveInteger.pseudocodeTypeName(), "weight"));
}
//
//
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public PrimitivePointer getFirst() {
return first;
}
public void setFirst(String first) {
this.first = ((PrimitiveGraph) getG().dereference()).getVertex(first).copy();
this.first.setName("first");
// and set this
super.set("first", this.first);
}
public void setFirst(PrimitivePointer first) {
this.first = first.copy();
this.first.setName("first");
super.set("first", this.first);
}
public PrimitivePointer getSecond() {
return second;
}
public void setSecond(String second) {
this.second = ((PrimitiveGraph) getG().dereference()).getVertex(second).copy();
this.second.setName("second");
super.set("second", this.second);
}
public void setSecond(PrimitivePointer second) {
this.second = second.copy();
this.second.setName("second");
super.set("second", this.second);
}
public PrimitivePointer getWeight() {
return weight;
}
public void setWeight(PrimitivePointer weight) {
this.weight = weight.copy();
this.weight.setName("weight");
super.set("weight", this.weight);
}
public PrimitivePointer getEdges() {
PrimitivePointer l = PrimitiveFactory.create(PrimitiveList.pseudocodeTypeName(), "edges");
PrimitiveList newList = (PrimitiveList) l.dereference();
PrimitivePointer firstEdgeList = ((PrimitiveVertex) first.dereference()).getEdges();
PrimitivePointer secondEdgeList = ((PrimitiveVertex) second.dereference()).getEdges();
PrimitiveList fl = ((PrimitiveList) firstEdgeList.dereference());
PrimitiveList sl = ((PrimitiveList) secondEdgeList.dereference());
for (PrimitivePointer e : fl.getList()) {
newList.add(e);
}
for (PrimitivePointer e : sl.getList()) {
newList.add(e);
}
return l;
}
//
//
public void populateFromEditComponentWrapper(JComponent editComponentWrapper) throws DynamicMVCException {
/*
String firstName = first.getEditComponentName();
JComponent firstChild = (JComponent)View.getComponent(editComponentWrapper, firstName);
first.populateFromEditComponentWrapper(firstChild);
String secondName = second.getEditComponentName();
JComponent secondChild = (JComponent)View.getComponent(editComponentWrapper, secondName);
second.populateFromEditComponentWrapper(secondChild);
String weightName = weight.getEditComponentName();
JComponent weightChild = (JComponent)View.getComponent(editComponentWrapper, weightName);
weight.populateFromEditComponentWrapper(weightChild);
*/
// need to populate properties
JComponent propertiesComponent = (JComponent) View.getComponent(editComponentWrapper, this.getPropertiesComponentName());
super.populateDefinedProperties(propertiesComponent);
}
public String getEditComponentWrapperName() {
return "pnl" + getName();
}
public String getEditComponentValue() {
return "txt" + getName() + "value";
}
public String getFirstNodeTextBox() {
return "txt" + getName() + "first";
}
public String getSecondNodeTextBox() {
return "txt" + getName() + "second";
}
public JComponent getEditComponent() {
// wrap everything in a panel
JPanel wrapper = new JPanel();
wrapper.setName(getEditComponentWrapperName());
/*
String fn = first.getName();
String sn = second.getName();
String wn = weight.getName();
first.setName("first");
second.setName("second");
weight.setName("weight");
JComponent firstWrapper = first.getEditComponent();
JComponent secondWrapper = second.getEditComponent();
JComponent weightWrapper = weight.getEditComponent();
first.setName(fn);
second.setName(sn);
weight.setName(wn);
wrapper.add(firstWrapper);
wrapper.add(secondWrapper);
wrapper.add(weightWrapper);
*/
super.addEditDefinedProperties(wrapper);
return wrapper;
}
public JComponent getReadOnlyComponent() {
// wrap everything in a panel
JPanel wrapper = new JPanel();
wrapper.setName(getEditComponentWrapperName());
String fn = "";
if (first != null) {
fn = first.getName();
first.setName("first");
JComponent firstWrapper = first.getReadOnlyComponent();
first.setName(fn);
wrapper.add(firstWrapper);
}
String sn = "";
if (second != null) {
sn = second.getName();
second.setName("second");
JComponent secondWrapper = second.getReadOnlyComponent();
second.setName(sn);
wrapper.add(secondWrapper);
}
String wn = "";
if (weight != null) {
wn = weight.getName();
weight.setName("weight");
JComponent weightWrapper = weight.getReadOnlyComponent();
weight.setName(wn);
wrapper.add(weightWrapper);
}
return wrapper;
}
public void draw(Graphics g) {
int x1 = ((PrimitiveInteger) ((PrimitiveVertex) getFirst().dereference()).getX().dereference()).getValue();
int y1 = ((PrimitiveInteger) ((PrimitiveVertex) getFirst().dereference()).getY().dereference()).getValue();
int x2 = ((PrimitiveInteger) ((PrimitiveVertex) getSecond().dereference()).getX().dereference()).getValue();
int y2 = ((PrimitiveInteger) ((PrimitiveVertex) getSecond().dereference()).getY().dereference()).getValue();
g.setColor(Color.GREEN);
double angle = getAngleBetween(x1, y1, x2, y2);
// if from left to right (x1 < x2), adjust down a little bit
// otherwise, adjust up a bit
// hack code
if (x1 < x2) {
y1 += PrimitiveVertex.getRadius()/2 * Math.cos(angle);
y2 += PrimitiveVertex.getRadius()/2 * Math.cos(angle);
} else {
y1 -= PrimitiveVertex.getRadius()/2 * Math.cos(angle - Math.PI);
y2 -= PrimitiveVertex.getRadius()/2 * Math.cos(angle - Math.PI);
}
if (angle%Math.PI >= 3*Math.PI / 8.0 && angle%Math.PI <= 5*Math.PI/8.0) {
x1 += PrimitiveVertex.getRadius()/2 * Math.sin(angle);
x2 += PrimitiveVertex.getRadius()/2 * Math.sin(angle);
} else {
x1 += PrimitiveVertex.getRadius()/2 * Math.sin(angle - Math.PI);
x2 += PrimitiveVertex.getRadius()/2 * Math.sin(angle - Math.PI);
}
if (this.getG().dereference() instanceof PrimitiveDirectedGraph) {
g.setColor(Color.BLUE);
drawArrow(x1, y1, x2, y2, g);
} else {
g.drawLine(x1, y1, x2, y2);
}
// adjust the position of the text
// hack code
if (x1 < x2) {
y1 += 15;
y2 += 15;
} else {
y1 -= 5;
y2 -= 5;
}
if (angle >= 3*Math.PI / 8.0 && angle <= 5*Math.PI/8.0) {
x1 += 10;
x2 += 10;
} else if (angle >= 11*Math.PI / 8.0 && angle <= 13*Math.PI/8.0) {
x1 -= 15;
x2 -= 15;
}
PrimitiveInteger w = ((PrimitiveInteger) weight.dereference());
g.drawString(String.valueOf(w.getValue()), (x1 + x2) / 2, (y1 + y2) / 2);
}
private double getAngleBetween(int x1, int y1, int x2, int y2) {
Point parentPoint = new Point(x1, y1);
Point childPoint = new Point(x2, y2);
int parentX = (int) parentPoint.getX();
int parentY = (int) parentPoint.getY();
int childX = (int) childPoint.getX();
int childY = (int) childPoint.getY();
Point referencePoint = new Point((int) (Integer.MAX_VALUE), (int) childPoint.getY());
double a = parentPoint.distance(childPoint);
double b = parentPoint.distance(referencePoint);
double c = childPoint.distance(referencePoint);
double beta = Math.acos(((a * a) + (b * b) - (c * c)) / (2 * a * b));
if (parentY > childY) {
beta = (2.0 * Math.PI) - beta;
}
return beta;
}
private void drawArrow(int x1, int y1, int x2, int y2, Graphics g) {
// draw the line
Point parentPoint = new Point(x1, y1);
Point childPoint = new Point(x2, y2);
int parentX = (int) parentPoint.getX();
int parentY = (int) parentPoint.getY();
int childX = (int) childPoint.getX();
int childY = (int) childPoint.getY();
/* + 10000 cause it makes it work */
Point referencePoint = new Point((int) (childPoint.getX() + 10000), (int) childPoint.getY());
double a = parentPoint.distance(childPoint);
double b = parentPoint.distance(referencePoint);
double c = childPoint.distance(referencePoint);
double beta = Math.acos(((a * a) + (b * b) - (c * c)) / (2 * a * b));
if (parentY > childY) {
beta = (2.0 * Math.PI) - beta;
}
int arrowX = (int) (Math.cos(beta) * (PrimitiveVertex.getRadius()));
int arrowY = (int) (Math.sin(beta) * (PrimitiveVertex.getRadius()));
arrowX = childX - arrowX;
arrowY = childY - arrowY;
g.drawLine(parentX, parentY, arrowX, arrowY);
Point arrowPoint = new Point(arrowX, arrowY);
// draw the arrow head
referencePoint = new Point((int) (arrowPoint.getX() + 10000), (int) arrowPoint.getY());
a = parentPoint.distance(arrowPoint);
b = parentPoint.distance(referencePoint);
c = arrowPoint.distance(referencePoint);
beta = Math.acos(((a * a) + (b * b) - (c * c)) / (2 * a * b)) + ((1.0 / 6.0) * Math.PI);
if (parentY > arrowY) {
beta = (2.0 * Math.PI) - beta;
}
int arrowTailX = (int) (Math.cos(beta) * (PrimitiveVertex.getRadius()));
int arrowTailY = (int) (Math.sin(beta) * (PrimitiveVertex.getRadius()));
arrowTailX = (int) arrowPoint.getX() - arrowTailX;
arrowTailY = (int) arrowPoint.getY() - arrowTailY;
g.drawLine(arrowX, arrowY, arrowTailX, arrowTailY);
beta = Math.acos(((a * a) + (b * b) - (c * c)) / (2 * a * b)) - ((1.0 / 6.0) * Math.PI);
if (parentY > arrowY) {
beta = (2.0 * Math.PI) - beta;
}
arrowTailX = (int) (Math.cos(beta) * (PrimitiveVertex.getRadius()));
arrowTailY = (int) (Math.sin(beta) * (PrimitiveVertex.getRadius()));
arrowTailX = (int) arrowPoint.getX() - arrowTailX;
arrowTailY = (int) arrowPoint.getY() - arrowTailY;
g.drawLine(arrowX, arrowY, arrowTailX, arrowTailY);
}
//
public Object execute(String methodName, ArrayList arguments) throws DynamicMVCException {
// is this a method of mine?
if (methodName.equalsIgnoreCase("equals")) {
return equals(arguments);
} else if (methodName.equalsIgnoreCase("notEqual")) {
return !equals(arguments);
} else if (methodName.equalsIgnoreCase("assign")) {
assign(arguments);
return null;
} else if (methodName.equalsIgnoreCase("hasEndPoint")) {
return hasEndPoint(arguments);
} else {
throw new DynamicMVCException("Invalid method name:'" + methodName + "' on object '" + getName() + "'.");
}
}
public PrimitivePointer findOtherVertex(ArrayList arguments) throws DynamicMVCException {
if (arguments.size() == 1) {
PrimitiveVertex v = (PrimitiveVertex) arguments.get(0).dereference();
return findOtherVertex(v);
} else {
throw new DynamicMVCException("Wrong number of arguments.");
}
}
public PrimitivePointer findOtherVertex(PrimitiveVertex v) throws DynamicMVCException {
PrimitivePointer p = v.getPointer();
if (this.first.equals(p)) {
return second;
} else if (this.second.equals(p)) {
return first;
} else {
throw new DynamicMVCException("Edge does not contain vertex.");
}
}
public PrimitivePointer hasEndPoint(ArrayList arguments) throws DynamicMVCException {
if (arguments.size() == 1) {
PrimitivePointer v1 = arguments.get(0);
return hasEndPoint(v1);
} else {
throw new DynamicMVCException("Wrong number of arguments.");
}
}
public PrimitivePointer hasEndPoint(PrimitivePointer v) throws DynamicMVCException {
if(v.dereference() instanceof PrimitiveVertex) {
return hasEndPoint((PrimitiveVertex)v.dereference());
}
throw new DynamicMVCException("Wrong type of argument. Expecting Vertex but found " + v.dereference().getType());
}
public PrimitivePointer hasEndPoint(PrimitiveVertex v) throws DynamicMVCException {
PrimitivePointer b = PrimitiveFactory.create(PrimitiveBoolean.pseudocodeTypeName(), "hasEndPoint");
PrimitiveBoolean bool = (PrimitiveBoolean)b.dereference();
bool.setValue(first.deepEquals(v) || second.deepEquals(v));
return b;
}
public PrimitivePointer hasEndPoints(ArrayList arguments) throws DynamicMVCException {
if (arguments.size() == 2) {
PrimitiveVertex v1 = (PrimitiveVertex) arguments.get(0).dereference();
PrimitiveVertex v2 = (PrimitiveVertex) arguments.get(1).dereference();
return hasEndPoints(v1, v2);
} else {
throw new DynamicMVCException("Wrong number of arguments.");
}
}
public PrimitivePointer hasEndPoints(PrimitiveVertex v1, PrimitiveVertex v2) {
if (first.equals(v1) && second.equals(v2)) {
PrimitivePointer b = PrimitiveFactory.create(PrimitiveBoolean.pseudocodeTypeName(), "");
((PrimitiveBoolean) b.dereference()).setValue(true);
return b;
}
if (getG().dereference() instanceof PrimitiveGraph) {
if (first.equals(v2) && second.equals(v1)) {
PrimitivePointer b = PrimitiveFactory.create(PrimitiveBoolean.pseudocodeTypeName(), "");
((PrimitiveBoolean) b.dereference()).setValue(true);
return b;
}
}
PrimitivePointer b = PrimitiveFactory.create(PrimitiveBoolean.pseudocodeTypeName(), "");
((PrimitiveBoolean) b.dereference()).setValue(false);
return b;
}
public PrimitivePointer hasEndPoints(PrimitivePointer v1, PrimitivePointer v2) {
PrimitiveVertex pv1 = (PrimitiveVertex) v1.dereference();
PrimitiveVertex pv2 = (PrimitiveVertex) v2.dereference();
PrimitiveVertex vFirst = (PrimitiveVertex) first.dereference();
PrimitiveVertex vSecond = (PrimitiveVertex) second.dereference();
try {
if (vFirst.equals(pv1) && vSecond.equals(pv2)) {
PrimitivePointer b = PrimitiveFactory.create(PrimitiveBoolean.pseudocodeTypeName(), "");
((PrimitiveBoolean) b.dereference()).setValue(true);
return b;
}
} catch (DynamicMVCException ex) {
ex.printStackTrace();
}
if (getG().dereference() instanceof PrimitiveGraph) {
try {
if (vFirst.equals(pv2) && vSecond.equals(pv1)) {
PrimitivePointer b = PrimitiveFactory.create(PrimitiveBoolean.pseudocodeTypeName(), "");
((PrimitiveBoolean) b.dereference()).setValue(true);
return b;
}
} catch (DynamicMVCException ex) {
ex.printStackTrace();
}
}
PrimitivePointer b = PrimitiveFactory.create(PrimitiveBoolean.pseudocodeTypeName(), "");
((PrimitiveBoolean) b.dereference()).setValue(false);
return b;
}
public int compareTo(Object o) throws DynamicMVCException {
if (o instanceof PrimitivePointer) {
PrimitiveEdge i = (PrimitiveEdge) ((PrimitivePointer) o).dereference();
return compareTo(i);
}
throw new DynamicMVCException("Invalid comparison");
}
public boolean equals(ArrayList arguments) throws DynamicMVCException {
if (arguments.size() == 1) {
PrimitiveEdge i = (PrimitiveEdge) arguments.get(0).dereference();
return equals(i);
}
throw new DynamicMVCException("Wrong number of arguments.");
}
public boolean equals(PrimitiveEdge i) {
return (compareTo(i) == 0);
}
public int compareTo(ArrayList arguments) throws DynamicMVCException {
if (arguments.size() == 1) {
PrimitiveEdge i = (PrimitiveEdge) arguments.get(0).dereference();
return compareTo(i);
}
throw new DynamicMVCException("Wrong number of arguments.");
}
public int compareTo(PrimitiveEdge i) {
String otherName = i.getName();
return getName().compareTo(otherName);
}
public void assign(ArrayList arguments) throws DynamicMVCException {
if (arguments.size() == 1) {
PrimitiveEdge i = (PrimitiveEdge) arguments.get(0).dereference();
assign(i);
}
throw new DynamicMVCException("Wrong number of arguments.");
}
public void assign(PrimitiveEdge i) throws DynamicMVCException {
throw new DynamicMVCException("Deprecated method");
/*String otherName = i.getName();
String otherValue = i.getValue();
String otherColor = i.getColor();
PrimitiveVertex otherFirst = i.getFirst();
PrimitiveVertex otherSecond = i.getSecond();
setName(otherName);
setValue(otherValue);
setColor(otherColor);
setFirst(otherFirst);
setSecond(otherSecond);
**/
}
public String toString() {
return getName() + ": " + getValue() + ": " + getColor() + ": " + ((PrimitiveVertex) first.dereference()).getName() + ": " + ((PrimitiveVertex) second.dereference()).getName();
}
public int compareTo(Primitive p) throws DynamicMVCException {
if (p instanceof PrimitiveEdge) {
return name.compareTo(p.getName());
} else {
throw new DynamicMVCException("Invalid comparison.");
}
}
public PrimitiveString toPrimitiveString() {
PrimitiveString s = (PrimitiveString) (PrimitiveFactory.create(PrimitiveString.pseudocodeTypeName(), "s").dereference());
s.setValue(toString());
return s;
}
public PrimitivePointer getG() {
return g;
}
public void setG(PrimitivePointer g) {
this.g = g;
}
}