CompoundRegion.java

00001 package edu.stanford.hci.r3.paper.regions;
00002 
00003 import java.awt.geom.Rectangle2D;
00004 import java.util.HashMap;
00005 import java.util.Map;
00006 import java.util.Set;
00007 
00008 import edu.stanford.hci.r3.paper.Region;
00009 import edu.stanford.hci.r3.render.RegionRenderer;
00010 import edu.stanford.hci.r3.render.regions.CompoundRenderer;
00011 import edu.stanford.hci.r3.units.Inches;
00012 import edu.stanford.hci.r3.units.Units;
00013 import edu.stanford.hci.r3.units.coordinates.Coordinates;
00014 
00026 public class CompoundRegion extends Region {
00027 
00031         private Map<Region, Coordinates> regionsAndRelativeLocations = new HashMap<Region, Coordinates>();
00032 
00036         private Units x;
00037 
00038         private Units y;
00039 
00043         public CompoundRegion(String name, Units xOrigin, Units yOrigin) {
00044                 // it is dimensionless until we calculate the actual size
00045                 super(name, xOrigin, yOrigin, new Inches(0), new Inches(0));
00046 
00047                 // since it is compound, we need to KEEP these origins aroudn for later calculations
00048                 x = xOrigin;
00049                 y = yOrigin.getUnitsObjectOfSameLengthIn(x);
00050         }
00051 
00062         public void addChild(Region childRegion, Coordinates relativeCoord) {
00063                 regionsAndRelativeLocations.put(childRegion, relativeCoord);
00064 
00065                 // get the shape
00066                 final Rectangle2D myBounds = (Rectangle2D) getShape();
00067                 final Units myUnits = getUnits();
00068 
00069                 // update the coordinates by taking the union of the current bounds with the
00070                 // bounds of the child (translated by relativeCoords)
00071                 final Rectangle2D childBounds = childRegion.getShape().getBounds2D();
00072                 final Units childUnits = childRegion.getUnits();
00073 
00074                 // change the child's bounds into bounds that can be interpreted in OUR units
00075                 final double c = childUnits.getConversionTo(myUnits);
00076                 // DebugUtils.println("Conversion is: " + c);
00077                 final Rectangle2D childBoundsInOurUnits = new Rectangle2D.Double( //
00078                                 childBounds.getX() * c, childBounds.getY() * c, //
00079                                 childBounds.getWidth() * childRegion.getScaleX() * c, //
00080                                 childBounds.getHeight() * childRegion.getScaleY() * c);
00081 
00082                 // the origin of the child is myOrigin + childOrigin + childOffset
00083                 final double childXTranslated = x.getValue() + childBoundsInOurUnits.getX()
00084                                 + relativeCoord.getX().getValueIn(myUnits);
00085                 final double childYTranslated = y.getValue() + childBoundsInOurUnits.getY()
00086                                 + relativeCoord.getY().getValueIn(myUnits);
00087 
00088                 final Rectangle2D childBoundsTranslated = new Rectangle2D.Double( //
00089                                 childXTranslated, childYTranslated, //
00090                                 childBoundsInOurUnits.getWidth(), //
00091                                 childBoundsInOurUnits.getHeight());
00092 
00093                 // set the shape to be the union of the two rectangles
00094                 // the catch here is that if you set the origin at 0,0 and you add a small rectangle
00095                 // way out there, the final bounds will be huge, because it is RELATIVE to the original
00096                 // origin!!!! You have been warned.
00097                 final Rectangle2D unionOfMyBoundsAndChildBounds = myBounds
00098                                 .createUnion(childBoundsTranslated);
00099                 setShape(unionOfMyBoundsAndChildBounds);
00100         }
00101 
00106         public Coordinates getChildOffset(Region child) {
00107                 return regionsAndRelativeLocations.get(child);
00108         }
00109 
00113         public Set<Region> getChildren() {
00114                 return regionsAndRelativeLocations.keySet();
00115         }
00116 
00120         public RegionRenderer getRenderer() {
00121                 return new CompoundRenderer(this);
00122         }
00123 
00127         public String toString() {
00128                 final Set<Region> children = regionsAndRelativeLocations.keySet();
00129                 final StringBuilder childNames = new StringBuilder();
00130                 int i = 0;
00131                 for (Region r : children) {
00132                         childNames.append(r.getName());
00133                         if (i < children.size() - 1) {
00134                                 childNames.append(", ");
00135                         }
00136                         i++;
00137                 }
00138                 return "Compound Region {" + childNames.toString() + "} at Bounds: [x="
00139                                 + getOriginX().getValue() + " y=" + getOriginY().getValue() + " w="
00140                                 + getShape().getBounds2D().getWidth() + " h="
00141                                 + getShape().getBounds2D().getHeight() + "] in " + referenceUnits.getUnitName();
00142         }
00143 }

Generated on Sat Apr 14 18:21:33 2007 for R3 Paper Toolkit by  doxygen 1.4.7