KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > texteditor > templates > ColumnLayout


1 /*******************************************************************************
2  * Copyright (c) 2005, 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.texteditor.templates;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.List JavaDoc;
15
16 import org.eclipse.swt.SWT;
17 import org.eclipse.swt.graphics.Point;
18 import org.eclipse.swt.graphics.Rectangle;
19 import org.eclipse.swt.widgets.Composite;
20 import org.eclipse.swt.widgets.Layout;
21 import org.eclipse.swt.widgets.ScrollBar;
22 import org.eclipse.swt.widgets.Table;
23 import org.eclipse.swt.widgets.TableColumn;
24
25 import org.eclipse.core.runtime.Assert;
26
27 import org.eclipse.jface.viewers.ColumnLayoutData;
28 import org.eclipse.jface.viewers.ColumnPixelData;
29 import org.eclipse.jface.viewers.ColumnWeightData;
30
31 /**
32  * Layout for tables, adapted from <code>TableLayoutComposite</code>.
33  *
34  * @since 3.2
35  */

36 final class ColumnLayout extends Layout {
37     
38     private static final String JavaDoc RECALCULATE_LAYOUT= "recalculateKey"; //$NON-NLS-1$
39

40     /**
41      * The number of extra pixels taken as horizontal trim by the table column.
42      * To ensure there are N pixels available for the content of the column,
43      * assign N+COLUMN_TRIM for the column width.
44      *
45      * @since 3.1
46      */

47     private static int COLUMN_TRIM= "carbon".equals(SWT.getPlatform()) ? 24 : 3; //$NON-NLS-1$
48

49     private List JavaDoc columns= new ArrayList JavaDoc();
50
51     /**
52      * Adds a new column of data to this table layout.
53      *
54      * @param data the column layout data
55      */

56     public void addColumnData(ColumnLayoutData data) {
57         columns.add(data);
58     }
59     
60     private Point computeTableSize(Table table, int wHint, int hHint) {
61         Point result= table.computeSize(wHint, hHint);
62         
63         int width= 0;
64         int size= columns.size();
65         for (int i= 0; i < size; ++i) {
66             ColumnLayoutData layoutData= (ColumnLayoutData) columns.get(i);
67             if (layoutData instanceof ColumnPixelData) {
68                 ColumnPixelData col= (ColumnPixelData) layoutData;
69                 width += col.width;
70                 if (col.addTrim) {
71                     width += COLUMN_TRIM;
72                 }
73             } else if (layoutData instanceof ColumnWeightData) {
74                 ColumnWeightData col= (ColumnWeightData) layoutData;
75                 width += col.minimumWidth;
76             } else {
77                 Assert.isTrue(false, "Unknown column layout data"); //$NON-NLS-1$
78
}
79         }
80         if (width > result.x)
81             result.x= width;
82         return result;
83     }
84     
85     private void layoutTable(final Table table, final int width, final Rectangle area, final boolean increase) {
86         final TableColumn[] tableColumns= table.getColumns();
87         final int size= Math.min(columns.size(), tableColumns.length);
88         final int[] widths= new int[size];
89
90         final int[] weightIteration= new int[size];
91         int numberOfWeightColumns= 0;
92         
93         int fixedWidth= 0;
94         int minWeightWidth= 0;
95         int totalWeight= 0;
96
97         // First calc space occupied by fixed columns
98
for (int i= 0; i < size; i++) {
99             ColumnLayoutData col= (ColumnLayoutData) columns.get(i);
100             if (col instanceof ColumnPixelData) {
101                 ColumnPixelData cpd= (ColumnPixelData) col;
102                 int pixels= cpd.width;
103                 if (cpd.addTrim) {
104                     pixels += COLUMN_TRIM;
105                 }
106                 widths[i]= pixels;
107                 fixedWidth += pixels;
108             } else if (col instanceof ColumnWeightData) {
109                 ColumnWeightData cw= (ColumnWeightData) col;
110                 weightIteration[numberOfWeightColumns]= i;
111                 numberOfWeightColumns++;
112                 totalWeight += cw.weight;
113                 minWeightWidth += cw.minimumWidth;
114                 widths[i]= cw.minimumWidth;
115             } else {
116                 Assert.isTrue(false, "Unknown column layout data"); //$NON-NLS-1$
117
}
118         }
119         
120
121         // Do we have columns that have a weight?
122
final int restIncludingMinWidths= width - fixedWidth;
123         final int rest= restIncludingMinWidths - minWeightWidth;
124         if (numberOfWeightColumns > 0 && rest > 0) {
125             
126             // Modify the weights to reflect what each column already
127
// has due to its minimum. Otherwise, columns with low
128
// minimums get discriminated.
129
int totalWantedPixels= 0;
130             final int[] wantedPixels= new int[numberOfWeightColumns];
131             for (int i= 0; i < numberOfWeightColumns; i++) {
132                 ColumnWeightData cw= (ColumnWeightData) columns.get(weightIteration[i]);
133                 wantedPixels[i]= totalWeight == 0 ? 0 : cw.weight * restIncludingMinWidths / totalWeight;
134                 totalWantedPixels+= wantedPixels[i];
135             }
136             
137             // Now distribute the rest to the columns with weight.
138
int totalDistributed= 0;
139             for (int i= 0; i < numberOfWeightColumns; ++i) {
140                 int pixels= totalWantedPixels == 0 ? 0 : wantedPixels[i] * rest / totalWantedPixels;
141                 totalDistributed += pixels;
142                 widths[weightIteration[i]] += pixels;
143             }
144
145             // Distribute any remaining pixels to columns with weight.
146
int diff= rest - totalDistributed;
147             for (int i= 0; diff > 0; i= ((i + 1) % numberOfWeightColumns)) {
148                 ++widths[weightIteration[i]];
149                 --diff;
150             }
151         }
152         
153         if (increase) {
154             table.setSize(area.width, area.height);
155         }
156         for (int i= 0; i < size; i++) {
157             tableColumns[i].setWidth(widths[i]);
158         }
159         if (!increase) {
160             table.setSize(area.width, area.height);
161         }
162     }
163
164     /*
165      * @see org.eclipse.swt.widgets.Layout#computeSize(org.eclipse.swt.widgets.Composite, int, int, boolean)
166      */

167     protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
168         return computeTableSize(getTable(composite), wHint, hHint);
169     }
170
171     /*
172      * @see org.eclipse.swt.widgets.Layout#layout(org.eclipse.swt.widgets.Composite, boolean)
173      */

