package com.horstmann.violet.framework.graphics.content; import java.awt.*; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; /** * This class groups together all the component relative * * @author Adrian Bobrowski <adrian071993@gmail.com> * @date 21.12.2015 */ public class RelativeLayout extends Layout { static protected class RelativeContent extends Content { public RelativeContent(Content content, Point2D position) { content.addParent(this); this.content = content; this.position = position; refreshUp(); } /** * @see Content#draw(Graphics2D) */ @Override public void draw(Graphics2D graphics) { content.draw(graphics, position); } /** * @see Content#refreshUp() */ @Override public final void refreshUp() { Rectangle2D minimalBounds = getMinimalBounds(); setWidth(minimalBounds.getWidth()); setHeight(minimalBounds.getHeight()); super.refreshUp(); } /** * @return minimal bounds of this element */ @Override public Rectangle2D getMinimalBounds() { Rectangle2D contentMinimalBounds = content.getMinimalBounds(); Rectangle2D selfMinimalBounds = super.getMinimalBounds(); return new Rectangle2D.Double( position.getX(), position.getY(), Math.max(selfMinimalBounds.getWidth(), contentMinimalBounds.getWidth()), Math.max(selfMinimalBounds.getHeight(), contentMinimalBounds.getHeight()) ); } /** * @return positions relative to the inside layout */ public Point2D getPosition() { return position; } /** * set positions relative to the inside layout * @param position */ public void setPosition(Point2D position) { if(null == position) { this.position.setLocation(0,0); } else { this.position.setLocation(Math.max(0, position.getX()),Math.max(0, position.getY())); } refreshUp(); } private Point2D position; private Content content; } /** * @see Layout#getNextOffset(Point2D, Content) */ @Override protected Point2D getNextOffset(Point2D beforeOffset, Content content) { return new Point2D.Double(0,0); } /** * @see Layout#getStartPointSeparator(Point2D) */ @Override protected Point2D getStartPointSeparator(Point2D offset) { return new Point2D.Double(0,0); } /** * @see Layout#getEndPointSeparator(Point2D) */ @Override protected Point2D getEndPointSeparator(Point2D offset) { return new Point2D.Double(0,0); } /** * @see Layout#add(Content) */ @Override public void add(Content content) { add(content, new Point2D.Double(0,0)); } /** * add a content to layout and sets him positions * @param content * @param position */ public void add(Content content, Point2D position) { if(null == content) { throw new NullPointerException("Content can't be null"); } super.add(new RelativeContent(content, position)); } /** * @see Layout#remove(Content) */ @Override public void remove(Content content) { if(null == content) { return; } RelativeContent relativeContent = null; for (Content c: getContents()) { relativeContent = (RelativeContent)c; if(relativeContent.content.equals(content)) { super.remove(relativeContent); break; } } } /** * @see Content#refreshUp() */ @Override public final void refreshUp() { Rectangle2D minimalBounds = getMinimalBounds(); setWidth(minimalBounds.getWidth()); setHeight(minimalBounds.getHeight()); super.refreshUp(); } /** * @return minimal bounds of this element */ @Override public Rectangle2D getMinimalBounds() { Rectangle2D selfMinimalBounds = super.getMinimalBounds(); double maxX = selfMinimalBounds.getWidth(); double maxY = selfMinimalBounds.getHeight(); for (Content content: getContents()) { Rectangle2D rect = content.getMinimalBounds(); maxX = Math.max(maxX, rect.getMaxX()); maxY = Math.max(maxY, rect.getMaxY()); } return new Rectangle2D.Double(getX(),getY(),maxX,maxY); } public final boolean setPosition(Content content, Point2D position) { if(null == content) { return false; } RelativeContent relativeContent = null; for (Content c: getContents()) { relativeContent = (RelativeContent)c; if(relativeContent.content.equals(content)) { relativeContent.setPosition(position); return true; } } return false; } }