10
|
1 /*******************************************************************************
|
|
2 * Copyright (c) 2006, 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 (original file dwtx.ui.texteditor.templates.ColumnLayout)
|
|
10 * Tom Schindl <tom.schindl@bestsolution.at> - refactored to be widget independent (bug 171824)
|
|
11 * - fix for bug 178280, 184342, 184045
|
|
12 * Port to the D programming language:
|
|
13 * Frank Benoit <benoit@tionex.de>
|
|
14 *******************************************************************************/
|
|
15 module dwtx.jface.layout.AbstractColumnLayout;
|
|
16
|
|
17
|
|
18
|
|
19 import dwt.DWT;
|
|
20 import dwt.graphics.Point;
|
|
21 import dwt.graphics.Rectangle;
|
|
22 import dwt.widgets.Composite;
|
|
23 import dwt.widgets.Event;
|
|
24 import dwt.widgets.Layout;
|
|
25 import dwt.widgets.Listener;
|
|
26 import dwt.widgets.Scrollable;
|
|
27 import dwt.widgets.Widget;
|
|
28 import dwtx.core.runtime.Assert;
|
|
29 import dwtx.jface.util.Policy;
|
|
30 import dwtx.jface.viewers.ColumnLayoutData;
|
|
31 import dwtx.jface.viewers.ColumnPixelData;
|
|
32 import dwtx.jface.viewers.ColumnWeightData;
|
|
33 import dwtx.jface.viewers.TableLayout;
|
|
34
|
|
35 import dwt.dwthelper.utils;
|
|
36
|
|
37 /**
|
|
38 * The AbstractColumnLayout is a {@link Layout} used to set the size of a table
|
|
39 * in a consistent way even during a resize unlike a {@link TableLayout} which
|
|
40 * only sets initial sizes.
|
|
41 *
|
|
42 * <p><b>You can only add the layout to a container whose
|
|
43 * only child is the table/tree control you want the layouts applied to.</b>
|
|
44 * </p>
|
|
45 *
|
|
46 * @since 3.3
|
|
47 */
|
|
48 abstract class AbstractColumnLayout : Layout {
|
|
49 /**
|
|
50 * The number of extra pixels taken as horizontal trim by the table column.
|
|
51 * To ensure there are N pixels available for the content of the column,
|
|
52 * assign N+COLUMN_TRIM for the column width.
|
|
53 *
|
|
54 * @since 3.1
|
|
55 */
|
|
56 private static int COLUMN_TRIM;
|
|
57
|
|
58 static const bool IS_GTK;
|
|
59
|
|
60 static const String LAYOUT_DATA;
|
|
61
|
|
62 static this(){
|
|
63 COLUMN_TRIM = "carbon".equals(DWT.getPlatform()) ? 24 : 3; //$NON-NLS-1$
|
|
64 IS_GTK = "gtk".equals(DWT.getPlatform());//$NON-NLS-1$
|
|
65 LAYOUT_DATA = Policy.JFACE ~ ".LAYOUT_DATA"; //$NON-NLS-1$
|
|
66 }
|
|
67
|
|
68 private bool inupdateMode = false;
|
|
69
|
|
70 private bool relayout = true;
|
|
71
|
|
72 private Listener resizeListener;
|
|
73 private void init_resizeListener(){
|
|
74 resizeListener = new class Listener {
|
|
75
|
|
76 public void handleEvent(Event event) {
|
|
77 if( ! inupdateMode ) {
|
|
78 updateColumnData(event.widget);
|
|
79 }
|
|
80 }
|
|
81
|
|
82 };
|
|
83 }
|
|
84 public this(){
|
|
85 init_resizeListener();
|
|
86 }
|
|
87
|
|
88 /**
|
|
89 * Adds a new column of data to this table layout.
|
|
90 *
|
|
91 * @param column
|
|
92 * the column
|
|
93 *
|
|
94 * @param data
|
|
95 * the column layout data
|
|
96 */
|
|
97 public void setColumnData(Widget column, ColumnLayoutData data) {
|
|
98
|
|
99 if( column.getData(LAYOUT_DATA) is null ) {
|
|
100 column.addListener(DWT.Resize, resizeListener);
|
|
101 }
|
|
102
|
|
103 column.setData(LAYOUT_DATA, data);
|
|
104 }
|
|
105
|
|
106 /**
|
|
107 * Compute the size of the table or tree based on the ColumnLayoutData and
|
|
108 * the width and height hint.
|
|
109 *
|
|
110 * @param scrollable
|
|
111 * the widget to compute
|
|
112 * @param wHint
|
|
113 * the width hint
|
|
114 * @param hHint
|
|
115 * the height hint
|
|
116 * @return Point where x is the width and y is the height
|
|
117 */
|
|
118 private Point computeTableTreeSize(Scrollable scrollable, int wHint,
|
|
119 int hHint) {
|
|
120 Point result = scrollable.computeSize(wHint, hHint);
|
|
121
|
|
122 int width = 0;
|
|
123 int size = getColumnCount(scrollable);
|
|
124 for (int i = 0; i < size; ++i) {
|
|
125 ColumnLayoutData layoutData = getLayoutData(scrollable,i);
|
|
126 if ( auto col = cast(ColumnPixelData)layoutData) {
|
|
127 width += col.width;
|
|
128 if (col.addTrim) {
|
|
129 width += COLUMN_TRIM;
|
|
130 }
|
|
131 } else if ( auto col = cast(ColumnWeightData)layoutData ) {
|
|
132 width += col.minimumWidth;
|
|
133 } else {
|
|
134 Assert.isTrue(false, "Unknown column layout data"); //$NON-NLS-1$
|
|
135 }
|
|
136 }
|
|
137 if (width > result.x)
|
|
138 result.x = width;
|
|
139
|
|
140 return result;
|
|
141 }
|
|
142
|
|
143 /**
|
|
144 * Layout the scrollable based on the supplied width and area. Only increase
|
|
145 * the size of the scrollable if increase is <code>true</code>.
|
|
146 *
|
|
147 * @param scrollable
|
|
148 * @param width
|
|
149 * @param area
|
|
150 * @param increase
|
|
151 */
|
|
152 private void layoutTableTree(Scrollable scrollable, int width,
|
|
153 Rectangle area, bool increase) {
|
|
154 int size = getColumnCount(scrollable);
|
|
155 int[] widths = new int[size];
|
|
156
|
|
157 int[] weightIteration = new int[size];
|
|
158 int numberOfWeightColumns = 0;
|
|
159
|
|
160 int fixedWidth = 0;
|
|
161 int minWeightWidth = 0;
|
|
162 int totalWeight = 0;
|
|
163
|
|
164 // First calc space occupied by fixed columns
|
|
165 for (int i = 0; i < size; i++) {
|
|
166 ColumnLayoutData col = getLayoutData(scrollable,i);
|
|
167 if ( auto cpd = cast(ColumnPixelData)col ) {
|
|
168 int pixels = cpd.width;
|
|
169 if (cpd.addTrim) {
|
|
170 pixels += COLUMN_TRIM;
|
|
171 }
|
|
172 widths[i] = pixels;
|
|
173 fixedWidth += pixels;
|
|
174 } else if ( auto cw = cast(ColumnWeightData) col ) {
|
|
175 weightIteration[numberOfWeightColumns] = i;
|
|
176 numberOfWeightColumns++;
|
|
177 totalWeight += cw.weight;
|
|
178 minWeightWidth += cw.minimumWidth;
|
|
179 widths[i] = cw.minimumWidth;
|
|
180 } else {
|
|
181 Assert.isTrue(false, "Unknown column layout data"); //$NON-NLS-1$
|
|
182 }
|
|
183 }
|
|
184
|
|
185 // Do we have columns that have a weight?
|
|
186 int restIncludingMinWidths = width - fixedWidth;
|
|
187 int rest = restIncludingMinWidths - minWeightWidth;
|
|
188 if (numberOfWeightColumns > 0 && rest > 0) {
|
|
189
|
|
190 // Modify the weights to reflect what each column already
|
|
191 // has due to its minimum. Otherwise, columns with low
|
|
192 // minimums get discriminated.
|
|
193 int totalWantedPixels = 0;
|
|
194 int[] wantedPixels = new int[numberOfWeightColumns];
|
|
195 for (int i = 0; i < numberOfWeightColumns; i++) {
|
|
196 ColumnWeightData cw = cast(ColumnWeightData) getLayoutData(scrollable,weightIteration[i]);
|
|
197 wantedPixels[i] = totalWeight is 0 ? 0 : cw.weight
|
|
198 * restIncludingMinWidths / totalWeight;
|
|
199 totalWantedPixels += wantedPixels[i];
|
|
200 }
|
|
201
|
|
202 // Now distribute the rest to the columns with weight.
|
|
203 int totalDistributed = 0;
|
|
204 for (int i = 0; i < numberOfWeightColumns; ++i) {
|
|
205 int pixels = totalWantedPixels is 0 ? 0 : wantedPixels[i]
|
|
206 * rest / totalWantedPixels;
|
|
207 totalDistributed += pixels;
|
|
208 widths[weightIteration[i]] += pixels;
|
|
209 }
|
|
210
|
|
211 // Distribute any remaining pixels to columns with weight.
|
|
212 int diff = rest - totalDistributed;
|
|
213 for (int i = 0; diff > 0; i = ((i + 1) % numberOfWeightColumns)) {
|
|
214 ++widths[weightIteration[i]];
|
|
215 --diff;
|
|
216 }
|
|
217 }
|
|
218
|
|
219 if (increase) {
|
|
220 scrollable.setSize(area.width, area.height);
|
|
221 }
|
|
222
|
|
223 inupdateMode = true;
|
|
224 setColumnWidths(scrollable, widths);
|
|
225 scrollable.update();
|
|
226 inupdateMode = false;
|
|
227
|
|
228 if (!increase) {
|
|
229 scrollable.setSize(area.width, area.height);
|
|
230 }
|
|
231 }
|
|
232
|
|
233 /*
|
|
234 * (non-Javadoc)
|
|
235 *
|
|
236 * @see dwt.widgets.Layout#computeSize(dwt.widgets.Composite,
|
|
237 * int, int, bool)
|
|
238 */
|
|
239 protected Point computeSize(Composite composite, int wHint, int hHint,
|
|
240 bool flushCache) {
|
|
241 return computeTableTreeSize(getControl(composite), wHint, hHint);
|
|
242 }
|
|
243
|
|
244 /*
|
|
245 * (non-Javadoc)
|
|
246 *
|
|
247 * @see dwt.widgets.Layout#layout(dwt.widgets.Composite,
|
|
248 * bool)
|
|
249 */
|
|
250 protected void layout(Composite composite, bool flushCache) {
|
|
251 Rectangle area = composite.getClientArea();
|
|
252 Scrollable table = getControl(composite);
|
|
253 int tableWidth = table.getSize().x;
|
|
254 int trim = computeTrim(area, table, tableWidth);
|
|
255 int width = Math.max(0, area.width - trim);
|
|
256
|
|
257 if (width > 1)
|
|
258 layoutTableTree(table, width, area, tableWidth < area.width);
|
|
259
|
|
260 // For the first time we need to relayout because Scrollbars are not
|
|
261 // calculate appropriately
|
|
262 if (relayout) {
|
|
263 relayout = false;
|
|
264 composite.layout();
|
|
265 }
|
|
266 }
|
|
267
|
|
268 /**
|
|
269 * Compute the area required for trim.
|
|
270 *
|
|
271 * @param area
|
|
272 * @param scrollable
|
|
273 * @param currentWidth
|
|
274 * @return int
|
|
275 */
|
|
276 private int computeTrim(Rectangle area, Scrollable scrollable,
|
|
277 int currentWidth) {
|
|
278 int trim;
|
|
279
|
|
280 if (currentWidth > 1) {
|
|
281 trim = currentWidth - scrollable.getClientArea().width;
|
|
282 } else {
|
|
283 // initially, the table has no extend and no client area - use the
|
|
284 // border with
|
|
285 // plus some padding as educated guess
|
|
286 trim = 2 * scrollable.getBorderWidth() + 1;
|
|
287 }
|
|
288
|
|
289 return trim;
|
|
290 }
|
|
291
|
|
292 /**
|
|
293 * Get the control being laid out.
|
|
294 *
|
|
295 * @param composite
|
|
296 * the composite with the layout
|
|
297 * @return {@link Scrollable}
|
|
298 */
|
|
299 Scrollable getControl(Composite composite) {
|
|
300 return cast(Scrollable) composite.getChildren()[0];
|
|
301 }
|
|
302
|
|
303 /**
|
|
304 * Get the number of columns for the receiver.
|
|
305 *
|
|
306 * @return the number of columns
|
|
307 */
|
|
308 abstract int getColumnCount(Scrollable tableTree);
|
|
309
|
|
310 /**
|
|
311 * Set the widths of the columns.
|
|
312 *
|
|
313 * @param widths
|
|
314 */
|
|
315 abstract void setColumnWidths(Scrollable tableTree, int[] widths);
|
|
316
|
|
317 abstract ColumnLayoutData getLayoutData(Scrollable tableTree, int columnIndex);
|
|
318
|
|
319 abstract void updateColumnData(Widget column);
|
|
320 }
|