KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > forms > widgets > TableWrapLayout


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.ui.forms.widgets;
12
13 import java.util.Enumeration JavaDoc;
14 import java.util.Hashtable JavaDoc;
15 import java.util.Vector JavaDoc;
16
17 import org.eclipse.swt.SWT;
18 import org.eclipse.swt.graphics.*;
19 import org.eclipse.swt.widgets.*;
20
21 /**
22  * This implementation of the layout algorithm attempts to position controls in
23  * the composite using a two-pass autolayout HTML table altorithm recommeded by
24  * HTML 4.01 W3C specification (see
25  * http://www.w3.org/TR/html4/appendix/notes.html#h-B.5.2.2). The main
26  * differences with GridLayout is that it has two passes and that width and
27  * height are not calculated in the same pass.
28  * <p>
29  * The advantage of the algorithm over GridLayout is that it is capable of
30  * flowing text controls capable of line wrap. These controls do not have
31  * natural 'preferred size'. Instead, they are capable of providing the required
32  * height if the width is set. Consequently, this algorithm first calculates the
33  * widths that will be assigned to columns, and then passes those widths to the
34  * controls to calculate the height. When a composite with this layout is a
35  * child of the scrolling composite, they should interact in such a way that
36  * reduction in the scrolling composite width results in the reflow and increase
37  * of the overall height.
38  * <p>
39  * If none of the columns contain expandable and wrappable controls, the
40  * end-result will be similar to the one provided by GridLayout. The difference
41  * will show up for layouts that contain controls whose minimum and maximum
42  * widths are not the same.
43  *
44  * @see TableWrapData
45  * @since 3.0
46  */

