package husacct.graphics.domain.figures; import husacct.common.Resource; import java.awt.Color; import java.awt.geom.Point2D; import java.awt.geom.Point2D.Double; import java.awt.image.BufferedImage; import java.net.URL; import java.util.ArrayList; import javax.imageio.ImageIO; import org.apache.log4j.Logger; import org.jhotdraw.draw.AttributeKeys; import org.jhotdraw.draw.Figure; import org.jhotdraw.draw.ImageFigure; import org.jhotdraw.draw.RectangleFigure; import org.jhotdraw.draw.TextFigure; import org.jhotdraw.draw.event.FigureEvent; import org.jhotdraw.draw.event.FigureListener; public class ParentFigure extends BaseFigure { private static final long serialVersionUID = 101138923385231941L; private static final Color defaultContainerColor = new Color(204, 204, 255); private RectangleFigure body; private TextFigure moduleName; private TextFigure moduleStereotype; private BufferedImage moduleIcon; private ImageFigure moduleIconFigure; protected int minWidth = 200; protected int minHeight = 150; private ArrayList<Figure> childrenOwnImpl; private double currentPositionX, currentPositionY; public ParentFigure(String uniqueName, String type) { super(uniqueName, uniqueName, type); childrenOwnImpl = new ArrayList<Figure>(); body = new RectangleFigure(); body.set(AttributeKeys.FILL_COLOR, defaultContainerColor); children.add(body); moduleName = new TextFigure(uniqueName); moduleName.set(AttributeKeys.FONT_BOLD, true); children.add(moduleName); moduleStereotype = new TextFigure('\u00AB' + type + '\u00BB'); if (type.equals("facade")) { moduleStereotype = new TextFigure('\u00AB' + "Interface" + '\u00BB'); } children.add(moduleStereotype); moduleIconFigure = new ImageFigure(); moduleIconFigure.set(AttributeKeys.STROKE_WIDTH, 0.0); moduleIconFigure.set(AttributeKeys.FILL_COLOR, defaultContainerColor); try { URL componentImageURL = null; // Set Icons: First icons Intended Architecture diagram, second implemented, third default. if (type.toLowerCase().equals("layer")) { componentImageURL = Resource.get(Resource.ICON_LAYER); } else if (type.toLowerCase().equals("component")) { componentImageURL = Resource.get(Resource.ICON_COMPONENT); } else if (type.toLowerCase().equals("facade")) { componentImageURL = Resource.get(Resource.ICON_FACADE); } else if (type.toLowerCase().equals("subsystem")) { componentImageURL = Resource.get(Resource.ICON_SUBSYSTEM); } else if (type.toLowerCase().equals("library")) { componentImageURL = Resource.get(Resource.ICON_EXTERNALLIB_GREEN); } else if (type.toLowerCase().equals("externallibrary")) { componentImageURL = Resource.get(Resource.ICON_EXTERNALLIB_BLUE); } else if (type.toLowerCase().equals("package")) { componentImageURL = Resource.get(Resource.ICON_PACKAGE); } else if (type.toLowerCase().equals("class")) { componentImageURL = Resource.get(Resource.ICON_CLASS_PUBLIC); } else if (type.toLowerCase().equals("interface")) { componentImageURL = Resource.get(Resource.ICON_INTERFACE_PUBLIC); } else{ componentImageURL = Resource.get(Resource.ICON_MODULE); } if(componentImageURL != null){ moduleIcon = ImageIO.read(componentImageURL); moduleIconFigure.setImage(null, moduleIcon); children.add(moduleIconFigure); } } catch (Exception e) { moduleIconFigure = null; Logger.getLogger(this.getClass()).warn("failed to load component icon image file"); } baseZIndex = -2; resetLayer(); setSizeable(true); addFigureListener(new FigureListener() { @Override public void areaInvalidated(FigureEvent e) { } @Override public void attributeChanged(FigureEvent e) { } @Override public void figureAdded(FigureEvent e) { } @Override public void figureChanged(FigureEvent e) { double oldX = currentPositionX; double oldY = currentPositionY; double newX = ((BaseFigure) e.getFigure()).getBounds().getX(); double newY = ((BaseFigure) e.getFigure()).getBounds().getY(); double difX = newX - oldX; double difY = newY - oldY; for (Figure fig : childrenOwnImpl) ((BaseFigure) fig).updateLocation(fig.getBounds().getX() + difX, fig.getBounds().getY() + difY); currentPositionX = newX; currentPositionY = newY; } @Override public void figureHandlesChanged(FigureEvent e) { } @Override public void figureRemoved(FigureEvent e) { } @Override public void figureRequestRemove(FigureEvent e) { } }); } @Override public boolean add(Figure figure) { BaseFigure bf = (BaseFigure) figure; bf.setInContainer(true); childrenOwnImpl.add(figure); figure.addFigureListener(new FigureListener() { @Override public void areaInvalidated(FigureEvent e) { } @Override public void attributeChanged(FigureEvent e) { } @Override public void figureAdded(FigureEvent e) { } @Override public void figureChanged(FigureEvent e) { double parentFigureStartX = getBounds().getX(); double parentFigureWidth = getBounds().getWidth(); double parentFigureEndX = parentFigureStartX + parentFigureWidth; double parentFigureStartY = getBounds().getY(); double parentFigureHeight = getBounds().getHeight(); double parentFigureEndY = parentFigureStartY + parentFigureHeight; BaseFigure childFigure = (BaseFigure) e.getFigure(); java.awt.geom.Rectangle2D.Double figureBounds = childFigure .getBounds(); double childFigureX = figureBounds.getX(); double childFigureWidth = figureBounds.getWidth(); double childFigureY = figureBounds.getY(); double childFigureHeight = figureBounds.getHeight(); boolean outsideLeft = childFigureX < parentFigureStartX; boolean outsideRight = childFigureX + childFigureWidth > parentFigureEndX; if (outsideLeft || outsideRight) { childFigure.willChange(); if (outsideLeft) childFigure.updateLocation( parentFigureStartX, childFigureY); else childFigure.updateLocation(parentFigureEndX - childFigureWidth, childFigureY); childFigure.changed(); } boolean outsideTop = childFigureY < parentFigureStartY; boolean outsideBottom = childFigureY + childFigureHeight > parentFigureEndY; if (outsideTop || outsideBottom) { childFigure.willChange(); if (outsideTop) childFigure.updateLocation(childFigureX, parentFigureStartY); else childFigure.updateLocation(childFigureX, parentFigureEndY - childFigureHeight); childFigure.changed(); } } @Override public void figureHandlesChanged(FigureEvent e) { } @Override public void figureRemoved(FigureEvent e) { } @Override public void figureRequestRemove(FigureEvent e) { } }); return true; } @Override public ParentFigure clone() { ParentFigure other = (ParentFigure) super.clone(); other.body = body.clone(); other.moduleName = moduleName.clone(); other.moduleStereotype = moduleStereotype.clone(); other.moduleIconFigure = moduleIconFigure.clone(); other.children = new ArrayList<Figure>(); other.children.add(other.body); other.children.add(other.moduleName); other.children.add(other.moduleStereotype); if (moduleIconFigure != null) other.children.add(other.moduleIconFigure); return other; } public BaseFigure[] getChildFigures() { return childrenOwnImpl.toArray(new BaseFigure[] {}); } @Override public boolean isParent() { return true; } @Override public void raiseLayer() { // zIndex = raiseZIndex-1; for (BaseFigure childFigure : getChildFigures()) childFigure.raiseLayer(); } @Override public void resetLayer() { super.resetLayer(); for (BaseFigure childFigure : getChildFigures()) childFigure.resetLayer(); } @Override public void setBounds(Point2D.Double anchor, Point2D.Double lead) { // Initialize element sizes double nameWidth = moduleName.getBounds().width; double textGap = 5; double marginY = 4; double iconMarginX = 3; double stereotypeWidth = moduleStereotype.getBounds().width; double iconWidth = 0; if (moduleIcon != null) { iconWidth = moduleIcon.getWidth(); } double totalHeaderWidth = textGap + nameWidth + textGap + stereotypeWidth + textGap + iconWidth + iconMarginX; this.minWidth = (int) totalHeaderWidth; // Set bounds body if (lead.x - anchor.x < minWidth) lead.x = anchor.x + minWidth; if (lead.y - anchor.y < minHeight) lead.y = anchor.y + minHeight; if (lead.x - anchor.x < totalHeaderWidth) lead.x = anchor.x + totalHeaderWidth; body.setBounds(anchor, lead); // Position name double namePlusX = ((lead.x - anchor.x - iconWidth - iconMarginX) - (nameWidth + textGap + stereotypeWidth)) / 2; Point2D.Double nameTextAnchor = (Double) anchor.clone(); nameTextAnchor.x += namePlusX; nameTextAnchor.y += marginY; moduleName.setBounds(nameTextAnchor, null); // Position stereotype Point2D.Double stereoTypeTextAnchor = (Double) anchor.clone(); stereoTypeTextAnchor.x = nameTextAnchor.x + nameWidth + textGap; stereoTypeTextAnchor.y += marginY; moduleStereotype.setBounds(stereoTypeTextAnchor, null); // Position icon if (moduleIconFigure != null) { double iconAnchorX = lead.x - iconMarginX - iconWidth; double iconAnchorY = anchor.y + marginY; double iconLeadX = iconAnchorX + iconWidth; double iconLeadY = iconAnchorY + moduleIcon.getHeight(); moduleIconFigure.setBounds(new Point2D.Double(iconAnchorX, iconAnchorY), new Point2D.Double(iconLeadX, iconLeadY)); } invalidate(); } public void setMinimalSizes(int minWidth, int minHeight) { this.minWidth = minWidth; this.minHeight = minHeight; } public void updateBounds(Point2D.Double anchor, Point2D.Double lead) { willChange(); setBounds(anchor, lead); changed(); } @Override public String toString() { String representation = ""; representation += "\name: " + super.name; representation += "\nType: " + type; representation += "\n"; return representation; } }