001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 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: *******************************************************************************/package org.eclipse.swt.layout;
011:
012: import org.eclipse.swt.*;
013: import org.eclipse.swt.graphics.*;
014: import org.eclipse.swt.widgets.*;
015:
016: /**
017: * Instances of this class are used to define the attachments
018: * of a control in a <code>FormLayout</code>.
019: * <p>
020: * To set a <code>FormData</code> object into a control, you use the
021: * <code>setLayoutData ()</code> method. To define attachments for the
022: * <code>FormData</code>, set the fields directly, like this:
023: * <pre>
024: * FormData data = new FormData();
025: * data.left = new FormAttachment(0,5);
026: * data.right = new FormAttachment(100,-5);
027: * button.setLayoutData(formData);
028: * </pre>
029: * </p>
030: * <p>
031: * <code>FormData</code> contains the <code>FormAttachments</code> for
032: * each edge of the control that the <code>FormLayout</code> uses to
033: * determine the size and position of the control. <code>FormData</code>
034: * objects also allow you to set the width and height of controls within
035: * a <code>FormLayout</code>.
036: * </p>
037: *
038: * @see FormLayout
039: * @see FormAttachment
040: *
041: * @since 2.0
042: */
043: public final class FormData {
044: /**
045: * width specifies the preferred width in pixels. This value
046: * is the wHint passed into Control.computeSize(int, int, boolean)
047: * to determine the preferred size of the control.
048: *
049: * The default value is SWT.DEFAULT.
050: *
051: * @see Control#computeSize(int, int, boolean)
052: */
053: public int width = SWT.DEFAULT;
054: /**
055: * height specifies the preferred height in pixels. This value
056: * is the hHint passed into Control.computeSize(int, int, boolean)
057: * to determine the preferred size of the control.
058: *
059: * The default value is SWT.DEFAULT.
060: *
061: * @see Control#computeSize(int, int, boolean)
062: */
063: public int height = SWT.DEFAULT;
064: /**
065: * left specifies the attachment of the left side of
066: * the control.
067: */
068: public FormAttachment left;
069: /**
070: * right specifies the attachment of the right side of
071: * the control.
072: */
073: public FormAttachment right;
074: /**
075: * top specifies the attachment of the top of the control.
076: */
077: public FormAttachment top;
078: /**
079: * bottom specifies the attachment of the bottom of the
080: * control.
081: */
082: public FormAttachment bottom;
083:
084: int cacheWidth = -1, cacheHeight = -1;
085: int defaultWhint, defaultHhint, defaultWidth = -1,
086: defaultHeight = -1;
087: int currentWhint, currentHhint, currentWidth = -1,
088: currentHeight = -1;
089: FormAttachment cacheLeft, cacheRight, cacheTop, cacheBottom;
090: boolean isVisited, needed;
091:
092: /**
093: * Constructs a new instance of FormData using
094: * default values.
095: */
096: public FormData() {
097: }
098:
099: /**
100: * Constructs a new instance of FormData according to the parameters.
101: * A value of SWT.DEFAULT indicates that no minimum width or
102: * no minimum height is specified.
103: *
104: * @param width a minimum width for the control
105: * @param height a minimum height for the control
106: */
107: public FormData(int width, int height) {
108: this .width = width;
109: this .height = height;
110: }
111:
112: void computeSize(Control control, int wHint, int hHint,
113: boolean flushCache) {
114: if (cacheWidth != -1 && cacheHeight != -1)
115: return;
116: if (wHint == this .width && hHint == this .height) {
117: if (defaultWidth == -1 || defaultHeight == -1
118: || wHint != defaultWhint || hHint != defaultHhint) {
119: Point size = control.computeSize(wHint, hHint,
120: flushCache);
121: defaultWhint = wHint;
122: defaultHhint = hHint;
123: defaultWidth = size.x;
124: defaultHeight = size.y;
125: }
126: cacheWidth = defaultWidth;
127: cacheHeight = defaultHeight;
128: return;
129: }
130: if (currentWidth == -1 || currentHeight == -1
131: || wHint != currentWhint || hHint != currentHhint) {
132: Point size = control.computeSize(wHint, hHint, flushCache);
133: currentWhint = wHint;
134: currentHhint = hHint;
135: currentWidth = size.x;
136: currentHeight = size.y;
137: }
138: cacheWidth = currentWidth;
139: cacheHeight = currentHeight;
140: }
141:
142: void flushCache() {
143: cacheWidth = cacheHeight = -1;
144: defaultHeight = defaultWidth = -1;
145: currentHeight = currentWidth = -1;
146: }
147:
148: int getWidth(Control control, boolean flushCache) {
149: needed = true;
150: computeSize(control, width, height, flushCache);
151: return cacheWidth;
152: }
153:
154: int getHeight(Control control, boolean flushCache) {
155: computeSize(control, width, height, flushCache);
156: return cacheHeight;
157: }
158:
159: FormAttachment getBottomAttachment(Control control, int spacing,
160: boolean flushCache) {
161: if (cacheBottom != null)
162: return cacheBottom;
163: if (isVisited)
164: return cacheBottom = new FormAttachment(0, getHeight(
165: control, flushCache));
166: if (bottom == null) {
167: if (top == null)
168: return cacheBottom = new FormAttachment(0, getHeight(
169: control, flushCache));
170: return cacheBottom = getTopAttachment(control, spacing,
171: flushCache).plus(getHeight(control, flushCache));
172: }
173: Control bottomControl = bottom.control;
174: if (bottomControl != null) {
175: if (bottomControl.isDisposed()) {
176: bottom.control = bottomControl = null;
177: } else {
178: if (bottomControl.getParent() != control.getParent()) {
179: bottomControl = null;
180: }
181: }
182: }
183: if (bottomControl == null)
184: return cacheBottom = bottom;
185: isVisited = true;
186: FormData bottomData = (FormData) bottomControl.getLayoutData();
187: FormAttachment bottomAttachment = bottomData
188: .getBottomAttachment(bottomControl, spacing, flushCache);
189: switch (bottom.alignment) {
190: case SWT.BOTTOM:
191: cacheBottom = bottomAttachment.plus(bottom.offset);
192: break;
193: case SWT.CENTER: {
194: FormAttachment topAttachment = bottomData.getTopAttachment(
195: bottomControl, spacing, flushCache);
196: FormAttachment bottomHeight = bottomAttachment
197: .minus(topAttachment);
198: cacheBottom = bottomAttachment.minus(bottomHeight.minus(
199: getHeight(control, flushCache)).divide(2));
200: break;
201: }
202: default: {
203: FormAttachment topAttachment = bottomData.getTopAttachment(
204: bottomControl, spacing, flushCache);
205: cacheBottom = topAttachment.plus(bottom.offset - spacing);
206: break;
207: }
208: }
209: isVisited = false;
210: return cacheBottom;
211: }
212:
213: FormAttachment getLeftAttachment(Control control, int spacing,
214: boolean flushCache) {
215: if (cacheLeft != null)
216: return cacheLeft;
217: if (isVisited)
218: return cacheLeft = new FormAttachment(0, 0);
219: if (left == null) {
220: if (right == null)
221: return cacheLeft = new FormAttachment(0, 0);
222: return cacheLeft = getRightAttachment(control, spacing,
223: flushCache).minus(getWidth(control, flushCache));
224: }
225: Control leftControl = left.control;
226: if (leftControl != null) {
227: if (leftControl.isDisposed()) {
228: left.control = leftControl = null;
229: } else {
230: if (leftControl.getParent() != control.getParent()) {
231: leftControl = null;
232: }
233: }
234: }
235: if (leftControl == null)
236: return cacheLeft = left;
237: isVisited = true;
238: FormData leftData = (FormData) leftControl.getLayoutData();
239: FormAttachment leftAttachment = leftData.getLeftAttachment(
240: leftControl, spacing, flushCache);
241: switch (left.alignment) {
242: case SWT.LEFT:
243: cacheLeft = leftAttachment.plus(left.offset);
244: break;
245: case SWT.CENTER: {
246: FormAttachment rightAttachment = leftData
247: .getRightAttachment(leftControl, spacing,
248: flushCache);
249: FormAttachment leftWidth = rightAttachment
250: .minus(leftAttachment);
251: cacheLeft = leftAttachment.plus(leftWidth.minus(
252: getWidth(control, flushCache)).divide(2));
253: break;
254: }
255: default: {
256: FormAttachment rightAttachment = leftData
257: .getRightAttachment(leftControl, spacing,
258: flushCache);
259: cacheLeft = rightAttachment.plus(left.offset + spacing);
260: }
261: }
262: isVisited = false;
263: return cacheLeft;
264: }
265:
266: String getName() {
267: String string = getClass().getName();
268: int index = string.lastIndexOf('.');
269: if (index == -1)
270: return string;
271: return string.substring(index + 1, string.length());
272: }
273:
274: FormAttachment getRightAttachment(Control control, int spacing,
275: boolean flushCache) {
276: if (cacheRight != null)
277: return cacheRight;
278: if (isVisited)
279: return cacheRight = new FormAttachment(0, getWidth(control,
280: flushCache));
281: if (right == null) {
282: if (left == null)
283: return cacheRight = new FormAttachment(0, getWidth(
284: control, flushCache));
285: return cacheRight = getLeftAttachment(control, spacing,
286: flushCache).plus(getWidth(control, flushCache));
287: }
288: Control rightControl = right.control;
289: if (rightControl != null) {
290: if (rightControl.isDisposed()) {
291: right.control = rightControl = null;
292: } else {
293: if (rightControl.getParent() != control.getParent()) {
294: rightControl = null;
295: }
296: }
297: }
298: if (rightControl == null)
299: return cacheRight = right;
300: isVisited = true;
301: FormData rightData = (FormData) rightControl.getLayoutData();
302: FormAttachment rightAttachment = rightData.getRightAttachment(
303: rightControl, spacing, flushCache);
304: switch (right.alignment) {
305: case SWT.RIGHT:
306: cacheRight = rightAttachment.plus(right.offset);
307: break;
308: case SWT.CENTER: {
309: FormAttachment leftAttachment = rightData
310: .getLeftAttachment(rightControl, spacing,
311: flushCache);
312: FormAttachment rightWidth = rightAttachment
313: .minus(leftAttachment);
314: cacheRight = rightAttachment.minus(rightWidth.minus(
315: getWidth(control, flushCache)).divide(2));
316: break;
317: }
318: default: {
319: FormAttachment leftAttachment = rightData
320: .getLeftAttachment(rightControl, spacing,
321: flushCache);
322: cacheRight = leftAttachment.plus(right.offset - spacing);
323: break;
324: }
325: }
326: isVisited = false;
327: return cacheRight;
328: }
329:
330: FormAttachment getTopAttachment(Control control, int spacing,
331: boolean flushCache) {
332: if (cacheTop != null)
333: return cacheTop;
334: if (isVisited)
335: return cacheTop = new FormAttachment(0, 0);
336: if (top == null) {
337: if (bottom == null)
338: return cacheTop = new FormAttachment(0, 0);
339: return cacheTop = getBottomAttachment(control, spacing,
340: flushCache).minus(getHeight(control, flushCache));
341: }
342: Control topControl = top.control;
343: if (topControl != null) {
344: if (topControl.isDisposed()) {
345: top.control = topControl = null;
346: } else {
347: if (topControl.getParent() != control.getParent()) {
348: topControl = null;
349: }
350: }
351: }
352: if (topControl == null)
353: return cacheTop = top;
354: isVisited = true;
355: FormData topData = (FormData) topControl.getLayoutData();
356: FormAttachment topAttachment = topData.getTopAttachment(
357: topControl, spacing, flushCache);
358: switch (top.alignment) {
359: case SWT.TOP:
360: cacheTop = topAttachment.plus(top.offset);
361: break;
362: case SWT.CENTER: {
363: FormAttachment bottomAttachment = topData
364: .getBottomAttachment(topControl, spacing,
365: flushCache);
366: FormAttachment topHeight = bottomAttachment
367: .minus(topAttachment);
368: cacheTop = topAttachment.plus(topHeight.minus(
369: getHeight(control, flushCache)).divide(2));
370: break;
371: }
372: default: {
373: FormAttachment bottomAttachment = topData
374: .getBottomAttachment(topControl, spacing,
375: flushCache);
376: cacheTop = bottomAttachment.plus(top.offset + spacing);
377: break;
378: }
379: }
380: isVisited = false;
381: return cacheTop;
382: }
383:
384: /**
385: * Returns a string containing a concise, human-readable
386: * description of the receiver.
387: *
388: * @return a string representation of the FormData object
389: */
390: public String toString() {
391: String string = getName() + " {";
392: if (width != SWT.DEFAULT)
393: string += "width=" + width + " ";
394: if (height != SWT.DEFAULT)
395: string += "height=" + height + " ";
396: if (left != null)
397: string += "left=" + left + " ";
398: if (right != null)
399: string += "right=" + right + " ";
400: if (top != null)
401: string += "top=" + top + " ";
402: if (bottom != null)
403: string += "bottom=" + bottom + " ";
404: string = string.trim();
405: string += "}";
406: return string;
407: }
408:
409: }
|