47 public final class TableWrapLayout extends Layout implements ILayoutExtension {
48     /**
49      * Number of columns to use when positioning children (default is 1).
50      */

51     public int numColumns = 1;
52
53     /**
54      * Left margin variable (default is 5).
55      */

56     public int leftMargin = 5;
57
58     /**
59      * Right margin variable (default is 5).
60      */

61     public int rightMargin = 5;
62
63     /**
64      * Top margin variable (default is 5).
65      */

66     public int topMargin = 5;
67
68     /**
69      * Botom margin variable (default is 5).
70      */

71     public int bottomMargin = 5;
72
73     /**
74      * Horizontal spacing (default is 5).
75      */

76     public int horizontalSpacing = 5;
77
78     /**
79      * Vertical spacing (default is 5).
80      */

81     public int verticalSpacing = 5;
82
83     /**
84      * If set to <code>true</code>, all the columns will have the same width.
85      * Otherwise, column widths will be computed based on controls in them and
86      * their layout data (default is <code>false</code>).
87      */

88     public boolean makeColumnsEqualWidth = false;
89
90     private boolean initialLayout = true;
91
92     private Vector JavaDoc grid = null;
93
94     private Hashtable JavaDoc rowspans;
95
96     private int[] minColumnWidths, maxColumnWidths;
97
98     private int widestColumnWidth;
99
100     private int[] growingColumns;
101
102     private int[] growingRows;
103
104     private LayoutCache cache = new LayoutCache();
105
106     private class RowSpan {
107         Control child;
108
109         int row;
110
111         int column;
112
113         int height;
114
115         int totalHeight;
116
117         public RowSpan(Control child, int column, int row) {
118             this.child = child;
119             this.column = column;
120             this.row = row;
121         }
122
123         /*
124          * Updates this row span's height with the given one if it is within
125          * this span.
126          */

127         public void update(int currentRow, int rowHeight) {
128             TableWrapData td = (TableWrapData) child.getLayoutData();
129             // is currentRow within this span?
130
if (currentRow >= row && currentRow < row + td.rowspan) {
131                 totalHeight += rowHeight;
132                 if (currentRow > row)
133                     totalHeight += verticalSpacing;
134             }
135         }
136
137         public int getRequiredHeightIncrease() {
138             if (totalHeight < height)
139                 return height - totalHeight;
140             return 0;
141         }
142     }
143
144     /**
145      * Implements ILayoutExtension. Should not be called directly.
146      *
147      * @see ILayoutExtension
148      */

149     public int computeMinimumWidth(Composite parent, boolean changed) {
150
151         Control[] children = parent.getChildren();
152         if (changed) {
153             cache.flush();
154         }
155
156         cache.setControls(children);
157
158         changed = true;
159         initializeIfNeeded(parent, changed);
160         if (initialLayout) {
161             changed = true;
162             initialLayout = false;
163         }
164         if (grid == null || changed) {
165             changed = true;
166             grid = new Vector JavaDoc();
167             createGrid(parent);
168         }
169         if (minColumnWidths == null)
170             minColumnWidths = new int[numColumns];
171         for (int i = 0; i < numColumns; i++) {
172             minColumnWidths[i] = 0;
173         }
174         return internalGetMinimumWidth(parent, changed);
175     }
176
177     /**
178      * Implements ILayoutExtension. Should not be called directly.
179      *
180      * @see ILayoutExtension
181      */

182     public int computeMaximumWidth(Composite parent, boolean changed) {
183         Control[] children = parent.getChildren();
184         if (changed) {
185             cache.flush();
186         }
187
188         cache.setControls(children);
189
190         changed = true;
191         initializeIfNeeded(parent, changed);
192         if (initialLayout) {
193             changed = true;
194             initialLayout = false;
195         }
196         if (grid == null || changed) {
197             changed = true;
198             grid = new Vector JavaDoc();
199             createGrid(parent);
200         }
201         if (maxColumnWidths == null)
202             maxColumnWidths = new int[numColumns];
203         for (int i = 0; i < numColumns; i++) {
204             maxColumnWidths[i] = 0;
205         }
206         return internalGetMaximumWidth(parent, changed);
207     }
208
209     /**
210      * @see Layout#layout(Composite, boolean)
211      */

212     protected void layout(Composite parent, boolean changed) {
213
214         Rectangle clientArea = parent.getClientArea();
215         Control[] children = parent.getChildren();
216         if (changed) {
217             cache.flush();
218         }
219
220         if (children.length == 0)
221             return;
222
223         cache.setControls(children);
224
225         int parentWidth = clientArea.width;
226         changed = true;
227         initializeIfNeeded(parent, changed);
228         if (initialLayout) {
229             changed = true;
230             initialLayout = false;
231         }
232         if (grid == null || changed) {
233             changed = true;
234             grid = new Vector JavaDoc();
235             createGrid(parent);
236         }
237         resetColumnWidths();
238         int minWidth = internalGetMinimumWidth(parent, changed);
239         int maxWidth = internalGetMaximumWidth(parent, changed);
240         int tableWidth = parentWidth;
241         int[] columnWidths;
242         if (parentWidth <= minWidth) {
243             tableWidth = minWidth;
244             if (makeColumnsEqualWidth) {
245                 columnWidths = new int[numColumns];
246                 for (int i = 0; i < numColumns; i++) {
247                     columnWidths[i] = widestColumnWidth;
248                 }
249             } else
250                 columnWidths = minColumnWidths;
251         } else if (parentWidth > maxWidth) {
252             if (growingColumns.length == 0) {
253                 tableWidth = maxWidth;
254                 columnWidths = maxColumnWidths;
255             } else {
256                 columnWidths = new int[numColumns];
257                 int colSpace = tableWidth - leftMargin - rightMargin;
258                 colSpace -= (numColumns - 1) * horizontalSpacing;
259                 int extra = parentWidth - maxWidth;
260                 int colExtra = extra / growingColumns.length;
261                 for (int i = 0; i < numColumns; i++) {
262                     columnWidths[i] = maxColumnWidths[i];
263                     if (isGrowingColumn(i)) {
264                         columnWidths[i] += colExtra;
265                     }
266                 }
267             }
268         } else {
269             columnWidths = new int[numColumns];
270             if (makeColumnsEqualWidth) {
271                 int colSpace = tableWidth - leftMargin - rightMargin;
272                 colSpace -= (numColumns - 1) * horizontalSpacing;
273                 int col = colSpace / numColumns;
274                 for (int i = 0; i < numColumns; i++) {
275                     columnWidths[i] = col;
276                 }
277             } else {
278                 columnWidths = assignExtraSpace(tableWidth, maxWidth, minWidth);
279             }
280         }
281         int y = topMargin+clientArea.y;
282         int[] rowHeights = computeRowHeights(children, columnWidths, changed);
283         for (int i = 0; i < grid.size(); i++) {
284             int rowHeight = rowHeights[i];
285             int x = leftMargin+clientArea.x;
286             TableWrapData[] row = (TableWrapData[]) grid.elementAt(i);
287             for (int j = 0; j < numColumns; j++) {
288                 TableWrapData td = row[j];
289                 if (td.isItemData) {
290                     Control child = children[td.childIndex];
291                     placeControl(child, td, x, y, rowHeights, i);
292                 }
293                 x += columnWidths[j];
294                 if (j < numColumns - 1)
295                     x += horizontalSpacing;
296             }
297             y += rowHeight + verticalSpacing;
298         }
299     }
300
301     int[] computeRowHeights(Control[] children, int[] columnWidths,
302             boolean changed) {
303         int[] rowHeights = new int[grid.size()];
304         for (int i = 0; i < grid.size(); i++) {
305             TableWrapData[] row = (TableWrapData[]) grid.elementAt(i);
306             rowHeights[i] = 0;
307             for (int j = 0; j < numColumns; j++) {
308                 TableWrapData td = row[j];
309                 if (td.isItemData == false) {
310                     continue;
311                 }
312                 Control child = children[td.childIndex];
313                 int span = td.colspan;
314                 int cwidth = 0;
315                 for (int k = j; k < j + span; k++) {
316                     cwidth += columnWidths[k];
317                     if (k < j + span - 1)
318                         cwidth += horizontalSpacing;
319                 }
320                 Point size = computeSize(td.childIndex, cwidth, td.indent, td.maxWidth, td.maxHeight);
321                 td.compWidth = cwidth;
322                 if (td.heightHint != SWT.DEFAULT) {
323                     size = new Point(size.x, td.heightHint);
324                 }
325                 td.compSize = size;
326                 RowSpan rowspan = (RowSpan) rowspans.get(child);
327                 if (rowspan == null) {
328                     rowHeights[i] = Math.max(rowHeights[i], size.y);
329                 } else
330                     rowspan.height = size.y;
331             }
332             updateRowSpans(i, rowHeights[i]);
333         }
334         for (Enumeration JavaDoc enm = rowspans.elements(); enm.hasMoreElements();) {
335             RowSpan rowspan = (RowSpan) enm.nextElement();
336             int increase = rowspan.getRequiredHeightIncrease();
337             if (increase == 0)
338                 continue;
339             TableWrapData td = (TableWrapData) rowspan.child.getLayoutData();
340             int ngrowing = 0;
341             int[] affectedRows = new int[grid.size()];
342             for (int i = 0; i < growingRows.length; i++) {
343                 int growingRow = growingRows[i];
344                 if (growingRow >= rowspan.row
345                         && growingRow < rowspan.row + td.rowspan) {
346                     affectedRows[ngrowing++] = growingRow;
347                 }
348             }
349             if (ngrowing == 0) {
350                 ngrowing = 1;
351                 affectedRows[0] = rowspan.row + td.rowspan - 1;
352             }
353             increase += increase % ngrowing;
354             int perRowIncrease = increase / ngrowing;
355             for (int i = 0; i < ngrowing; i++) {
356                 int growingRow = affectedRows[i];
357                 rowHeights[growingRow] += perRowIncrease;
358             }
359         }
360         return rowHeights;
361     }
362
363     boolean isGrowingColumn(int col) {
364         if (growingColumns == null)
365             return false;
366         for (int i = 0; i < growingColumns.length; i++) {
367             if (col == growingColumns[i])
368                 return true;
369         }
370         return false;
371     }
372
373     int[] assignExtraSpace(int tableWidth, int maxWidth, int minWidth) {
374         int fixedPart = leftMargin + rightMargin + (numColumns - 1)
375                 * horizontalSpacing;
376         int D = maxWidth - minWidth;
377         int W = tableWidth - fixedPart - minWidth;
378         int widths[] = new int[numColumns];
379         int rem = 0;
380         for (int i = 0; i < numColumns; i++) {
381             int cmin = minColumnWidths[i];
382             int cmax = maxColumnWidths[i];
383             int d = cmax - cmin;
384             int extra = D != 0 ? (d * W) / D : 0;
385             if (i < numColumns - 1) {
386                 widths[i] = cmin + extra;
387                 rem += widths[i];
388             } else {
389                 widths[i] = tableWidth - fixedPart - rem;
390             }
391         }
392         return widths;
393     }
394
395     Point computeSize(int childIndex, int width, int indent, int maxWidth, int maxHeight) {
396         int widthArg = width - indent;
397         SizeCache controlCache = cache.getCache(childIndex);
398         if (!isWrap(controlCache.getControl()))
399             widthArg = SWT.DEFAULT;
400         Point size = controlCache.computeSize(widthArg, SWT.DEFAULT);
401         if (maxWidth!=SWT.DEFAULT)
402             size.x = Math.min(size.x, maxWidth);
403         if (maxHeight!=SWT.DEFAULT)
404             size.y = Math.min(size.y, maxHeight);
405         size.x += indent;
406         return size;
407     }
408
409     void placeControl(Control control, TableWrapData td, int x, int y,
410             int[] rowHeights, int row) {
411         int xloc = x + td.indent;
412         int yloc = y;
413         int height = td.compSize.y;
414         int colWidth = td.compWidth - td.indent;
415         int width = td.compSize.x-td.indent;
416         width = Math.min(width, colWidth);
417         int slotHeight = rowHeights[row];
418         RowSpan rowspan = (RowSpan) rowspans.get(control);
419         if (rowspan != null) {
420             slotHeight = 0;
421             for (int i = row; i < row + td.rowspan; i++) {
422                 if (i > row)
423                     slotHeight += verticalSpacing;
424                 slotHeight += rowHeights[i];
425             }
426         }
427         // align horizontally
428
if (td.align == TableWrapData.CENTER) {
429             xloc = x + colWidth / 2 - width / 2;
430         } else if (td.align == TableWrapData.RIGHT) {
431             xloc = x + colWidth - width;
432         } else if (td.align == TableWrapData.FILL) {
433             width = colWidth;
434         }
435         // align vertically
436
if (td.valign == TableWrapData.MIDDLE) {
437             yloc = y + slotHeight / 2 - height / 2;
438         } else if (td.valign == TableWrapData.BOTTOM) {
439             yloc = y + slotHeight - height;
440         } else if (td.valign == TableWrapData.FILL) {
441             height = slotHeight;
442         }
443         control.setBounds(xloc, yloc, width, height);
444     }
445
446     void createGrid(Composite composite) {
447         int row, column, rowFill, columnFill;
448         Control[] children;
449         TableWrapData spacerSpec;
450         Vector JavaDoc growingCols = new Vector JavaDoc();
451         Vector JavaDoc growingRows = new Vector JavaDoc();
452         rowspans = new Hashtable JavaDoc();
453         //
454
children = composite.getChildren();
455         if (children.length == 0)
456             return;
457         //
458
grid.addElement(createEmptyRow());
459         row = 0;
460         column = 0;
461         // Loop through the children and place their associated layout specs in
462
// the
463
// grid. Placement occurs left to right, top to bottom (i.e., by row).
464
for (int i = 0; i < children.length; i++) {
465             // Find the first available spot in the grid.
466
Control child = children[i];
467             TableWrapData spec = (TableWrapData) child.getLayoutData();
468             while (((TableWrapData[]) grid.elementAt(row))[column] != null) {
469                 column = column + 1;
470                 if (column >= numColumns) {
471                     row = row + 1;
472                     column = 0;
473                     if (row >= grid.size()) {
474                         grid.addElement(createEmptyRow());
475                     }
476                 }
477             }
478             // See if the place will support the widget's horizontal span. If
479
// not, go to the
480
// next row.
481
if (column + spec.colspan - 1 >= numColumns) {
482                 grid.addElement(createEmptyRow());
483                 row = row + 1;
484                 column = 0;
485             }
486             // The vertical span for the item will be at least 1. If it is > 1,
487
// add other rows to the grid.
488
if (spec.rowspan > 1) {
489                 rowspans.put(child, new RowSpan(child, column, row));
490             }
491             for (int j = 2; j <= spec.rowspan; j++) {
492                 if (row + j > grid.size()) {
493                     grid.addElement(createEmptyRow());
494                 }
495             }
496             // Store the layout spec. Also cache the childIndex. NOTE: That we
497
// assume the children of a
498
// composite are maintained in the order in which they are created
499
// and added to the composite.
500
((TableWrapData[]) grid.elementAt(row))[column] = spec;
501             spec.childIndex = i;
502             if (spec.grabHorizontal) {
503                 updateGrowingColumns(growingCols, spec, column);
504             }
505             if (spec.grabVertical) {
506                 updateGrowingRows(growingRows, spec, row);
507             }
508             // Put spacers in the grid to account for the item's vertical and
509
// horizontal
510
// span.
511
rowFill = spec.rowspan - 1;
512             columnFill = spec.colspan - 1;
513             for (int r = 1; r <= rowFill; r++) {
514                 for (int c = 0; c < spec.colspan; c++) {
515                     spacerSpec = new TableWrapData();
516                     spacerSpec.isItemData = false;
517                     ((TableWrapData[]) grid.elementAt(row + r))[column + c] = spacerSpec;
518                 }
519             }
520             for (int c = 1; c <= columnFill; c++) {
521                 for (int r = 0; r < spec.rowspan; r++) {
522                     spacerSpec = new TableWrapData();
523                     spacerSpec.isItemData = false;
524                     ((TableWrapData[]) grid.elementAt(row + r))[column + c] = spacerSpec;
525                 }
526             }
527             column = column + spec.colspan - 1;
528         }
529         // Fill out empty grid cells with spacers.
530
for (int k = column + 1; k < numColumns; k++) {
531             spacerSpec = new TableWrapData();
532             spacerSpec.isItemData = false;
533             ((TableWrapData[]) grid.elementAt(row))[k] = spacerSpec;
534         }
535         for (int k = row + 1; k < grid.size(); k++) {
536             spacerSpec = new TableWrapData();
537             spacerSpec.isItemData = false;
538             ((TableWrapData[]) grid.elementAt(k))[column] = spacerSpec;
539         }
540         growingColumns = new int[growingCols.size()];
541         for (int i = 0; i < growingCols.size(); i++) {
542             growingColumns[i] = ((Integer JavaDoc) growingCols.get(i)).intValue();
543         }
544         this.growingRows = new int[growingRows.size()];
545         for (int i = 0; i < growingRows.size(); i++) {
546             this.growingRows[i] = ((Integer JavaDoc) growingRows.get(i)).intValue();
547         }
548     }
549
550     private void updateGrowingColumns(Vector JavaDoc growingColumns,
551             TableWrapData spec, int column) {
552         int affectedColumn = column + spec.colspan - 1;
553         for (int i = 0; i < growingColumns.size(); i++) {
554             Integer JavaDoc col = (Integer JavaDoc) growingColumns.get(i);
555             if (col.intValue() == affectedColumn)
556                 return;
557         }
558         growingColumns.add(new Integer JavaDoc(affectedColumn));
559     }
560
561     private void updateGrowingRows(Vector JavaDoc growingRows, TableWrapData spec,
562             int row) {
563         int affectedRow = row + spec.rowspan - 1;
564         for (int i = 0; i < growingRows.size(); i++) {
565             Integer JavaDoc irow = (Integer JavaDoc) growingRows.get(i);
566             if (irow.intValue() == affectedRow)
567                 return;
568         }
569         growingRows.add(new Integer JavaDoc(affectedRow));
570     }
571
572     private TableWrapData[] createEmptyRow() {
573         TableWrapData[] row = new TableWrapData[numColumns];
574         for (int i = 0; i < numColumns; i++)
575             row[i] = null;
576         return row;
577     }
578
579     /**
580      * @see Layout#computeSize(Composite, int, int, boolean)
581      */

582     protected Point computeSize(Composite parent, int wHint, int hHint,
583             boolean changed) {
584         Control[] children = parent.getChildren();
585         if (changed) {
586             cache.flush();
587         }
588         if (children.length == 0) {
589             return new Point(0, 0);
590         }
591         cache.setControls(children);
592
593         int parentWidth = wHint;
594         changed = true;
595         initializeIfNeeded(parent, changed);
596         if (initialLayout) {
597             changed = true;
598             initialLayout = false;
599         }
600         if (grid == null || changed) {
601             changed = true;
602             grid = new Vector JavaDoc();
603             createGrid(parent);
604         }
605         resetColumnWidths();
606         int minWidth = internalGetMinimumWidth(parent, changed);
607         int maxWidth = internalGetMaximumWidth(parent, changed);
608         
609         if (wHint == SWT.DEFAULT)
610             parentWidth = maxWidth;
611         
612         int tableWidth = parentWidth;
613         int[] columnWidths;
614         if (parentWidth <= minWidth) {
615             tableWidth = minWidth;
616             if (makeColumnsEqualWidth) {
617                 columnWidths = new int[numColumns];
618                 for (int i = 0; i < numColumns; i++) {
619                     columnWidths[i] = widestColumnWidth;
620                 }
621             } else
622                 columnWidths = minColumnWidths;
623         } else if (parentWidth >= maxWidth) {
624             if (makeColumnsEqualWidth) {
625                 columnWidths = new int[numColumns];
626                 int colSpace = parentWidth - leftMargin - rightMargin;
627                 colSpace -= (numColumns - 1) * horizontalSpacing;
628                 int col = colSpace / numColumns;
629                 for (int i = 0; i < numColumns; i++) {
630                     columnWidths[i] = col;
631                 }
632             } else {
633                 tableWidth = maxWidth;
634                 columnWidths = maxColumnWidths;
635             }
636         } else {
637             columnWidths = new int[numColumns];
638             if (makeColumnsEqualWidth) {
639                 int colSpace = tableWidth - leftMargin - rightMargin;
640                 colSpace -= (numColumns - 1) * horizontalSpacing;
641                 int col = colSpace / numColumns;
642                 for (int i = 0; i < numColumns; i++) {
643                     columnWidths[i] = col;
644                 }
645             } else {
646                 columnWidths = assignExtraSpace(tableWidth, maxWidth, minWidth);
647             }
648         }
649         int totalHeight = 0;
650         int innerHeight = 0;
651         // compute widths
652
for (int i = 0; i < grid.size(); i++) {
653             TableWrapData[] row = (TableWrapData[]) grid.elementAt(i);
654             // assign widths, calculate heights
655
int rowHeight = 0;
656             for (int j = 0; j < numColumns; j++) {
657                 TableWrapData td = row[j];
658                 if (td.isItemData == false) {
659                     continue;
660                 }
661                 Control child = children[td.childIndex];
662                 int span = td.colspan;
663                 int cwidth = 0;
664                 for (int k = j; k < j + span; k++) {
665                     if (k > j)
666                         cwidth += horizontalSpacing;
667                     cwidth += columnWidths[k];
668                 }
669                 int cy = td.heightHint;
670                 if (cy == SWT.DEFAULT) {
671                     Point size = computeSize(td.childIndex, cwidth, td.indent, td.maxWidth, td.maxHeight);
672                     cy = size.y;
673                 }
674                 RowSpan rowspan = (RowSpan) rowspans.get(child);
675                 if (rowspan != null) {
676                     // don't take the height of this child into acount
677
// because it spans multiple rows
678
rowspan.height = cy;
679                 } else {
680                     rowHeight = Math.max(rowHeight, cy);
681                 }
682             }
683             updateRowSpans(i, rowHeight);
684             if (i > 0)
685                 innerHeight += verticalSpacing;
686             innerHeight += rowHeight;
687         }
688         if (!rowspans.isEmpty())
689             innerHeight = compensateForRowSpans(innerHeight);
690         totalHeight = topMargin + innerHeight + bottomMargin;
691         return new Point(tableWidth, totalHeight);
692     }
693
694     private void updateRowSpans(int row, int rowHeight) {
695         if (rowspans == null || rowspans.size() == 0)
696             return;
697         for (Enumeration JavaDoc enm = rowspans.elements(); enm.hasMoreElements();) {
698             RowSpan rowspan = (RowSpan) enm.nextElement();
699             rowspan.update(row, rowHeight);
700         }
701     }
702
703     private int compensateForRowSpans(int totalHeight) {
704         for (Enumeration JavaDoc enm = rowspans.elements(); enm.hasMoreElements();) {
705             RowSpan rowspan = (RowSpan) enm.nextElement();
706             totalHeight += rowspan.getRequiredHeightIncrease();
707         }
708         return totalHeight;
709     }
710
711     int internalGetMinimumWidth(Composite parent, boolean changed) {
712         if (changed)
713             //calculateMinimumColumnWidths(parent, true);
714
calculateColumnWidths(parent, minColumnWidths, false, true);
715         int minimumWidth = 0;
716         widestColumnWidth = 0;
717         if (makeColumnsEqualWidth) {
718             for (int i = 0; i < numColumns; i++) {
719                 widestColumnWidth = Math.max(widestColumnWidth,
720                         minColumnWidths[i]);
721             }
722         }
723         for (int i = 0; i < numColumns; i++) {
724             if (i > 0)
725                 minimumWidth += horizontalSpacing;
726             if (makeColumnsEqualWidth)
727                 minimumWidth += widestColumnWidth;
728             else
729                 minimumWidth += minColumnWidths[i];
730         }
731         // add margins
732
minimumWidth += leftMargin + rightMargin;
733         return minimumWidth;
734     }
735
736     int internalGetMaximumWidth(Composite parent, boolean changed) {
737         if (changed)
738             //calculateMaximumColumnWidths(parent, true);
739
calculateColumnWidths(parent, maxColumnWidths, true, true);
740         int maximumWidth = 0;
741         for (int i = 0; i < numColumns; i++) {
742             if (i > 0)
743                 maximumWidth += horizontalSpacing;
744             maximumWidth += maxColumnWidths[i];
745         }
746         // add margins
747
maximumWidth += leftMargin + rightMargin;
748         return maximumWidth;
749     }
750
751     void resetColumnWidths() {
752         if (minColumnWidths == null)
753             minColumnWidths = new int[numColumns];
754         if (maxColumnWidths == null)
755             maxColumnWidths = new int[numColumns];
756         for (int i = 0; i < numColumns; i++) {
757             minColumnWidths[i] = 0;
758         }
759         for (int i = 0; i < numColumns; i++) {
760             maxColumnWidths[i] = 0;
761         }
762     }
763     
764     void calculateColumnWidths(Composite parent, int [] columnWidths, boolean max, boolean changed) {
765         boolean secondPassNeeded=false;
766         for (int i = 0; i < grid.size(); i++) {
767             TableWrapData[] row = (TableWrapData[]) grid.elementAt(i);
768             for (int j = 0; j < numColumns; j++) {
769                 TableWrapData td = row[j];
770                 if (td.isItemData == false)
771                     continue;
772                 
773                 if (td.colspan>1) {
774                     // we will not do controls with multiple column span
775
// here - increment and continue
776
secondPassNeeded=true;
777                     j+=td.colspan-1;
778                     continue;
779                 }
780
781                 SizeCache childCache = cache.getCache(td.childIndex);
782                 // !!
783
int width = max?childCache.computeMaximumWidth():childCache.computeMinimumWidth();
784                 if (td.maxWidth!=SWT.DEFAULT)
785                     width = Math.min(width, td.maxWidth);
786
787                 width += td.indent;
788                 columnWidths[j] = Math.max(columnWidths[j], width);
789             }
790         }
791         if (!secondPassNeeded) return;
792         
793         // Second pass for controls with multi-column horizontal span
794
for (int i = 0; i < grid.size(); i++) {
795             TableWrapData[] row = (TableWrapData[]) grid.elementAt(i);
796             for (int j = 0; j < numColumns; j++) {
797                 TableWrapData td = row[j];
798                 if (td.isItemData == false || td.colspan==1)
799                     continue;
800
801                 SizeCache childCache = cache.getCache(td.childIndex);
802                 int width = max?childCache.computeMaximumWidth():childCache.computeMinimumWidth();
803                 if (td.maxWidth!=SWT.DEFAULT)
804                     width = Math.min(width, td.maxWidth);
805
806                 width += td.indent;
807                 // check if the current width is enough to
808
// support the control; if not, add the delta to
809
// the last column or to all the growing columns, if present
810
int current = 0;
811                 for (int k = j; k < j + td.colspan; k++) {
812                     if (k > j)
813                         current += horizontalSpacing;
814                     current += columnWidths[k];
815                 }
816                 if (width <= current) {
817                     // we are ok - nothing to do here
818
} else {
819                     int ndiv = 0;
820                     if (growingColumns != null) {
821                         for (int k = j; k < j + td.colspan; k++) {
822                             if (isGrowingColumn(k)) {
823                                 ndiv++;
824                             }
825                         }
826                     }
827                     if (ndiv == 0) {
828                         // add the delta to the last column
829
columnWidths[j + td.colspan - 1] += width
830                                 - current;
831                     } else {
832                         // distribute the delta to the growing
833
// columns
834
int percolumn = (width - current) / ndiv;
835                         if ((width - current) % ndiv > 0)
836                             percolumn++;
837                         for (int k = j; k < j + td.colspan; k++) {
838                             if (isGrowingColumn(k))
839                                 columnWidths[k] += percolumn;
840                         }
841                     }
842                 }
843             }
844         }
845     }
846     
847     boolean isWrap(Control control) {
848         if (control instanceof Composite
849                 && ((Composite) control).getLayout() instanceof ILayoutExtension)
850             return true;
851         return (control.getStyle() & SWT.WRAP) != 0;
852     }
853
854     private void initializeIfNeeded(Composite parent, boolean changed) {
855         if (changed)
856             initialLayout = true;
857         if (initialLayout) {
858             initializeLayoutData(parent);
859             initialLayout = false;
860         }
861     }
862
863     void initializeLayoutData(Composite composite) {
864         Control[] children = composite.getChildren();
865         for (int i = 0; i < children.length; i++) {
866             Control child = children[i];
867             if (child.getLayoutData() == null) {
868                 child.setLayoutData(new TableWrapData());
869             }
870         }
871     }
872 }
873
Popular Tags