001: /*
002: */
003: package com.cloudgarden.layout;
004:
005: import java.awt.Component;
006: import java.awt.Container;
007: import java.awt.Dimension;
008: import java.awt.LayoutManager2;
009: import java.awt.Rectangle;
010: import java.util.HashMap;
011:
012: /**
013: * Lays out components, using a combination of their "bounds" property
014: * and their AnchorConstraints layout constraint objects.
015: * <P>
016: * Sides of the components can be anchored either absolutely (eg, if the
017: * right side is anchored absolutely then it will always be a fixed number
018: * of pixels from the right side of it's parent container) or relatively (ie,
019: * if any side is anchored relatively then it will always occur a fixed
020: * fraction of the way along it's parent's side). Or they can be not anchored,
021: * at all in which case they will occur at places determined by their
022: * component's "bounds" property and the anchoring of the component's
023: * other sides.
024: */
025: public class AnchorLayout implements LayoutManager2 {
026:
027: private int preferredWidth, preferredHeight, minHeight, minWidth;
028: private HashMap constraintMap = new HashMap();
029: private boolean sizesCalculated = false;
030: private Container container;
031:
032: public AnchorLayout() {
033: super ();
034: }
035:
036: void initialize(Container parent) {
037: if (sizesCalculated)
038: return;
039: Component[] children = parent.getComponents();
040: preferredWidth = 10000;
041: preferredHeight = 10000;
042: minWidth = 0;
043: minHeight = 0;
044: Rectangle pb = parent.getBounds();
045: for (int i = 0; i < children.length; i++) {
046: Component child = children[i];
047: if (child != null) {
048: Object ld = constraintMap.get(child);
049: Rectangle b = child.getBounds();
050: Dimension pref = child.getPreferredSize();
051: Dimension min = child.getMaximumSize();
052: if (pref == null)
053: pref = child.getSize();
054: if (min == null)
055: min = child.getSize();
056: int minX = b.x + b.width;
057: int minY = b.y + b.height;
058: int maxX = b.x + b.width;
059: int maxY = b.y + b.height;
060: if (ld instanceof AnchorConstraint) {
061: AnchorConstraint ac = (AnchorConstraint) ld;
062: int acl = ac.left;
063: int acr = ac.right;
064: int aclt = ac.leftType;
065: int acrt = ac.rightType;
066:
067: if (aclt == AnchorConstraint.ANCHOR_REL)
068: acl = acl * pb.width / 1000;
069: if (acrt == AnchorConstraint.ANCHOR_REL)
070: acr = pb.width - acr * pb.width / 1000;
071:
072: if (aclt != AnchorConstraint.ANCHOR_NONE
073: && acrt != AnchorConstraint.ANCHOR_NONE)
074: maxX = acl + pref.width + acr;
075: if (aclt == AnchorConstraint.ANCHOR_NONE)
076: acl = 0;
077: if (acrt == AnchorConstraint.ANCHOR_NONE)
078: acr = 0;
079: minX = acl + min.width + acr;
080:
081: int act = ac.top;
082: int acb = ac.bottom;
083: int actt = ac.topType;
084: int acbt = ac.bottomType;
085: if (actt == AnchorConstraint.ANCHOR_REL)
086: act = act * pb.height / 1000;
087: if (acbt == AnchorConstraint.ANCHOR_REL)
088: acb = pb.height - acb * pb.height / 1000;
089:
090: if (actt != AnchorConstraint.ANCHOR_NONE
091: && acbt != AnchorConstraint.ANCHOR_NONE)
092: maxY = act + pref.height + acb;
093: if (actt == AnchorConstraint.ANCHOR_NONE)
094: act = 0;
095: if (acbt == AnchorConstraint.ANCHOR_NONE)
096: acb = 0;
097: minY = act + min.height + acb;
098: }
099: if (minX > minWidth)
100: minWidth = minX;
101: if (maxX > minWidth)
102: preferredWidth = maxX;
103: if (minY > minHeight)
104: minHeight = minY;
105: if (maxY > preferredHeight)
106: preferredHeight = maxY;
107: }
108: }
109:
110: }
111:
112: /* (non-Javadoc)
113: * @see org.eclipse.swt.widgets.Layout#layout(org.eclipse.swt.widgets.Composite, boolean)
114: */
115: public void layoutContainer(Container container) {
116: this .container = container;
117: Component children[] = container.getComponents();
118: Rectangle rect = container.getBounds();
119: int width = rect.width;
120: int height = rect.height;
121: for (int i = 0; i < children.length; i++) {
122: Component child = children[i];
123: if (child != null) {
124: Object ld = constraintMap.get(child);
125: Rectangle b = child.getBounds();
126: Dimension pref = child.getPreferredSize();
127: if (pref == null)
128: pref = child.getSize();
129: if (ld instanceof AnchorConstraint) {
130: AnchorConstraint ac = (AnchorConstraint) ld;
131: int acl = ac.left;
132: int acr = ac.right;
133: int aclt = ac.leftType;
134: int acrt = ac.rightType;
135: if (aclt == AnchorConstraint.ANCHOR_REL)
136: acl = acl * width / 1000;
137: if (acrt == AnchorConstraint.ANCHOR_REL)
138: acr = width - acr * width / 1000;
139:
140: if (aclt != AnchorConstraint.ANCHOR_NONE) {
141: if (acrt != AnchorConstraint.ANCHOR_NONE) {
142: b.width = width - acr - acl;
143: b.x = acl;
144: } else {
145: b.width = pref.width;
146: if (b.width + acl > width)
147: b.width = width - acl;
148: b.x = acl;
149: }
150: } else {
151: if (acrt != AnchorConstraint.ANCHOR_NONE) {
152: b.x = width - acr - pref.width;
153: }
154: b.width = pref.width;
155: if (b.width + b.x > width)
156: b.width = width - b.x;
157: }
158:
159: int act = ac.top;
160: int acb = ac.bottom;
161: int actt = ac.topType;
162: int acbt = ac.bottomType;
163: if (actt == AnchorConstraint.ANCHOR_REL)
164: act = act * height / 1000;
165: if (acbt == AnchorConstraint.ANCHOR_REL)
166: acb = height - acb * height / 1000;
167:
168: if (actt != AnchorConstraint.ANCHOR_NONE) {
169: if (acbt != AnchorConstraint.ANCHOR_NONE) {
170: b.height = height - acb - act;
171: b.y = act;
172: } else {
173: b.height = pref.height;
174: if (b.height + act > height)
175: b.height = height - act;
176: b.y = act;
177: }
178: } else {
179: if (acbt != AnchorConstraint.ANCHOR_NONE) {
180: b.y = height - acb - pref.height;
181: }
182: b.height = pref.height;
183: if (b.height + b.y > height)
184: b.height = height - b.y;
185: }
186: child.setBounds(b);
187: }
188: }
189: }
190: }
191:
192: /* (non-Javadoc)
193: * @see java.awt.LayoutManager#addLayoutComponent(java.lang.String, java.awt.Component)
194: */
195: public void addLayoutComponent(String name, Component comp) {
196: }
197:
198: /* (non-Javadoc)
199: * @see java.awt.LayoutManager#removeLayoutComponent(java.awt.Component)
200: */
201: public void removeLayoutComponent(Component comp) {
202: constraintMap.remove(comp);
203: }
204:
205: /* (non-Javadoc)
206: * @see java.awt.LayoutManager#preferredLayoutSize(java.awt.Container)
207: */
208: public Dimension preferredLayoutSize(Container parent) {
209: initialize(parent);
210: return new Dimension(preferredWidth, preferredHeight);
211: }
212:
213: /* (non-Javadoc)
214: * @see java.awt.LayoutManager#minimumLayoutSize(java.awt.Container)
215: */
216: public Dimension minimumLayoutSize(Container parent) {
217: initialize(parent);
218: return new Dimension(minWidth, minHeight);
219: }
220:
221: /* (non-Javadoc)
222: * @see java.awt.LayoutManager2#addLayoutComponent(java.awt.Component, java.lang.Object)
223: */
224: public void addLayoutComponent(Component comp, Object constraints) {
225: constraintMap.put(comp, constraints);
226: }
227:
228: /* (non-Javadoc)
229: * @see java.awt.LayoutManager2#maximumLayoutSize(java.awt.Container)
230: */
231: public Dimension maximumLayoutSize(Container target) {
232: return preferredLayoutSize(target);
233: }
234:
235: /* (non-Javadoc)
236: * @see java.awt.LayoutManager2#getLayoutAlignmentX(java.awt.Container)
237: */
238: public float getLayoutAlignmentX(Container target) {
239: return 0;
240: }
241:
242: /* (non-Javadoc)
243: * @see java.awt.LayoutManager2#getLayoutAlignmentY(java.awt.Container)
244: */
245: public float getLayoutAlignmentY(Container target) {
246: return 0;
247: }
248:
249: /* (non-Javadoc)
250: * @see java.awt.LayoutManager2#invalidateLayout(java.awt.Container)
251: */
252: public void invalidateLayout(Container target) {
253: sizesCalculated = false;
254: }
255:
256: }
|