001: package com.xoetrope.builder.w3c.html;
002:
003: import com.xoetrope.builder.w3c.html.tags.XHtmlTagHandler;
004: import java.awt.Component;
005: import java.awt.Container;
006: import java.awt.Dimension;
007: import java.awt.Insets;
008: import java.awt.LayoutManager;
009: import javax.swing.SwingConstants;
010:
011: /**
012: * A layout manager for html forms. Components flow along rows till a break element
013: * is encountered abd then they flow to the next row along the page length
014: * <p> Copyright (c) Xoetrope Ltd., 2002-2006</p>
015: * <p> $Revision: 1.2 $</p>
016: * <p> License: see License.txt</p>
017: */
018: public class XHtmlFormLayout implements LayoutManager {
019: public static final int PREFERRED = 0;
020: public static final int FILL = 1;
021:
022: protected XHtmlBuilder builder;
023: private int padding = 2;
024: private XHtmlTagHandler tag;
025:
026: private int horizontalAlignment = SwingConstants.LEFT;
027:
028: /**
029: * Creates a layout manager that will lay out components along the
030: * y axis.
031: *
032: * @param target the container that needs to be laid out
033: */
034: public XHtmlFormLayout(XHtmlBuilder htmlBuilder) {
035: builder = htmlBuilder;
036: }
037:
038: /**
039: * Set the horizontal alignment
040: * @param alignment the alignment string - left|right|center
041: */
042: public void setAlignment(String alignment) {
043: horizontalAlignment = builder.getSwingConstant(alignment);
044: }
045:
046: /**
047: * If the layout manager uses a per-component string,
048: * adds the component <code>comp</code> to the layout,
049: * associating it
050: * with the string specified by <code>name</code>.
051: *
052: * @param name the string to be associated with the component
053: * @param comp the component to be added
054: */
055: public void addLayoutComponent(String name, Component comp) {
056: }
057:
058: /**
059: * Removes the specified component from the layout.
060: * @param comp the component to be removed
061: */
062: public void removeLayoutComponent(Component comp) {
063:
064: }
065:
066: /**
067: * Calculates the preferred size dimensions for the specified
068: * container, given the components it contains.
069: * @param parent the container to be laid out
070: *
071: * @see #minimumLayoutSize
072: */
073: public Dimension preferredLayoutSize(Container parent) {
074: Dimension parentSize = parent.getSize();
075:
076: int numComponents = parent.getComponentCount();
077: int preferredWidth = 0;
078: int preferredHeight = 0;
079: int rowHeight = 0;
080: int rowWidth = 0;
081: for (int i = 0; i < numComponents; i++) {
082: Component c = parent.getComponent(i);
083: if (c.isVisible()) {
084: Dimension d = getPreferredSize(parentSize, c);
085: if ((tag != null) && tag.breaksFlow()) {
086: // Add the previous row's height, width
087: preferredHeight += rowHeight;
088: preferredWidth = Math.max(rowWidth, preferredWidth);
089: rowHeight = d.height;
090: rowWidth = d.width;
091: } else {
092: rowHeight = Math.max(rowHeight, d.height);
093: rowWidth += d.width;
094: }
095: }
096: }
097: // Add he last row's height
098: preferredHeight += rowHeight;
099: preferredWidth = Math.max(rowWidth, preferredWidth);
100:
101: Insets insets = parent.getInsets();
102: return new Dimension(preferredWidth + insets.left
103: + insets.right + padding, preferredHeight + insets.top
104: + insets.bottom + padding);
105: }
106:
107: /**
108: * Calculates the minimum size dimensions for the specified
109: * container, given the components it contains.
110: * @param parent the component to be laid out
111: * @see #preferredLayoutSize
112: */
113: public Dimension minimumLayoutSize(Container parent) {
114: Dimension parentSize = parent.getSize();
115:
116: int numComponents = parent.getComponentCount();
117: int preferredWidth = 0;
118: int preferredHeight = 0;
119: int rowHeight = 0;
120: int rowWidth = 0;
121: for (int i = 0; i < numComponents; i++) {
122: Component c = parent.getComponent(i);
123: Dimension d = getMinimumSize(parentSize, c);
124: if ((tag != null) && tag.breaksFlow()) {
125: // Add the previous row's height, width
126: preferredHeight += rowHeight;
127: preferredWidth = Math.max(rowWidth, preferredWidth);
128: rowHeight = d.height;
129: rowWidth = d.width;
130: } else {
131: rowHeight = Math.max(rowHeight, d.height);
132: rowWidth += d.width;
133: }
134: }
135: // Add he last row's height
136: preferredHeight += rowHeight;
137: preferredWidth = Math.max(rowWidth, preferredWidth);
138:
139: Insets insets = parent.getInsets();
140: return new Dimension(preferredWidth + insets.left
141: + insets.right + padding, preferredHeight + insets.top
142: + insets.bottom + padding);
143: }
144:
145: /**
146: * Lays out the specified container.
147: * @param parent the container to be laid out
148: */
149: public void layoutContainer(Container parent) {
150: Dimension parentSize = parent.getSize();
151:
152: int numComponents = parent.getComponentCount();
153: int rowHeight = 0;
154: int cx = 0;
155: int cy = 0;
156:
157: if (horizontalAlignment == SwingConstants.RIGHT)
158: cx = parentSize.width;
159: else if (horizontalAlignment == SwingConstants.CENTER)
160: cx = parentSize.width / 2;
161: int startX = cx;
162: for (int i = 0; i < numComponents; i++) {
163: Component c = parent.getComponent(i);
164: if (c.isVisible()) {
165: Dimension d = getPreferredSize(parentSize, c);
166: if (d.width > parentSize.width)
167: d.width = parentSize.width;
168: if ((tag != null) && tag.breaksFlow()) {
169: cx = startX;
170: cy += rowHeight;
171: rowHeight = 0;
172: }
173:
174: int x = cx;
175: int dx = 0;
176: if (horizontalAlignment == SwingConstants.RIGHT)
177: dx = -d.width;
178: else if (horizontalAlignment == SwingConstants.CENTER)
179: dx = -d.width / 2;
180: /**@todo this isn't right as the component cumulative width isn't considered */
181:
182: c.setBounds(x + dx, cy, d.width, d.height);
183: rowHeight = Math.max(rowHeight, d.height);
184: cx += dx;
185: }
186: }
187: }
188:
189: /**
190: * Lookup the tag handler for a component
191: * @param c the component in question
192: */
193: private void getTagHandler(Component c) {
194: tag = (XHtmlTagHandler) builder.getComponentAttribute(Integer
195: .toString(c.hashCode()), "tagHandler");
196: }
197:
198: /**
199: * Get the preferred size of the component accounting for the html attributes
200: * @param parentSize the parent container's dimensions
201: * @param c the component in question
202: */
203: private Dimension getPreferredSize(Dimension parentSize, Component c) {
204: if (tag == null)
205: getTagHandler(c);
206: Dimension d = c.getPreferredSize();
207:
208: if (tag == null)
209: return d;
210:
211: int tagWidth = tag.getWidth(parentSize);
212: int tagHeight = tag.getHeight(parentSize);
213: return new Dimension(tagWidth > 0 ? tagWidth : d.width,
214: tagHeight > 0 ? tagHeight : d.height);
215: }
216:
217: /**
218: * Get the preferred size of the component accounting for the html attributes
219: * @param parentSize the parent container's dimensions
220: * @param c the component in question
221: */
222: private Dimension getMinimumSize(Dimension parentSize, Component c) {
223: if (tag == null)
224: getTagHandler(c);
225: Dimension d = c.getMinimumSize();
226: if (tag == null)
227: return d;
228:
229: int tagWidth = tag.getWidth(parentSize);
230: int tagHeight = tag.getHeight(parentSize);
231: return new Dimension(tagWidth > 0 ? tagWidth : d.width,
232: tagHeight > 0 ? tagHeight : d.height);
233: }
234: }
|