001: /*
002: * Copyright (C) 2004 NNL Technology AB
003: * Visit www.infonode.net for information about InfoNode(R)
004: * products and how to contact NNL Technology AB.
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU General Public License
008: * as published by the Free Software Foundation; either version 2
009: * of the License, or (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
019: * MA 02111-1307, USA.
020: */
021:
022: // $Id: DirectionLayout.java,v 1.15 2005/12/04 13:46:03 jesper Exp $
023: package net.infonode.gui.layout;
024:
025: import net.infonode.util.Direction;
026:
027: import java.awt.*;
028: import java.util.ArrayList;
029: import java.util.HashMap;
030:
031: public class DirectionLayout implements LayoutManager2 {
032: private static final Insets EMPTY_INSETS = new Insets(0, 0, 0, 0);
033:
034: private Direction direction;
035: private HashMap componentInsets;
036: private int componentSpacing;
037: private boolean compressing;
038:
039: private ArrayList layoutOrderList;
040:
041: public DirectionLayout() {
042: this (Direction.RIGHT);
043: }
044:
045: public DirectionLayout(int componentSpacing) {
046: this (Direction.RIGHT, componentSpacing);
047: }
048:
049: public DirectionLayout(Direction direction) {
050: this (direction, 0);
051: }
052:
053: public DirectionLayout(Direction direction, int componentSpacing) {
054: this .direction = direction;
055: this .componentSpacing = componentSpacing;
056: }
057:
058: public int getComponentSpacing() {
059: return componentSpacing;
060: }
061:
062: public void setComponentSpacing(int componentSpacing) {
063: this .componentSpacing = componentSpacing;
064: }
065:
066: public void addLayoutComponent(String name, Component comp) {
067: }
068:
069: public Direction getDirection() {
070: return direction;
071: }
072:
073: public void setDirection(Direction direction) {
074: this .direction = direction;
075: }
076:
077: public boolean isVertical() {
078: return !direction.isHorizontal();
079: }
080:
081: public boolean isCompressing() {
082: return compressing;
083: }
084:
085: public void setCompressing(boolean compressing) {
086: this .compressing = compressing;
087: }
088:
089: public void setLayoutOrderList(ArrayList layoutOrderList) {
090: this .layoutOrderList = layoutOrderList;
091: }
092:
093: private int getSize(Dimension d) {
094: return (int) (isVertical() ? d.getHeight() : d.getWidth());
095: }
096:
097: private static int getBeforeSpacing(Insets insets) {
098: return insets.left;
099: }
100:
101: private int getAfterSpacing(Component component, boolean isLast) {
102: return getInsets(component).right
103: + (isLast ? 0 : componentSpacing);
104: }
105:
106: private Dimension createSize(int size, int otherSize) {
107: return isVertical() ? new Dimension(otherSize, size)
108: : new Dimension(size, otherSize);
109: }
110:
111: private static Dimension getSize(Dimension interiorSize,
112: Container component) {
113: Insets insets = component.getInsets();
114: return new Dimension(interiorSize.width + insets.left
115: + insets.right, interiorSize.height + insets.top
116: + insets.bottom);
117: }
118:
119: private int getOtherSize(Dimension dim) {
120: return (int) (isVertical() ? dim.getWidth() : dim.getHeight());
121: }
122:
123: private void setSize(Component component, int size, int otherSize) {
124: int maxOtherSize = getOtherSize(component.getMaximumSize());
125: component.setSize(createSize(size, Math.min(maxOtherSize,
126: otherSize)));
127: }
128:
129: public void layoutContainer(Container parent) {
130: Component[] components = getVisibleChildren(parent);
131:
132: /*System.out.println("Parent: " + parent.getComponentCount() + " List: " + components.length);
133: for (int i = 0; i < components.length; i++) {
134: System.out.println("Parent: " + parent.getComponent(i) + " List: " + components[i]);
135: }*/
136:
137: int count = components.length;
138:
139: if (components.length == 0)
140: return;
141:
142: int totalSpacing = 0;
143:
144: for (int i = 0; i < components.length; i++)
145: totalSpacing += getSpacing(components[i],
146: i == components.length - 1);
147:
148: boolean[] discarded = new boolean[components.length];
149: Dimension parentInteriorSize = LayoutUtil
150: .getInteriorSize(parent);
151: int componentsTotalSize = getSize(parentInteriorSize)
152: - totalSpacing;
153: int maxComponentSize = componentsTotalSize / components.length;
154: int lastCount;
155:
156: int otherSize = getOtherSize(parentInteriorSize);
157: //System.out.println(parentInteriorSize);
158: // int otherSize = Math.min(getOtherSize(parentInteriorSize), getOtherSize(LayoutUtil.getMaxPreferredSize(components)));
159:
160: // First, set componentsTotalSize of all components that fit inside the limit
161: do {
162: lastCount = count;
163:
164: for (int i = 0; i < components.length; i++) {
165: if (!discarded[i]) {
166: int prefSize = getSize(components[i]
167: .getPreferredSize());
168:
169: if (prefSize <= maxComponentSize) {
170: setSize(components[i], prefSize, otherSize);
171: componentsTotalSize -= prefSize;
172: discarded[i] = true;
173: count--;
174:
175: if (count == 0)
176: break;
177:
178: maxComponentSize = componentsTotalSize / count;
179: }
180: }
181: }
182: } while (lastCount > count);
183:
184: if (count > 0) {
185: do {
186: lastCount = count;
187:
188: // Now fit all that have a larger minimum componentsTotalSize
189: for (int i = 0; i < components.length; i++) {
190: if (!discarded[i]) {
191: int minSize = getSize(components[i]
192: .getMinimumSize());
193:
194: if (minSize >= maxComponentSize) {
195: setSize(components[i], minSize, otherSize);
196: componentsTotalSize -= minSize;
197: discarded[i] = true;
198: count--;
199:
200: if (count == 0)
201: break;
202:
203: maxComponentSize = componentsTotalSize
204: / count;
205: }
206: }
207: }
208: } while (lastCount > count);
209: }
210:
211: Insets insets = parent.getInsets();
212:
213: int pos = direction == Direction.RIGHT ? insets.left
214: : direction == Direction.DOWN ? insets.top
215: : direction == Direction.LEFT ? insets.right
216: : insets.bottom;
217:
218: int yOffset = isVertical() ? insets.left : insets.top;
219:
220: for (int i = 0; i < components.length; i++) {
221: pos += getBeforeSpacing(getInsets(components[i]));
222:
223: if (!discarded[i]) {
224: int componentSize = Math
225: .max(getSize(components[i].getMinimumSize()),
226: componentsTotalSize / count);
227: setSize(components[i], componentSize, otherSize);
228: count--;
229: componentsTotalSize -= componentSize;
230: }
231:
232: int yPos = yOffset
233: + (int) ((otherSize - getOtherSize(components[i]
234: .getSize())) * (direction == Direction.DOWN
235: || direction == Direction.LEFT ? 1 - components[i]
236: .getAlignmentY()
237: : components[i].getAlignmentY()));
238:
239: if (isVertical()) {
240: components[i].setLocation(yPos,
241: direction == Direction.DOWN ? pos : parent
242: .getHeight()
243: - pos - components[i].getHeight());
244: } else {
245: components[i].setLocation(
246: direction == Direction.RIGHT ? pos : parent
247: .getWidth()
248: - pos - components[i].getWidth(), yPos);
249: }
250:
251: pos += getSize(components[i].getSize())
252: + getAfterSpacing(components[i],
253: i == components.length - 1);
254: //System.out.println("\n" + components[i] + " " + components[i].getLocation() + " " + components[i].getSize() + " " + ((JComponent)components[i]).getInsets());
255: }
256: }
257:
258: public void setComponentInsets(Component c, Insets i) {
259: if (i == null) {
260: removeLayoutComponent(c);
261: } else {
262: if (componentInsets == null)
263: componentInsets = new HashMap(4);
264:
265: componentInsets.put(c, i);
266: }
267: }
268:
269: private Component[] getVisibleChildren(Container parent) {
270: if (layoutOrderList != null) {
271: Component[] components = new Component[layoutOrderList
272: .size()];
273: for (int i = 0; i < layoutOrderList.size(); i++)
274: components[i] = (Component) layoutOrderList.get(i);
275:
276: return LayoutUtil.getVisibleChildren(components);
277: }
278:
279: return LayoutUtil.getVisibleChildren(parent);
280: }
281:
282: private int getSpacing(Component component, boolean isLast) {
283: Insets insets = getInsets(component);
284: return insets.left + insets.right
285: + (isLast ? 0 : componentSpacing);
286: }
287:
288: private Insets getInsets(Component component) {
289: Object o = componentInsets == null ? null : componentInsets
290: .get(component);
291: return o == null ? EMPTY_INSETS : (Insets) o;
292: }
293:
294: public Dimension minimumLayoutSize(Container parent) {
295: Component[] c = getVisibleChildren(parent);
296: int size = 0;
297: int maxHeight = 0;
298:
299: for (int i = 0; i < c.length; i++) {
300: size += getSize(c[i].getMinimumSize())
301: + getSpacing(c[i], i == c.length - 1);
302: maxHeight = Math.max(getOtherSize(c[i].getMinimumSize()),
303: maxHeight);
304: }
305:
306: Dimension d = getSize(isVertical() ? new Dimension(maxHeight,
307: size) : new Dimension(size, maxHeight), parent);
308: //System.out.println("Minimum size: " + d);
309: return d;
310: }
311:
312: public Dimension preferredLayoutSize(Container parent) {
313: Component[] c = getVisibleChildren(parent);
314: int size = 0;
315: int maxHeight = 0;
316:
317: for (int i = 0; i < c.length; i++) {
318: if (!compressing)
319: size += getSize(c[i].getPreferredSize())
320: + getSpacing(c[i], i == c.length - 1);
321:
322: maxHeight = Math.max(getOtherSize(c[i].getPreferredSize()),
323: maxHeight);
324: }
325:
326: Dimension d = getSize(isVertical() ? new Dimension(maxHeight,
327: size) : new Dimension(size, maxHeight), parent);
328: //System.out.println("Preferred size: " + d);
329: return d;
330: }
331:
332: public void removeLayoutComponent(Component comp) {
333: if (componentInsets != null) {
334: componentInsets.remove(comp);
335:
336: if (componentInsets.size() == 0)
337: componentInsets = null;
338: }
339: }
340:
341: public void addLayoutComponent(Component comp, Object constraints) {
342: setComponentInsets(comp, (Insets) constraints);
343: }
344:
345: public float getLayoutAlignmentX(Container target) {
346: return 0;
347: }
348:
349: public float getLayoutAlignmentY(Container target) {
350: return 0;
351: }
352:
353: public void invalidateLayout(Container target) {
354: }
355:
356: public Dimension maximumLayoutSize(Container parent) {
357: Component[] c = getVisibleChildren(parent);
358: int size = 0;
359: int maxHeight = Integer.MAX_VALUE;
360:
361: for (int i = 0; i < c.length; i++) {
362: size += getSize(c[i].getMaximumSize())
363: + getSpacing(c[i], i == c.length - 1);
364: // maxHeight = Math.min(getOtherSize(c[i].getMaximumSize()), maxHeight);
365: }
366:
367: Dimension d = getSize(isVertical() ? new Dimension(maxHeight,
368: size) : new Dimension(size, maxHeight), parent);
369: //System.out.println("Maximum size: " + d);
370: return d;
371: }
372: }
|