001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: * Darrell Meyer <darrell@mygwt.net> - derived implementation
011: *******************************************************************************/package net.mygwt.ui.client.widget.layout;
012:
013: import net.mygwt.ui.client.MyDOM;
014: import net.mygwt.ui.client.Style;
015: import net.mygwt.ui.client.util.Rectangle;
016: import net.mygwt.ui.client.widget.Layout;
017: import net.mygwt.ui.client.widget.WidgetContainer;
018:
019: import com.google.gwt.user.client.Element;
020: import com.google.gwt.user.client.ui.Widget;
021:
022: /**
023: * RowLayouts determine the size and position of the children of a
024: * <code>Container</code> by placing them either in horizontal row or a
025: * vertical column within the parent <code>Container</code>.
026: *
027: * <p>
028: * RowLayout aligns all widgets in one row if the type is set to horizontal, and
029: * one column if it is set to vertical. Provides configurable margins and
030: * spacing.
031: * </p>
032: *
033: * <p>
034: * This layout is designed to work with containers with an explicit size and
035: * will not render properly without a size.
036: * </p>
037: */
038: public class RowLayout extends Layout {
039:
040: int type = Style.VERTICAL;
041: int margin = 0;
042: int spacing = 0;
043:
044: /**
045: * Creates a new vertical row layout.
046: */
047: public RowLayout() {
048: this (Style.VERTICAL);
049: }
050:
051: /**
052: * Constructs a new row layout given the type.
053: *
054: * @param type the type of row layout
055: */
056: public RowLayout(int type) {
057: this .type = type;
058: }
059:
060: /**
061: * Returns the margin.
062: *
063: * @return the margin
064: */
065: public int getMargin() {
066: return margin;
067: }
068:
069: /**
070: * Returns the spacing.
071: *
072: * @return the spacing in pixels
073: */
074: public int getSpacing() {
075: return spacing;
076: }
077:
078: /**
079: * Returns the type.
080: *
081: * @return the type
082: */
083: public int getType() {
084: return type;
085: }
086:
087: /**
088: * Sets the number of pixels of margin that will be placed along the edges of
089: * the layout. The default value is 0.
090: *
091: * @param margin the margin
092: */
093: public void setMargin(int margin) {
094: this .margin = margin;
095: }
096:
097: /**
098: * Sets the amount of space between widgets.
099: *
100: * @param spacing the spacing value
101: */
102: public void setSpacing(int spacing) {
103: this .spacing = spacing;
104: }
105:
106: /**
107: * Sets whether the layout places controls in rows or columns. The default
108: * value is VERTICAL.
109: *
110: * Valid values are:
111: * <ul>
112: * <li>HORIZONTAL: Position the controls horizontally from left to right</li>
113: * <li>VERTICAL: Position the controls vertically from top to bottom</li>
114: * </ul>
115: *
116: * @param type the type
117: */
118: public void setType(int type) {
119: this .type = type;
120: }
121:
122: protected void onLayout(WidgetContainer container, Element target) {
123: super .onLayout(container, target);
124:
125: WidgetContainer wc = (WidgetContainer) container;
126: Rectangle rect = MyDOM.getBounds(target, true);
127:
128: int size = container.getWidgetCount();
129:
130: int height = rect.height - (2 * margin);
131: int width = rect.width - (2 * margin);
132: int top = rect.y += margin;
133: int left = rect.x += margin;
134: left -= MyDOM.getScrollLeft(target);
135: top -= MyDOM.getScrollTop(target);
136:
137: // adjust for spacing
138: if (type == Style.HORIZONTAL) {
139: width -= ((size - 1) * spacing);
140: } else {
141: height -= ((size - 1) * spacing);
142: }
143:
144: int fillHeight = height;
145: int fillWidth = width;
146:
147: int fillingHeight = 0;
148: int fillingWidth = 0;
149:
150: // 1st pass
151: for (int i = 0; i < size; i++) {
152: Widget widget = container.getWidget(i);
153: if (!widget.isVisible())
154: continue;
155:
156: MyDOM.makePositionable(widget.getElement(), true);
157:
158: RowData data = (RowData) wc.getLayoutData(widget);
159: if (data == null) {
160: data = new RowData();
161: wc.setLayoutData(widget, data);
162: }
163:
164: if (type == Style.HORIZONTAL) {
165: if (data.fillWidth) {
166: fillingWidth++;
167: } else if (data.width != Style.DEFAULT) {
168: fillWidth -= data.width;
169: data.calcWidth = data.width;
170: } else {
171: int flowWidth = widget.getOffsetWidth();
172: fillWidth -= flowWidth;
173: data.calcWidth = flowWidth;
174: }
175: if (data.fillHeight) {
176: data.calcHeight = height;
177: } else if (data.height != Style.DEFAULT) {
178: data.calcHeight = data.height;
179: } else {
180: data.calcHeight = widget.getOffsetHeight();
181: }
182: } else {
183: if (data.fillHeight) {
184: fillingHeight++;
185: } else if (data.height != Style.DEFAULT) {
186: fillHeight -= data.height;
187: data.calcHeight = data.height;
188: } else {
189: int flowHeight = widget.getOffsetHeight();
190: fillHeight -= flowHeight;
191: data.calcHeight = flowHeight;
192: }
193: if (data.fillWidth) {
194: data.calcWidth = width;
195: } else if (data.width != Style.DEFAULT) {
196: data.calcWidth = data.width;
197: } else {
198: data.calcWidth = widget.getOffsetWidth();
199: }
200: }
201:
202: }
203:
204: // 2nd pass
205: for (int i = 0; i < size; i++) {
206: Widget widget = (Widget) container.getWidget(i);
207: if (!widget.isVisible())
208: continue;
209: RowData data = (RowData) wc.getLayoutData(widget);
210:
211: int w = (int) data.calcWidth;
212: int h = (int) data.calcHeight;
213:
214: if (type == Style.VERTICAL) {
215: if (data.fillHeight) {
216: h = fillHeight / fillingHeight;
217: }
218: } else {
219: if (data.fillWidth) {
220: w = fillWidth / fillingWidth;
221: }
222: }
223:
224: top = Math.max(0, top);
225:
226: // do not set size for normal flow
227: int fh = h;
228: int fw = w;
229: if (!data.fillHeight && data.height == Style.DEFAULT) {
230: fh = -1;
231: }
232: if (!data.fillWidth && data.width == Style.DEFAULT) {
233: fw = -1;
234: }
235:
236: setBounds(widget, left, top, fw, fh);
237:
238: if (type == Style.VERTICAL) {
239: top = top + h + spacing;
240: } else {
241: left = left + w + spacing;
242: }
243:
244: }
245: }
246:
247: }
|