/* */ package com.cloudgarden.layout; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.LayoutManager2; import java.awt.Rectangle; import java.util.HashMap; /** * Lays out components, using a combination of their "bounds" property * and their AnchorConstraints layout constraint objects. * <P> * Sides of the components can be anchored either absolutely (eg, if the * right side is anchored absolutely then it will always be a fixed number * of pixels from the right side of it's parent container) or relatively (ie, * if any side is anchored relatively then it will always occur a fixed * fraction of the way along it's parent's side). Or they can be not anchored, * at all in which case they will occur at places determined by their * component's "bounds" property and the anchoring of the component's * other sides. */ public class AnchorLayout implements LayoutManager2 { private int preferredWidth, preferredHeight, minHeight, minWidth; private HashMap constraintMap = new HashMap(); private boolean sizesCalculated = false; private Container container; public AnchorLayout() { super(); } void initialize(Container parent) { if (sizesCalculated) return; Component[] children = parent.getComponents(); preferredWidth = 10000; preferredHeight = 10000; minWidth = 0; minHeight = 0; Rectangle pb = parent.getBounds(); for (int i = 0; i < children.length; i++) { Component child = children[i]; if (child != null) { Object ld = constraintMap.get(child); Rectangle b = child.getBounds(); Dimension pref = child.getPreferredSize(); Dimension min = child.getMaximumSize(); if (pref == null) pref = child.getSize(); if (min == null) min = child.getSize(); int minX = b.x + b.width; int minY = b.y + b.height; int maxX = b.x + b.width; int maxY = b.y + b.height; if (ld instanceof AnchorConstraint) { AnchorConstraint ac = (AnchorConstraint) ld; int acl = ac.left; int acr = ac.right; int aclt = ac.leftType; int acrt = ac.rightType; if (aclt == AnchorConstraint.ANCHOR_REL) acl = acl * pb.width / 1000; if (acrt == AnchorConstraint.ANCHOR_REL) acr = pb.width - acr * pb.width / 1000; if (aclt != AnchorConstraint.ANCHOR_NONE && acrt != AnchorConstraint.ANCHOR_NONE) maxX = acl + pref.width + acr; if (aclt == AnchorConstraint.ANCHOR_NONE) acl = 0; if (acrt == AnchorConstraint.ANCHOR_NONE) acr = 0; minX = acl + min.width + acr; int act = ac.top; int acb = ac.bottom; int actt = ac.topType; int acbt = ac.bottomType; if (actt == AnchorConstraint.ANCHOR_REL) act = act * pb.height / 1000; if (acbt == AnchorConstraint.ANCHOR_REL) acb = pb.height - acb * pb.height / 1000; if (actt != AnchorConstraint.ANCHOR_NONE && acbt != AnchorConstraint.ANCHOR_NONE) maxY = act + pref.height + acb; if (actt == AnchorConstraint.ANCHOR_NONE) act = 0; if (acbt == AnchorConstraint.ANCHOR_NONE) acb = 0; minY = act + min.height + acb; } if (minX > minWidth) minWidth = minX; if (maxX > minWidth) preferredWidth = maxX; if (minY > minHeight) minHeight = minY; if (maxY > preferredHeight) preferredHeight = maxY; } } } /* (non-Javadoc) * @see org.eclipse.swt.widgets.Layout#layout(org.eclipse.swt.widgets.Composite, boolean) */ public void layoutContainer(Container container) { this.container = container; Component children[] = container.getComponents(); Rectangle rect = container.getBounds(); int width = rect.width; int height = rect.height; for (int i = 0; i < children.length; i++) { Component child = children[i]; if (child != null) { Object ld = constraintMap.get(child); Rectangle b = child.getBounds(); Dimension pref = child.getPreferredSize(); if (pref == null) pref = child.getSize(); if (ld instanceof AnchorConstraint) { AnchorConstraint ac = (AnchorConstraint) ld; int acl = ac.left; int acr = ac.right; int aclt = ac.leftType; int acrt = ac.rightType; if (aclt == AnchorConstraint.ANCHOR_REL) acl = acl * width / 1000; if (acrt == AnchorConstraint.ANCHOR_REL) acr = width - acr * width / 1000; if (aclt != AnchorConstraint.ANCHOR_NONE) { if (acrt != AnchorConstraint.ANCHOR_NONE) { b.width = width - acr - acl; b.x = acl; } else { b.width = pref.width; if (b.width + acl > width) b.width = width - acl; b.x = acl; } } else { if (acrt != AnchorConstraint.ANCHOR_NONE) { b.x = width - acr - pref.width; } b.width = pref.width; if (b.width + b.x > width) b.width = width - b.x; } int act = ac.top; int acb = ac.bottom; int actt = ac.topType; int acbt = ac.bottomType; if (actt == AnchorConstraint.ANCHOR_REL) act = act * height / 1000; if (acbt == AnchorConstraint.ANCHOR_REL) acb = height - acb * height / 1000; if (actt != AnchorConstraint.ANCHOR_NONE) { if (acbt != AnchorConstraint.ANCHOR_NONE) { b.height = height - acb - act; b.y = act; } else { b.height = pref.height; if (b.height + act > height) b.height = height - act; b.y = act; } } else { if (acbt != AnchorConstraint.ANCHOR_NONE) { b.y = height - acb - pref.height; } b.height = pref.height; if (b.height + b.y > height) b.height = height - b.y; } child.setBounds(b); } } } } /* (non-Javadoc) * @see java.awt.LayoutManager#addLayoutComponent(java.lang.String, java.awt.Component) */ public void addLayoutComponent(String name, Component comp) {} /* (non-Javadoc) * @see java.awt.LayoutManager#removeLayoutComponent(java.awt.Component) */ public void removeLayoutComponent(Component comp) { constraintMap.remove(comp); } /* (non-Javadoc) * @see java.awt.LayoutManager#preferredLayoutSize(java.awt.Container) */ public Dimension preferredLayoutSize(Container parent) { initialize(parent); return new Dimension(preferredWidth, preferredHeight); } /* (non-Javadoc) * @see java.awt.LayoutManager#minimumLayoutSize(java.awt.Container) */ public Dimension minimumLayoutSize(Container parent) { initialize(parent); return new Dimension(minWidth, minHeight); } /* (non-Javadoc) * @see java.awt.LayoutManager2#addLayoutComponent(java.awt.Component, java.lang.Object) */ public void addLayoutComponent(Component comp, Object constraints) { constraintMap.put(comp, constraints); } /* (non-Javadoc) * @see java.awt.LayoutManager2#maximumLayoutSize(java.awt.Container) */ public Dimension maximumLayoutSize(Container target) { return preferredLayoutSize(target); } /* (non-Javadoc) * @see java.awt.LayoutManager2#getLayoutAlignmentX(java.awt.Container) */ public float getLayoutAlignmentX(Container target) { return 0; } /* (non-Javadoc) * @see java.awt.LayoutManager2#getLayoutAlignmentY(java.awt.Container) */ public float getLayoutAlignmentY(Container target) { return 0; } /* (non-Javadoc) * @see java.awt.LayoutManager2#invalidateLayout(java.awt.Container) */ public void invalidateLayout(Container target) { sizesCalculated = false; } }