ArrowView.java
package algorithmen.umleditor;
import java.awt.*;
/**
* View eines UmlArrow.
* Zuständig für die graphische Darstellung eines Pfeils.
*/
public class ArrowView extends View implements Observer {
protected View start;
protected View end;
protected int tipWidth; // Breite der Ofeilspitze
protected int tipLength; // L?nge der Pfeilspitze
protected int topOffset; // Abstand des (horiz.) Pfeils von der oberen Linie
protected Polygon pol;
// enth?lt Anfangspunkt, rechte Pfeilspitze, Endpunkte, linke Pfeilspitze
protected Polygon pol3; // Pfeilspitze, Teil von pol
protected static BasicStroke normal; // Zeichenstil für normale
protected static BasicStroke dashed; // und für gestrichelte Linien
/**
* Erzeugt eine Pfeilansicht zwischen den Objekten, die durch die Views
* start und end repräsentiert werden.
*/
public ArrowView(Arrow model, View start, View end) {
super(model, new Point()); // Anfangspunkt muss erst berechnet werden
this.start = start;
this.end = end;
tipWidth = 10;
tipLength = 10;
topOffset = 15;
computeCoordinates();
setupStrokes();
// achte auf Änderungen der UmlObjekte
start.addObserver(this);
end.addObserver(this);
}
public Editor createEditor(UmlElement m, Frame p) {
return new ArrowEditor((Arrow) m, p);
}
public Editor createEditor(UmlElement m, Dialog p) {
return new ArrowEditor((Arrow) m, p);
}
/**
* Problem: Arrow bezieht sich immer auf zwei UmlElement's,
* es gibt daher kein Standard-Objekt.
* Um dem Interface Gen?ge zu tun, werden einfach zwei Standard-Objekte
* miterzeugt.
*/
public UmlElement createStandardObject() {
return new Arrow(new Class(), new Class());
}
/**
* Pr?ft, ob der Punkt p im umschlie?enden Polygon des Objekts liegt.
*/
public boolean contains(Point p) {
return pol.contains(p);
}
public void draw(Graphics g) {
Arrow a = (Arrow) model;
ArrowType type = a.getType();
Graphics2D g2 = (Graphics2D) g;
computeCoordinates();
// lazy initialisation
// nötig, da Strokes nicht Serializable sind.
if (normal == null) {
setupStrokes();
}
// erst die Linie
if (type.equals(ArrowType.IMPLEMENTATION) || type.equals(ArrowType.RELATION)) {
g2.setStroke(dashed);
g2.drawLine(pol.xpoints[0], pol.ypoints[0], pol.xpoints[2], pol.ypoints[2]);
g2.setStroke(normal);
} else {
g2.drawLine(pol.xpoints[0], pol.ypoints[0], pol.xpoints[2], pol.ypoints[2]);
}
// dann die Spitze
if (type.equals(ArrowType.REFERENCE) || type.equals(ArrowType.RELATION)) {
g2.drawLine(pol.xpoints[2], pol.ypoints[2], pol.xpoints[1], pol.ypoints[1]);
g2.drawLine(pol.xpoints[2], pol.ypoints[2], pol.xpoints[3], pol.ypoints[3]);
} else if (!type.equals(ArrowType.ASSOCIATION) ) {
g2.setPaint(Color.WHITE);
g2.fill(pol3);
g2.setPaint(Color.BLACK);
g2.draw(pol3);
} // ASSOCIATION hat keinen Pfeil
}
/**
* Berechnet Punkte des Pfeils.
*/
protected void computeCoordinates() {
Arrow a = (Arrow) model;
// 4 Punkte für den Pfeil, definieren auch das Polygon für Maus-Treffer
int[] x = new int[4];
int[] y = new int[4];
pol = new Polygon(x, y, 4);
// Dreieck für die Pfeilspitze bzw. Raute
if (a.getType().equals(ArrowType.AGGREGATION)) {
pol3 = new Polygon(x, y, 4);
} else {
pol3 = new Polygon(x, y, 3);
}
// berechne Start- und Endpunkt
if (a.getType().isVertical()) {
// Pfeile beginnen und enden auf der Mitte der oberen bzw. unteren
// Begrenzung des Objekts
pol.xpoints[0] = start.getPosition().x + start.getSize().width/2;
pol.ypoints[0] = start.getPosition().y;
pol.xpoints[2] = end.getPosition().x + end.getSize().width/2;
pol.ypoints[2] = end.getPosition().y + end.getSize().height;
} else {
// Pfeile starten rechts oben und enden links oben
pol.xpoints[0] = start.getPosition().x + start.getSize().width;
pol.ypoints[0] = start.getPosition().y + topOffset;
pol.xpoints[2] = end.getPosition().x;
pol.ypoints[2] = end.getPosition().y + topOffset;
}
// berechne Enden der Pfeilspitze
// e1 = Einheitsvektor in Pfeilrechtung
// e2 = Einheitsvektor orthogonal dazu
double e1x = pol.xpoints[2] - pol.xpoints[0];
double e1y = pol.ypoints[2] - pol.ypoints[0];
double eabs = Math.sqrt(e1x*e1x + e1y*e1y);
e1x /= eabs;
e1y /= eabs;
double e2x = e1y;
double e2y = -e1x;
if (! (a.getType().equals(ArrowType.AGGREGATION) )){
pol.xpoints[1] = (int)(pol.xpoints[2] + tipWidth*e2x - tipLength*e1x);
pol.ypoints[1] = (int)(pol.ypoints[2] + tipWidth*e2y - tipLength*e1y);
pol.xpoints[3] = (int)(pol.xpoints[2] - tipWidth*e2x - tipLength*e1x);
pol.ypoints[3] = (int)(pol.ypoints[2] - tipWidth*e2y - tipLength*e1y);
pol.invalidate(); // interne Caches von Polygon aktualisieren
pol3.xpoints[0] = pol.xpoints[1];
pol3.ypoints[0] = pol.ypoints[1];
pol3.xpoints[1] = pol.xpoints[2];
pol3.ypoints[1] = pol.ypoints[2];
pol3.xpoints[2] = pol.xpoints[3];
pol3.ypoints[2] = pol.ypoints[3];
pol3.invalidate();
} else {
// Aggregation wird mit Raute am Anfang dargestellt
pol.xpoints[1] = (int)(pol.xpoints[0] + tipWidth*e2x + tipLength*e1x);
pol.ypoints[1] = (int)(pol.ypoints[0] + tipWidth*e2y + tipLength*e1y);
pol.xpoints[3] = (int)(pol.xpoints[0] - tipWidth*e2x + tipLength*e1x);
pol.ypoints[3] = (int)(pol.ypoints[0] - tipWidth*e2y + tipLength*e1y);
pol.invalidate(); // interne Caches von Polygon aktualisieren
pol3.xpoints[0] = pol.xpoints[0];
pol3.ypoints[0] = pol.ypoints[0];
pol3.xpoints[1] = pol.xpoints[1];
pol3.ypoints[1] = pol.ypoints[1];
pol3.xpoints[2] = (int)(pol.xpoints[0] + 2*tipLength*e1x);
pol3.ypoints[2] = (int)(pol.ypoints[0] + 2*tipLength*e1y);
pol3.xpoints[3] = pol.xpoints[3];
pol3.ypoints[3] = pol.ypoints[3];
pol3.invalidate();
}
}
public void update() {
computeCoordinates();
}
protected void setupStrokes() {
float dash1[] = {10.0f};
normal = new BasicStroke();
dashed = new BasicStroke(1.0f, BasicStroke.CAP_BUTT,
BasicStroke.JOIN_MITER, 10.0f, dash1, 0.0f);
}
}