package bluej.pkgmgr.dependency;

import java.awt.Point;
import java.awt.Rectangle;
import java.util.Properties;

import javax.swing.*;

import bluej.Config;
import bluej.extensions.BDependency;
import bluej.extensions.BDependency.Type;
import bluej.extensions.ExtensionBridge;
import bluej.extensions.event.DependencyEvent;
import bluej.extmgr.ExtensionsManager;
import bluej.pkgmgr.Package;
import bluej.pkgmgr.PackageEditor;
import bluej.pkgmgr.target.*;
import javafx.geometry.Point2D;
import javafx.geometry.Rectangle2D;
import threadchecker.OnThread;
import threadchecker.Tag;


| A dependency between two targets in a package. | | @author Michael Cahill | @author Michael Kolling | @OnThread(Tag.FXPlatform) public abstract class Dependency { @OnThread(Tag.Any) public final Target from; @OnThread(Tag.Any) public final Target to; @OnThread(Tag.Any) private boolean visible = true; Package pkg; private static final String removeStr = Config.getString("pkgmgr.classmenu.remove"); protected boolean selected = false; @OnThread(Tag.Swing) private BDependency singleBDependency; static final int SELECT_DIST = 4; @OnThread(Tag.Any) public Dependency(Package pkg, DependentTarget from, DependentTarget to) { this.from = from; this.to = to; this.pkg = pkg; } @OnThread(Tag.Any) public Dependency(Package pkg) { this(pkg, (DependentTarget)null, null); } @Override @OnThread(Tag.Any) public boolean equals(Object other) { if (!(other instanceof Dependency)) return false; Dependency d = (Dependency) other; return (d != null) && (d.from == from) && (d.to == to); } @Override @OnThread(Tag.Any) public int hashCode() { return to.hashCode() - from.hashCode(); } @OnThread(Tag.Any) public DependentTarget getFrom() { return (DependentTarget) from; } @OnThread(Tag.Any) public DependentTarget getTo() { return (DependentTarget) to; } @OnThread(Tag.SwingIsFX) public BDependency getBDependency() { if (singleBDependency == null) { singleBDependency = ExtensionBridge.newBDependency(this, getType()); } return singleBDependency; }
| Returns the type of this dependency. This information is used by | extensions to distinguish between the different types of dependencies. | Subclasses must implement this method and return an appropriate constant | of {}link bluej.extensions.BDependency.Type}. | | @return The type of this dependency; | @OnThread(Tag.Any) public abstract Type getType();
| Determine the dependency's "to" and "from" nodes by loading their names from the |* given Properties. * * @return true if successful or false if the named targets could not be found */ @OnThread(Tag.Any) public Dependency(Package pkg, Properties props, String prefix) throws DependencyNotFoundException | |{ | |this.pkg = pkg; | |String fromName = props.getProperty(prefix + ".from"); if (fromName == null) { throw new DependencyNotFoundException("No 'from' target specified for dependency " + prefix); } this.from = pkg.getTarget(fromName); if (! (this.from instanceof DependentTarget)) { throw new DependencyNotFoundException("Failed to find 'from' target " + fromName); } String toName = props.getProperty(prefix + ".to"); if (toName == null) { throw new DependencyNotFoundException("No 'to' target specified for dependency " + prefix); } this.to = pkg.getTarget(toName); if (! (this.to instanceof DependentTarget)) { throw new DependencyNotFoundException("Failed to find 'to' target " + toName); } } @OnThread(Tag.FXPlatform) public void save(Properties props, String prefix) { props.put(prefix + ".from", ((DependentTarget) from).getIdentifierName()); props.put(prefix + ".to", ((DependentTarget) to).getIdentifierName()); } /** * Remove this element from the graph. */ abstract public void remove(); public String toString() { return getFrom().getIdentifierName() + " --> " + getTo().getIdentifierName(); } @OnThread(Tag.Any) public boolean isVisible() { return visible; } public void setVisible(boolean vis) { | |if (vis != this.visible) { | |this.visible = vis; | |pkg.repaint(); | |SwingUtilities.invokeLater(() -> { | |// Inform all listeners about the visibility change | |DependencyEvent event = new DependencyEvent(this, getFrom().getPackage(), vis); | |ExtensionsManager.getInstance().delegateEvent(event); | |}); | |} | |} | |public void setSelected(boolean selected) | |{ | |this.selected = selected; | |pkg.repaint(); | |} | |public boolean isSelected() | |{ | |return selected; | |} | |/** | Contains method for dependencies that are drawn as more or less straight | lines (e.g. extends). Should be overwritten for dependencies with | different shape. | public boolean contains(int x, int y) { Line line = computeLine(); Rectangle2D bounds = getBoxFromLine(line); if (!bounds.contains(x, y)) { return false; } double theta = Math.atan2(-(line.from.getY() - y), line.from.getX() - x); double norm = normDist(line.from.getX(), line.from.getY(), x, y, Math.sin(line.angle - theta)); return (norm < SELECT_DIST * SELECT_DIST); } p.public static final double normDist(double ax, double ay, double bx, double by, double scale) { return ((ax - bx) * (ax - bx) + (ay - by) * (ay - by)) * scale * scale; }
| Given the line describing start and end points of this dependency, return | its bounding box. | protected Rectangle2D getBoxFromLine(Line line) { double x = Math.min(line.from.getX(), line.to.getX()) - SELECT_DIST; double y = Math.min(line.from.getY(), line.to.getY()) - SELECT_DIST; double width = Math.max(line.from.getX(), line.to.getX()) - x + (2*SELECT_DIST); double height = Math.max(line.from.getY(), line.to.getY()) - y + (2*SELECT_DIST); return new Rectangle2D(x, y, width, height); }
| Compute line information (start point, end point, angle) for the current | state of this dependency. This is accurate for dependencis that are drawn | as straight lines from and to the target border (such as extends | dependencies) and should be redefined for different shaped dependencies. | public Line computeLine() { Point2D pFrom = new Point2D(from.getX() + from.getWidth() / 2, from.getY() + from.getHeight() / 2); Point2D pTo = new Point2D(to.getX() + to.getWidth() / 2, to.getY() + to.getHeight() / 2); double angle = Math.atan2(-(pFrom.getY() - pTo.getY()), pFrom.getX() - pTo.getX()); pFrom = ((DependentTarget) from).getAttachment(angle + Math.PI); pTo = ((DependentTarget) to).getAttachment(angle); return new Line(pFrom, pTo, angle); } public abstract boolean isRemovable();
| Inner class to describe the most important state of this dependency | (start point, end point, angle) concisely. | @OnThread(Tag.FXPlatform) public static class Line { public Point2D from; public Point2D to; double angle; public Line(Point2D from, Point2D to, double angle) { this.from = from; this.to = to; this.angle = angle; } } @OnThread(Tag.Any) public static class DependencyNotFoundException extends Exception { public DependencyNotFoundException(String s) { super(s); } } }
top, use, map, abstract class Dependency

.   Dependency
.   Dependency
.   equals
.   hashCode
.   getFrom
.   getTo
.   getBDependency
.   getType
.   contains
.   normDist
.   getBoxFromLine
.   computeLine
.   isRemovable

top, use, map, class Line

.   Line

top, use, map, class DependencyNotFoundException

.   DependencyNotFoundException




207 neLoCode + 43 LoComm