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: *******************************************************************************/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 lay out the control children of a
018: * <code>Composite</code> in a grid.
019: * <p>
020: * <code>GridLayout</code> has a number of configuration fields, and the
021: * controls it lays out can have an associated layout data object, called
022: * <code>GridData</code>. The power of <code>GridLayout</code> lies in the
023: * ability to configure <code>GridData</code> for each control in the layout.
024: * </p>
025: * <p>
026: * The following code creates a shell managed by a <code>GridLayout</code>
027: * with 3 columns:
028: * <pre>
029: * Display display = new Display();
030: * Shell shell = new Shell(display);
031: * GridLayout gridLayout = new GridLayout();
032: * gridLayout.numColumns = 3;
033: * shell.setLayout(gridLayout);
034: * </pre>
035: * The <code>numColumns</code> field is the most important field in a
036: * <code>GridLayout</code>. Widgets are laid out in columns from left
037: * to right, and a new row is created when <code>numColumns</code> + 1
038: * controls are added to the <code>Composite<code>.
039: * </p>
040: *
041: * @see GridData
042: */
043: public final class GridLayout extends Layout {
044:
045: /**
046: * numColumns specifies the number of cell columns in the layout.
047: * If numColumns has a value less than 1, the layout will not
048: * set the size and position of any controls.
049: *
050: * The default value is 1.
051: */
052: public int numColumns = 1;
053:
054: /**
055: * makeColumnsEqualWidth specifies whether all columns in the layout
056: * will be forced to have the same width.
057: *
058: * The default value is false.
059: */
060: public boolean makeColumnsEqualWidth = false;
061:
062: /**
063: * marginWidth specifies the number of pixels of horizontal margin
064: * that will be placed along the left and right edges of the layout.
065: *
066: * The default value is 5.
067: */
068: public int marginWidth = 5;
069:
070: /**
071: * marginHeight specifies the number of pixels of vertical margin
072: * that will be placed along the top and bottom edges of the layout.
073: *
074: * The default value is 5.
075: */
076: public int marginHeight = 5;
077:
078: /**
079: * marginLeft specifies the number of pixels of horizontal margin
080: * that will be placed along the left edge of the layout.
081: *
082: * The default value is 0.
083: *
084: * @since 3.1
085: */
086: public int marginLeft = 0;
087:
088: /**
089: * marginTop specifies the number of pixels of vertical margin
090: * that will be placed along the top edge of the layout.
091: *
092: * The default value is 0.
093: *
094: * @since 3.1
095: */
096: public int marginTop = 0;
097:
098: /**
099: * marginRight specifies the number of pixels of horizontal margin
100: * that will be placed along the right edge of the layout.
101: *
102: * The default value is 0.
103: *
104: * @since 3.1
105: */
106: public int marginRight = 0;
107:
108: /**
109: * marginBottom specifies the number of pixels of vertical margin
110: * that will be placed along the bottom edge of the layout.
111: *
112: * The default value is 0.
113: *
114: * @since 3.1
115: */
116: public int marginBottom = 0;
117:
118: /**
119: * horizontalSpacing specifies the number of pixels between the right
120: * edge of one cell and the left edge of its neighbouring cell to
121: * the right.
122: *
123: * The default value is 5.
124: */
125: public int horizontalSpacing = 5;
126:
127: /**
128: * verticalSpacing specifies the number of pixels between the bottom
129: * edge of one cell and the top edge of its neighbouring cell underneath.
130: *
131: * The default value is 5.
132: */
133: public int verticalSpacing = 5;
134:
135: /**
136: * Constructs a new instance of this class.
137: */
138: public GridLayout() {
139: }
140:
141: /**
142: * Constructs a new instance of this class given the
143: * number of columns, and whether or not the columns
144: * should be forced to have the same width.
145: * If numColumns has a value less than 1, the layout will not
146: * set the size and position of any controls.
147: *
148: * @param numColumns the number of columns in the grid
149: * @param makeColumnsEqualWidth whether or not the columns will have equal width
150: *
151: * @since 2.0
152: */
153: public GridLayout(int numColumns, boolean makeColumnsEqualWidth) {
154: this .numColumns = numColumns;
155: this .makeColumnsEqualWidth = makeColumnsEqualWidth;
156: }
157:
158: protected Point computeSize(Composite composite, int wHint,
159: int hHint, boolean flushCache) {
160: Point size = layout(composite, false, 0, 0, wHint, hHint,
161: flushCache);
162: if (wHint != SWT.DEFAULT)
163: size.x = wHint;
164: if (hHint != SWT.DEFAULT)
165: size.y = hHint;
166: return size;
167: }
168:
169: protected boolean flushCache(Control control) {
170: Object data = control.getLayoutData();
171: if (data != null)
172: ((GridData) data).flushCache();
173: return true;
174: }
175:
176: GridData getData(Control[][] grid, int row, int column,
177: int rowCount, int columnCount, boolean first) {
178: Control control = grid[row][column];
179: if (control != null) {
180: GridData data = (GridData) control.getLayoutData();
181: int hSpan = Math.max(1, Math.min(data.horizontalSpan,
182: columnCount));
183: int vSpan = Math.max(1, data.verticalSpan);
184: int i = first ? row + vSpan - 1 : row - vSpan + 1;
185: int j = first ? column + hSpan - 1 : column - hSpan + 1;
186: if (0 <= i && i < rowCount) {
187: if (0 <= j && j < columnCount) {
188: if (control == grid[i][j])
189: return data;
190: }
191: }
192: }
193: return null;
194: }
195:
196: protected void layout(Composite composite, boolean flushCache) {
197: Rectangle rect = composite.getClientArea();
198: layout(composite, true, rect.x, rect.y, rect.width,
199: rect.height, flushCache);
200: }
201:
202: Point layout(Composite composite, boolean move, int x, int y,
203: int width, int height, boolean flushCache) {
204: if (numColumns < 1) {
205: return new Point(
206: marginLeft + marginWidth * 2 + marginRight,
207: marginTop + marginHeight * 2 + marginBottom);
208: }
209: Control[] children = composite.getChildren();
210: int count = 0;
211: for (int i = 0; i < children.length; i++) {
212: Control control = children[i];
213: GridData data = (GridData) control.getLayoutData();
214: if (data == null || !data.exclude) {
215: children[count++] = children[i];
216: }
217: }
218: if (count == 0) {
219: return new Point(
220: marginLeft + marginWidth * 2 + marginRight,
221: marginTop + marginHeight * 2 + marginBottom);
222: }
223: for (int i = 0; i < count; i++) {
224: Control child = children[i];
225: GridData data = (GridData) child.getLayoutData();
226: if (data == null)
227: child.setLayoutData(data = new GridData());
228: if (flushCache)
229: data.flushCache();
230: data.computeSize(child, data.widthHint, data.heightHint,
231: flushCache);
232: if (data.grabExcessHorizontalSpace && data.minimumWidth > 0) {
233: if (data.cacheWidth < data.minimumWidth) {
234: int trim = 0;
235: //TEMPORARY CODE
236: if (child instanceof Scrollable) {
237: Rectangle rect = ((Scrollable) child)
238: .computeTrim(0, 0, 0, 0);
239: trim = rect.width;
240: } else {
241: trim = child.getBorderWidth() * 2;
242: }
243: data.cacheWidth = data.cacheHeight = SWT.DEFAULT;
244: data.computeSize(child, Math.max(0,
245: data.minimumWidth - trim), data.heightHint,
246: false);
247: }
248: }
249: if (data.grabExcessVerticalSpace && data.minimumHeight > 0) {
250: data.cacheHeight = Math.max(data.cacheHeight,
251: data.minimumHeight);
252: }
253: }
254:
255: /* Build the grid */
256: int row = 0, column = 0, rowCount = 0, columnCount = numColumns;
257: Control[][] grid = new Control[4][columnCount];
258: for (int i = 0; i < count; i++) {
259: Control child = children[i];
260: GridData data = (GridData) child.getLayoutData();
261: int hSpan = Math.max(1, Math.min(data.horizontalSpan,
262: columnCount));
263: int vSpan = Math.max(1, data.verticalSpan);
264: while (true) {
265: int lastRow = row + vSpan;
266: if (lastRow >= grid.length) {
267: Control[][] newGrid = new Control[lastRow + 4][columnCount];
268: System.arraycopy(grid, 0, newGrid, 0, grid.length);
269: grid = newGrid;
270: }
271: if (grid[row] == null) {
272: grid[row] = new Control[columnCount];
273: }
274: while (column < columnCount
275: && grid[row][column] != null) {
276: column++;
277: }
278: int endCount = column + hSpan;
279: if (endCount <= columnCount) {
280: int index = column;
281: while (index < endCount && grid[row][index] == null) {
282: index++;
283: }
284: if (index == endCount)
285: break;
286: column = index;
287: }
288: if (column + hSpan >= columnCount) {
289: column = 0;
290: row++;
291: }
292: }
293: for (int j = 0; j < vSpan; j++) {
294: if (grid[row + j] == null) {
295: grid[row + j] = new Control[columnCount];
296: }
297: for (int k = 0; k < hSpan; k++) {
298: grid[row + j][column + k] = child;
299: }
300: }
301: rowCount = Math.max(rowCount, row + vSpan);
302: column += hSpan;
303: }
304:
305: /* Column widths */
306: int availableWidth = width - horizontalSpacing
307: * (columnCount - 1)
308: - (marginLeft + marginWidth * 2 + marginRight);
309: int expandCount = 0;
310: int[] widths = new int[columnCount];
311: int[] minWidths = new int[columnCount];
312: boolean[] expandColumn = new boolean[columnCount];
313: for (int j = 0; j < columnCount; j++) {
314: for (int i = 0; i < rowCount; i++) {
315: GridData data = getData(grid, i, j, rowCount,
316: columnCount, true);
317: if (data != null) {
318: int hSpan = Math.max(1, Math.min(
319: data.horizontalSpan, columnCount));
320: if (hSpan == 1) {
321: int w = data.cacheWidth + data.horizontalIndent;
322: widths[j] = Math.max(widths[j], w);
323: if (data.grabExcessHorizontalSpace) {
324: if (!expandColumn[j])
325: expandCount++;
326: expandColumn[j] = true;
327: }
328: if (!data.grabExcessHorizontalSpace
329: || data.minimumWidth != 0) {
330: w = !data.grabExcessHorizontalSpace
331: || data.minimumWidth == SWT.DEFAULT ? data.cacheWidth
332: : data.minimumWidth;
333: w += data.horizontalIndent;
334: minWidths[j] = Math.max(minWidths[j], w);
335: }
336: }
337: }
338: }
339: for (int i = 0; i < rowCount; i++) {
340: GridData data = getData(grid, i, j, rowCount,
341: columnCount, false);
342: if (data != null) {
343: int hSpan = Math.max(1, Math.min(
344: data.horizontalSpan, columnCount));
345: if (hSpan > 1) {
346: int spanWidth = 0, spanMinWidth = 0, spanExpandCount = 0;
347: for (int k = 0; k < hSpan; k++) {
348: spanWidth += widths[j - k];
349: spanMinWidth += minWidths[j - k];
350: if (expandColumn[j - k])
351: spanExpandCount++;
352: }
353: if (data.grabExcessHorizontalSpace
354: && spanExpandCount == 0) {
355: expandCount++;
356: expandColumn[j] = true;
357: }
358: int w = data.cacheWidth + data.horizontalIndent
359: - spanWidth - (hSpan - 1)
360: * horizontalSpacing;
361: if (w > 0) {
362: if (makeColumnsEqualWidth) {
363: int equalWidth = (w + spanWidth)
364: / hSpan;
365: int remainder = (w + spanWidth) % hSpan, last = -1;
366: for (int k = 0; k < hSpan; k++) {
367: widths[last = j - k] = Math.max(
368: equalWidth, widths[j - k]);
369: }
370: if (last > -1)
371: widths[last] += remainder;
372: } else {
373: if (spanExpandCount == 0) {
374: widths[j] += w;
375: } else {
376: int delta = w / spanExpandCount;
377: int remainder = w % spanExpandCount, last = -1;
378: for (int k = 0; k < hSpan; k++) {
379: if (expandColumn[j - k]) {
380: widths[last = j - k] += delta;
381: }
382: }
383: if (last > -1)
384: widths[last] += remainder;
385: }
386: }
387: }
388: if (!data.grabExcessHorizontalSpace
389: || data.minimumWidth != 0) {
390: w = !data.grabExcessHorizontalSpace
391: || data.minimumWidth == SWT.DEFAULT ? data.cacheWidth
392: : data.minimumWidth;
393: w += data.horizontalIndent - spanMinWidth
394: - (hSpan - 1) * horizontalSpacing;
395: if (w > 0) {
396: if (spanExpandCount == 0) {
397: minWidths[j] += w;
398: } else {
399: int delta = w / spanExpandCount;
400: int remainder = w % spanExpandCount, last = -1;
401: for (int k = 0; k < hSpan; k++) {
402: if (expandColumn[j - k]) {
403: minWidths[last = j - k] += delta;
404: }
405: }
406: if (last > -1)
407: minWidths[last] += remainder;
408: }
409: }
410: }
411: }
412: }
413: }
414: }
415: if (makeColumnsEqualWidth) {
416: int minColumnWidth = 0;
417: int columnWidth = 0;
418: for (int i = 0; i < columnCount; i++) {
419: minColumnWidth = Math.max(minColumnWidth, minWidths[i]);
420: columnWidth = Math.max(columnWidth, widths[i]);
421: }
422: columnWidth = width == SWT.DEFAULT || expandCount == 0 ? columnWidth
423: : Math.max(minColumnWidth, availableWidth
424: / columnCount);
425: for (int i = 0; i < columnCount; i++) {
426: expandColumn[i] = expandCount > 0;
427: widths[i] = columnWidth;
428: }
429: } else {
430: if (width != SWT.DEFAULT && expandCount > 0) {
431: int totalWidth = 0;
432: for (int i = 0; i < columnCount; i++) {
433: totalWidth += widths[i];
434: }
435: int c = expandCount;
436: int delta = (availableWidth - totalWidth) / c;
437: int remainder = (availableWidth - totalWidth) % c;
438: int last = -1;
439: while (totalWidth != availableWidth) {
440: for (int j = 0; j < columnCount; j++) {
441: if (expandColumn[j]) {
442: if (widths[j] + delta > minWidths[j]) {
443: widths[last = j] = widths[j] + delta;
444: } else {
445: widths[j] = minWidths[j];
446: expandColumn[j] = false;
447: c--;
448: }
449: }
450: }
451: if (last > -1)
452: widths[last] += remainder;
453:
454: for (int j = 0; j < columnCount; j++) {
455: for (int i = 0; i < rowCount; i++) {
456: GridData data = getData(grid, i, j,
457: rowCount, columnCount, false);
458: if (data != null) {
459: int hSpan = Math.max(1, Math.min(
460: data.horizontalSpan,
461: columnCount));
462: if (hSpan > 1) {
463: if (!data.grabExcessHorizontalSpace
464: || data.minimumWidth != 0) {
465: int spanWidth = 0, spanExpandCount = 0;
466: for (int k = 0; k < hSpan; k++) {
467: spanWidth += widths[j - k];
468: if (expandColumn[j - k])
469: spanExpandCount++;
470: }
471: int w = !data.grabExcessHorizontalSpace
472: || data.minimumWidth == SWT.DEFAULT ? data.cacheWidth
473: : data.minimumWidth;
474: w += data.horizontalIndent
475: - spanWidth
476: - (hSpan - 1)
477: * horizontalSpacing;
478: if (w > 0) {
479: if (spanExpandCount == 0) {
480: widths[j] += w;
481: } else {
482: int delta2 = w
483: / spanExpandCount;
484: int remainder2 = w
485: % spanExpandCount, last2 = -1;
486: for (int k = 0; k < hSpan; k++) {
487: if (expandColumn[j
488: - k]) {
489: widths[last2 = j
490: - k] += delta2;
491: }
492: }
493: if (last2 > -1)
494: widths[last2] += remainder2;
495: }
496: }
497: }
498: }
499: }
500: }
501: }
502: if (c == 0)
503: break;
504: totalWidth = 0;
505: for (int i = 0; i < columnCount; i++) {
506: totalWidth += widths[i];
507: }
508: delta = (availableWidth - totalWidth) / c;
509: remainder = (availableWidth - totalWidth) % c;
510: last = -1;
511: }
512: }
513: }
514:
515: /* Wrapping */
516: GridData[] flush = null;
517: int flushLength = 0;
518: if (width != SWT.DEFAULT) {
519: for (int j = 0; j < columnCount; j++) {
520: for (int i = 0; i < rowCount; i++) {
521: GridData data = getData(grid, i, j, rowCount,
522: columnCount, false);
523: if (data != null) {
524: if (data.heightHint == SWT.DEFAULT) {
525: Control child = grid[i][j];
526: //TEMPORARY CODE
527: int hSpan = Math.max(1, Math.min(
528: data.horizontalSpan, columnCount));
529: int currentWidth = 0;
530: for (int k = 0; k < hSpan; k++) {
531: currentWidth += widths[j - k];
532: }
533: currentWidth += (hSpan - 1)
534: * horizontalSpacing
535: - data.horizontalIndent;
536: if ((currentWidth != data.cacheWidth && data.horizontalAlignment == SWT.FILL)
537: || (data.cacheWidth > currentWidth)) {
538: int trim = 0;
539: if (child instanceof Scrollable) {
540: Rectangle rect = ((Scrollable) child)
541: .computeTrim(0, 0, 0, 0);
542: trim = rect.width;
543: } else {
544: trim = child.getBorderWidth() * 2;
545: }
546: data.cacheWidth = data.cacheHeight = SWT.DEFAULT;
547: data.computeSize(child, Math.max(0,
548: currentWidth - trim),
549: data.heightHint, false);
550: if (data.grabExcessVerticalSpace
551: && data.minimumHeight > 0) {
552: data.cacheHeight = Math.max(
553: data.cacheHeight,
554: data.minimumHeight);
555: }
556: if (flush == null)
557: flush = new GridData[count];
558: flush[flushLength++] = data;
559: }
560: }
561: }
562: }
563: }
564: }
565:
566: /* Row heights */
567: int availableHeight = height - verticalSpacing * (rowCount - 1)
568: - (marginTop + marginHeight * 2 + marginBottom);
569: expandCount = 0;
570: int[] heights = new int[rowCount];
571: int[] minHeights = new int[rowCount];
572: boolean[] expandRow = new boolean[rowCount];
573: for (int i = 0; i < rowCount; i++) {
574: for (int j = 0; j < columnCount; j++) {
575: GridData data = getData(grid, i, j, rowCount,
576: columnCount, true);
577: if (data != null) {
578: int vSpan = Math.max(1, Math.min(data.verticalSpan,
579: rowCount));
580: if (vSpan == 1) {
581: int h = data.cacheHeight + data.verticalIndent;
582: heights[i] = Math.max(heights[i], h);
583: if (data.grabExcessVerticalSpace) {
584: if (!expandRow[i])
585: expandCount++;
586: expandRow[i] = true;
587: }
588: if (!data.grabExcessVerticalSpace
589: || data.minimumHeight != 0) {
590: h = !data.grabExcessVerticalSpace
591: || data.minimumHeight == SWT.DEFAULT ? data.cacheHeight
592: : data.minimumHeight;
593: h += data.verticalIndent;
594: minHeights[i] = Math.max(minHeights[i], h);
595: }
596: }
597: }
598: }
599: for (int j = 0; j < columnCount; j++) {
600: GridData data = getData(grid, i, j, rowCount,
601: columnCount, false);
602: if (data != null) {
603: int vSpan = Math.max(1, Math.min(data.verticalSpan,
604: rowCount));
605: if (vSpan > 1) {
606: int spanHeight = 0, spanMinHeight = 0, spanExpandCount = 0;
607: for (int k = 0; k < vSpan; k++) {
608: spanHeight += heights[i - k];
609: spanMinHeight += minHeights[i - k];
610: if (expandRow[i - k])
611: spanExpandCount++;
612: }
613: if (data.grabExcessVerticalSpace
614: && spanExpandCount == 0) {
615: expandCount++;
616: expandRow[i] = true;
617: }
618: int h = data.cacheHeight + data.verticalIndent
619: - spanHeight - (vSpan - 1)
620: * verticalSpacing;
621: if (h > 0) {
622: if (spanExpandCount == 0) {
623: heights[i] += h;
624: } else {
625: int delta = h / spanExpandCount;
626: int remainder = h % spanExpandCount, last = -1;
627: for (int k = 0; k < vSpan; k++) {
628: if (expandRow[i - k]) {
629: heights[last = i - k] += delta;
630: }
631: }
632: if (last > -1)
633: heights[last] += remainder;
634: }
635: }
636: if (!data.grabExcessVerticalSpace
637: || data.minimumHeight != 0) {
638: h = !data.grabExcessVerticalSpace
639: || data.minimumHeight == SWT.DEFAULT ? data.cacheHeight
640: : data.minimumHeight;
641: h += data.verticalIndent - spanMinHeight
642: - (vSpan - 1) * verticalSpacing;
643: if (h > 0) {
644: if (spanExpandCount == 0) {
645: minHeights[i] += h;
646: } else {
647: int delta = h / spanExpandCount;
648: int remainder = h % spanExpandCount, last = -1;
649: for (int k = 0; k < vSpan; k++) {
650: if (expandRow[i - k]) {
651: minHeights[last = i - k] += delta;
652: }
653: }
654: if (last > -1)
655: minHeights[last] += remainder;
656: }
657: }
658: }
659: }
660: }
661: }
662: }
663: if (height != SWT.DEFAULT && expandCount > 0) {
664: int totalHeight = 0;
665: for (int i = 0; i < rowCount; i++) {
666: totalHeight += heights[i];
667: }
668: int c = expandCount;
669: int delta = (availableHeight - totalHeight) / c;
670: int remainder = (availableHeight - totalHeight) % c;
671: int last = -1;
672: while (totalHeight != availableHeight) {
673: for (int i = 0; i < rowCount; i++) {
674: if (expandRow[i]) {
675: if (heights[i] + delta > minHeights[i]) {
676: heights[last = i] = heights[i] + delta;
677: } else {
678: heights[i] = minHeights[i];
679: expandRow[i] = false;
680: c--;
681: }
682: }
683: }
684: if (last > -1)
685: heights[last] += remainder;
686:
687: for (int i = 0; i < rowCount; i++) {
688: for (int j = 0; j < columnCount; j++) {
689: GridData data = getData(grid, i, j, rowCount,
690: columnCount, false);
691: if (data != null) {
692: int vSpan = Math.max(1, Math.min(
693: data.verticalSpan, rowCount));
694: if (vSpan > 1) {
695: if (!data.grabExcessVerticalSpace
696: || data.minimumHeight != 0) {
697: int spanHeight = 0, spanExpandCount = 0;
698: for (int k = 0; k < vSpan; k++) {
699: spanHeight += heights[i - k];
700: if (expandRow[i - k])
701: spanExpandCount++;
702: }
703: int h = !data.grabExcessVerticalSpace
704: || data.minimumHeight == SWT.DEFAULT ? data.cacheHeight
705: : data.minimumHeight;
706: h += data.verticalIndent
707: - spanHeight - (vSpan - 1)
708: * verticalSpacing;
709: if (h > 0) {
710: if (spanExpandCount == 0) {
711: heights[i] += h;
712: } else {
713: int delta2 = h
714: / spanExpandCount;
715: int remainder2 = h
716: % spanExpandCount, last2 = -1;
717: for (int k = 0; k < vSpan; k++) {
718: if (expandRow[i - k]) {
719: heights[last2 = i
720: - k] += delta2;
721: }
722: }
723: if (last2 > -1)
724: heights[last2] += remainder2;
725: }
726: }
727: }
728: }
729: }
730: }
731: }
732: if (c == 0)
733: break;
734: totalHeight = 0;
735: for (int i = 0; i < rowCount; i++) {
736: totalHeight += heights[i];
737: }
738: delta = (availableHeight - totalHeight) / c;
739: remainder = (availableHeight - totalHeight) % c;
740: last = -1;
741: }
742: }
743:
744: /* Position the controls */
745: if (move) {
746: int gridY = y + marginTop + marginHeight;
747: for (int i = 0; i < rowCount; i++) {
748: int gridX = x + marginLeft + marginWidth;
749: for (int j = 0; j < columnCount; j++) {
750: GridData data = getData(grid, i, j, rowCount,
751: columnCount, true);
752: if (data != null) {
753: int hSpan = Math.max(1, Math.min(
754: data.horizontalSpan, columnCount));
755: int vSpan = Math.max(1, data.verticalSpan);
756: int cellWidth = 0, cellHeight = 0;
757: for (int k = 0; k < hSpan; k++) {
758: cellWidth += widths[j + k];
759: }
760: for (int k = 0; k < vSpan; k++) {
761: cellHeight += heights[i + k];
762: }
763: cellWidth += horizontalSpacing * (hSpan - 1);
764: int childX = gridX + data.horizontalIndent;
765: int childWidth = Math.min(data.cacheWidth,
766: cellWidth);
767: switch (data.horizontalAlignment) {
768: case SWT.CENTER:
769: case GridData.CENTER:
770: childX += Math
771: .max(
772: 0,
773: (cellWidth
774: - data.horizontalIndent - childWidth) / 2);
775: break;
776: case SWT.RIGHT:
777: case SWT.END:
778: case GridData.END:
779: childX += Math.max(0, cellWidth
780: - data.horizontalIndent
781: - childWidth);
782: break;
783: case SWT.FILL:
784: childWidth = cellWidth
785: - data.horizontalIndent;
786: break;
787: }
788: cellHeight += verticalSpacing * (vSpan - 1);
789: int childY = gridY + data.verticalIndent;
790: int childHeight = Math.min(data.cacheHeight,
791: cellHeight);
792: switch (data.verticalAlignment) {
793: case SWT.CENTER:
794: case GridData.CENTER:
795: childY += Math
796: .max(
797: 0,
798: (cellHeight
799: - data.verticalIndent - childHeight) / 2);
800: break;
801: case SWT.BOTTOM:
802: case SWT.END:
803: case GridData.END:
804: childY += Math
805: .max(0, cellHeight
806: - data.verticalIndent
807: - childHeight);
808: break;
809: case SWT.FILL:
810: childHeight = cellHeight
811: - data.verticalIndent;
812: break;
813: }
814: Control child = grid[i][j];
815: if (child != null) {
816: child.setBounds(childX, childY, childWidth,
817: childHeight);
818: }
819: }
820: gridX += widths[j] + horizontalSpacing;
821: }
822: gridY += heights[i] + verticalSpacing;
823: }
824: }
825:
826: // clean up cache
827: for (int i = 0; i < flushLength; i++) {
828: flush[i].cacheWidth = flush[i].cacheHeight = -1;
829: }
830:
831: int totalDefaultWidth = 0;
832: int totalDefaultHeight = 0;
833: for (int i = 0; i < columnCount; i++) {
834: totalDefaultWidth += widths[i];
835: }
836: for (int i = 0; i < rowCount; i++) {
837: totalDefaultHeight += heights[i];
838: }
839: totalDefaultWidth += horizontalSpacing * (columnCount - 1)
840: + marginLeft + marginWidth * 2 + marginRight;
841: totalDefaultHeight += verticalSpacing * (rowCount - 1)
842: + marginTop + marginHeight * 2 + marginBottom;
843: return new Point(totalDefaultWidth, totalDefaultHeight);
844: }
845:
846: String getName() {
847: String string = getClass().getName();
848: int index = string.lastIndexOf('.');
849: if (index == -1)
850: return string;
851: return string.substring(index + 1, string.length());
852: }
853:
854: /**
855: * Returns a string containing a concise, human-readable
856: * description of the receiver.
857: *
858: * @return a string representation of the layout
859: */
860: public String toString() {
861: String string = getName() + " {";
862: if (numColumns != 1)
863: string += "numColumns=" + numColumns + " ";
864: if (makeColumnsEqualWidth)
865: string += "makeColumnsEqualWidth=" + makeColumnsEqualWidth
866: + " ";
867: if (marginWidth != 0)
868: string += "marginWidth=" + marginWidth + " ";
869: if (marginHeight != 0)
870: string += "marginHeight=" + marginHeight + " ";
871: if (marginLeft != 0)
872: string += "marginLeft=" + marginLeft + " ";
873: if (marginRight != 0)
874: string += "marginRight=" + marginRight + " ";
875: if (marginTop != 0)
876: string += "marginTop=" + marginTop + " ";
877: if (marginBottom != 0)
878: string += "marginBottom=" + marginBottom + " ";
879: if (horizontalSpacing != 0)
880: string += "horizontalSpacing=" + horizontalSpacing + " ";
881: if (verticalSpacing != 0)
882: string += "verticalSpacing=" + verticalSpacing + " ";
883: string = string.trim();
884: string += "}";
885: return string;
886: }
887: }
|