174     protected void layout(Composite composite, boolean flushCache) {
175         Rectangle area= composite.getClientArea();
176         Table table= getTable(composite);
177         int tableWidth= table.getSize().x;
178         int trim= computeTrim(area, table, tableWidth);
179         int width= Math.max(0, area.width - trim);
180         
181         if (width > 1)
182             layoutTable(table, width, area, tableWidth < area.width);
183         
184         if( composite.getData(RECALCULATE_LAYOUT) == null ) {
185             composite.setData(RECALCULATE_LAYOUT, Boolean.FALSE);
186             composite.layout();
187         }
188     }
189
190     private int computeTrim(Rectangle area, Table table, int tableWidth) {
191         Point preferredSize= computeTableSize(table, area.width, area.height);
192         int trim;
193         if (tableWidth > 1) {
194             trim= tableWidth - table.getClientArea().width;
195         } else {
196             // initially, the table has no extend and no client area - use the border with
197
// plus some padding as educated guess
198
trim= 2 * table.getBorderWidth() + 1 ;
199         }
200         if (preferredSize.y > area.height) {
201             // Subtract the scrollbar width from the total column width
202
// if a vertical scrollbar will be required, but is not currently showing
203
// (in which case it is already subtracted above)
204
ScrollBar vBar= table.getVerticalBar();
205             if (!vBar.isVisible()) {
206                 Point vBarSize= vBar.getSize();
207                 trim += vBarSize.x;
208             }
209         }
210         return trim;
211     }
212
213     private Table getTable(Composite composite) {
214         return (Table) composite.getChildren()[0];
215     }
216
217 }
218
Popular Tags