View | Details | Raw Unified | Return to bug 133279 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/gmf/internal/codegen/draw2d/GridLayout.java (+794 lines)
Added Link Here
1
package org.eclipse.gmf.internal.codegen.draw2d;
2
3
import java.util.HashMap;
4
import java.util.List;
5
import java.util.Map;
6
7
import org.eclipse.draw2d.AbstractLayout;
8
import org.eclipse.draw2d.IFigure;
9
import org.eclipse.draw2d.LayoutManager;
10
import org.eclipse.draw2d.geometry.Dimension;
11
import org.eclipse.draw2d.geometry.Rectangle;
12
import org.eclipse.swt.SWT;
13
14
15
/**
16
 * Lays out children into a Grid arrangement in which overall aligment and
17
 * spacing can be configured, as well as specfic layout requirements for the
18
 * each individual member of the GridLayout. This layout is a Draw2D port of the
19
 * swt GridLayout.
20
 * 
21
 * <code>GridLayout</code> has a number of configuration fields, and the
22
 * Figures it lays out can have an associated layout data object, called
23
 * <code>GridLayoutData</code> (similar to the swt GridLayoutData object). The power of
24
 * <code>GridLayout</code> lies in the ability to configure
25
 * <code>GridLayoutData</code> for each Figure in the layout.
26
 * <p>
27
 * The following code creates a container Figure managed by a
28
 * <code>GridLayout</code> with 2 columns, containing 3 RectangleFigure
29
 * shapes, the last of which has been given further layout instructions.
30
 * Note that it is the <code>GridLayout</code> method <code>setConstraint</code>
31
 * that binds the child <code>Figure</code> to its layout <code>GridLayoutData</code> object.
32
 * 
33
 * <pre>
34
 *     Figure container = new Figure();
35
 *     GridLayout gridLayout = new GridLayout();
36
 *     gridLayout.numColumns = 2;
37
 *     container.setLayout(gridLayout);
38
 * 
39
 *     Shape rect;
40
 *     rect = new RectangleFigure();
41
 *     container.add(rect);
42
 * 
43
 *     rect = new RectangleFigure();
44
 *     container.add(rect);
45
 * 
46
 *     rect = new RectangleFigure();
47
 *     GridLayoutData GridLayoutData = new GridLayoutData();
48
 *     GridLayoutData.widthHint = 150;
49
 *     layout.setConstraint(rect, GridLayoutData);
50
 * 
51
 *     container.add(rect);
52
 * </pre>
53
 * 
54
 * <p>
55
 * The <code>numColumns</code> field is the most important field in a
56
 * <code>GridLayout</code>. Widgets are laid out in columns from left to
57
 * right, and a new row is created when <code>numColumns</code>+ 1 figures
58
 * are added to the <code>Figure<code> parent container.
59
 * 
60
 * @see GridLayoutData
61
 * 
62
 * @author Asim Ullah
63
 * created: Sep 10, 2004
64
 */
65
public class GridLayout extends AbstractLayout {
66
67
	/**
68
	 * numColumns specifies the number of cell columns in the layout.
69
	 * 
70
	 * The default value is 1.
71
	 */
72
	public int numColumns = 1;
73
74
	/**
75
	 * makeColumnsEqualWidth specifies whether all columns in the layout will be
76
	 * forced to have the same width.
77
	 * 
78
	 * The default value is false.
79
	 */
80
	public boolean makeColumnsEqualWidth = false;
81
82
	/**
83
	 * marginWidth specifies the number of pixels of horizontal margin that will
84
	 * be placed along the left and right edges of the layout.
85
	 * 
86
	 * The default value is 5.
87
	 */
88
	public int marginWidth = 5;
89
90
	/**
91
	 * marginHeight specifies the number of pixels of vertical margin that will
92
	 * be placed along the top and bottom edges of the layout.
93
	 * 
94
	 * The default value is 5.
95
	 */
96
	public int marginHeight = 5;
97
98
	/**
99
	 * horizontalSpacing specifies the number of pixels between the right edge
100
	 * of one cell and the left edge of its neighbouring cell to the right.
101
	 * 
102
	 * The default value is 5.
103
	 */
104
	public int horizontalSpacing = 5;
105
106
	/**
107
	 * verticalSpacing specifies the number of pixels between the bottom edge of
108
	 * one cell and the top edge of its neighbouring cell underneath.
109
	 * 
110
	 * The default value is 5.
111
	 */
112
	public int verticalSpacing = 5;
113
114
	/** The layout contraints */
115
	protected Map constraints = new HashMap();
116
117
	/**
118
	 *  Default Constructor
119
	 */
120
	public GridLayout() {
121
		super();
122
	}
123
124
	/**
125
	 * Constructs a new instance of this class given the number of columns, and
126
	 * whether or not the columns should be forced to have the same width.
127
	 * 
128
	 * @param numColumns
129
	 *            the number of columns in the grid
130
	 * @param makeColumnsEqualWidth
131
	 *            whether or not the columns will have equal width
132
	 *  
133
	 */
134
	public GridLayout(int numColumns, boolean makeColumnsEqualWidth) {
135
		this.numColumns = numColumns;
136
		this.makeColumnsEqualWidth = makeColumnsEqualWidth;
137
	}
138
139
	/**
140
	 * @param child
141
	 * @param wHint
142
	 * @param hHint
143
	 * @return
144
	 */
145
	protected Dimension getChildSize(IFigure child, int wHint, int hHint) {
146
		return child.getPreferredSize(wHint, hHint);
147
	}
148
149
	GridLayoutData getData(IFigure[][] grid, int row, int column, int rowCount,
150
			int columnCount, boolean first) {
151
		IFigure figure = grid[row][column];
152
		if (figure != null) {
153
			GridLayoutData data = (GridLayoutData) getConstraint(figure);
154
			int hSpan = Math.max(1, Math.min(data.horizontalSpan, columnCount));
155
			int vSpan = Math.max(1, data.verticalSpan);
156
			int i = first ? row + vSpan - 1 : row - vSpan + 1;
157
			int j = first ? column + hSpan - 1 : column - hSpan + 1;
158
			if (0 <= i && i < rowCount) {
159
				if (0 <= j && j < columnCount) {
160
					if (figure == grid[i][j])
161
						return data;
162
				}
163
			}
164
		}
165
		return null;
166
	}
167
    
168
    void initChildren(IFigure container)
169
    {
170
        List children = container.getChildren();
171
        for (int i = 0; i < children.size(); i++) {
172
            IFigure child = (IFigure) children.get(i);
173
            if (child.getLayoutManager()==null)
174
            	child.setLayoutManager(this);
175
        }
176
    }
177
178
	/*
179
	 * (non-Javadoc)
180
	 * 
181
	 * @see org.eclipse.draw2d.AbstractLayout#calculatePreferredSize(org.eclipse.draw2d.IFigure,
182
	 *      int, int)
183
	 */
184
	protected Dimension calculatePreferredSize(IFigure container, int wHint,
185
			int hHint) {
186
		Dimension size = layout(container, false, 0, 0, wHint, hHint, /* flushCache */
187
				true);
188
    		if (wHint != SWT.DEFAULT)
189
			size.width = wHint;
190
		if (hHint != SWT.DEFAULT)
191
			size.height = hHint;
192
193
		return size;
194
	}
195
196
	/*
197
	 * (non-Javadoc)
198
	 * 
199
	 * @see org.eclipse.draw2d.LayoutManager#layout(org.eclipse.draw2d.IFigure)
200
	 */
201
	public void layout(IFigure container) {
202
        //initChildren( container);
203
		Rectangle rect = container.getClientArea();
204
		layout(container, true, rect.x, rect.y, rect.width, rect.height, /* flushCache */
205
				true);
206
207
	}
208
209
	Dimension layout(IFigure container, boolean move, int x, int y, int width,
210
			int height, boolean flushCache) {
211
		if (numColumns < 1)
212
			return new Dimension(marginWidth * 2, marginHeight * 2);
213
		List children = container.getChildren();
214
		for (int i = 0; i < children.size(); i++) {
215
			IFigure child = (IFigure) children.get(i);
216
217
			GridLayoutData data = (GridLayoutData) getConstraint(child);
218
			if (data == null)
219
				setConstraint(child, data = new GridLayoutData());
220
			if (flushCache)
221
				data.flushCache();
222
			data.computeSize(child, flushCache);
223
		}
224
225
		/* Build the grid */
226
		int row = 0, column = 0, rowCount = 0, columnCount = numColumns;
227
		IFigure[][] grid = new IFigure[4][columnCount];
228
		for (int i = 0; i < children.size(); i++) {
229
			IFigure child = (IFigure) children.get(i);
230
			GridLayoutData data = (GridLayoutData) getConstraint(child);
231
			int hSpan = Math.max(1, Math.min(data.horizontalSpan, columnCount));
232
			int vSpan = Math.max(1, data.verticalSpan);
233
			while (true) {
234
				int lastRow = row + vSpan;
235
				if (lastRow >= grid.length) {
236
					IFigure[][] newGrid = new IFigure[lastRow + 4][columnCount];
237
					System.arraycopy(grid, 0, newGrid, 0, grid.length);
238
					grid = newGrid;
239
				}
240
				if (grid[row] == null) {
241
					grid[row] = new IFigure[columnCount];
242
				}
243
				while (column < columnCount && grid[row][column] != null) {
244
					column++;
245
				}
246
				int endCount = column + hSpan;
247
				if (endCount <= columnCount) {
248
					int index = column;
249
					while (index < endCount && grid[row][index] == null) {
250
						index++;
251
					}
252
					if (index == endCount)
253
						break;
254
					column = index;
255
				}
256
				if (column + hSpan >= columnCount) {
257
					column = 0;
258
					row++;
259
				}
260
			}
261
			for (int j = 0; j < vSpan; j++) {
262
				if (grid[row + j] == null) {
263
					grid[row + j] = new IFigure[columnCount];
264
				}
265
				for (int k = 0; k < hSpan; k++) {
266
					grid[row + j][column + k] = child;
267
				}
268
			}
269
			rowCount = Math.max(rowCount, row + vSpan);
270
			column += hSpan;
271
		}
272
273
		/* Column widths */
274
		int availableWidth = width - horizontalSpacing * (columnCount - 1)
275
				- marginWidth * 2;
276
		int expandCount = 0;
277
		int[] widths = new int[columnCount];
278
		int[] minWidths = new int[columnCount];
279
		boolean[] expandColumn = new boolean[columnCount];
280
		for (int j = 0; j < columnCount; j++) {
281
			for (int i = 0; i < rowCount; i++) {
282
				GridLayoutData data = getData(grid, i, j, rowCount, columnCount, true);
283
				if (data != null) {
284
					int hSpan = Math.max(1, Math.min(data.horizontalSpan,
285
							columnCount));
286
					if (hSpan == 1) {
287
						int w = data.cacheWidth + data.horizontalIndent;
288
						widths[j] = Math.max(widths[j], w);
289
						if (data.grabExcessHorizontalSpace) {
290
							if (!expandColumn[j])
291
								expandCount++;
292
							expandColumn[j] = true;
293
						}
294
						if (data.widthHint != SWT.DEFAULT
295
								|| !data.grabExcessHorizontalSpace) {
296
							minWidths[j] = Math.max(minWidths[j], w);
297
						}
298
					}
299
				}
300
			}
301
			for (int i = 0; i < rowCount; i++) {
302
				GridLayoutData data = getData(grid, i, j, rowCount, columnCount,
303
						false);
304
				if (data != null) {
305
					int hSpan = Math.max(1, Math.min(data.horizontalSpan,
306
							columnCount));
307
					if (hSpan > 1) {
308
						int spanWidth = 0, spanMinWidth = 0, spanExpandCount = 0;
309
						for (int k = 0; k < hSpan; k++) {
310
							spanWidth += widths[j - k];
311
							spanMinWidth += minWidths[j - k];
312
							if (expandColumn[j - k])
313
								spanExpandCount++;
314
						}
315
						if (data.grabExcessHorizontalSpace
316
								&& spanExpandCount == 0) {
317
							expandCount++;
318
							expandColumn[j] = true;
319
						}
320
						int w = data.cacheWidth + data.horizontalIndent
321
								- spanWidth - (hSpan - 1) * horizontalSpacing;
322
						if (w > 0) {
323
							if (spanExpandCount == 0) {
324
								widths[j] += w;
325
							} else {
326
								int delta = w / spanExpandCount;
327
								int remainder = w % spanExpandCount, last = -1;
328
								for (int k = 0; k < hSpan; k++) {
329
									if (expandColumn[j - k]) {
330
										widths[last = j - k] += delta;
331
									}
332
								}
333
								if (last > -1)
334
									widths[last] += remainder;
335
							}
336
						}
337
						if (data.widthHint != SWT.DEFAULT
338
								|| !data.grabExcessHorizontalSpace) {
339
							w = data.cacheWidth + data.horizontalIndent
340
									- spanMinWidth - (hSpan - 1)
341
									* horizontalSpacing;
342
							if (w > 0) {
343
								if (spanExpandCount == 0) {
344
									minWidths[j] += w;
345
								} else {
346
									int delta = w / spanExpandCount;
347
									int remainder = w % spanExpandCount, last = -1;
348
									for (int k = 0; k < hSpan; k++) {
349
										if (expandColumn[j - k]) {
350
											minWidths[last = j - k] += delta;
351
										}
352
									}
353
									if (last > -1)
354
										minWidths[last] += remainder;
355
								}
356
							}
357
						}
358
					}
359
				}
360
			}
361
		}
362
		if (makeColumnsEqualWidth) {
363
			int minColumnWidth = 0;
364
			int columnWidth = 0;
365
			for (int i = 0; i < columnCount; i++) {
366
				minColumnWidth = Math.max(minColumnWidth, minWidths[i]);
367
				columnWidth = Math.max(columnWidth, widths[i]);
368
			}
369
			columnWidth = width == SWT.DEFAULT || expandCount == 0
370
					? columnWidth
371
					: Math.max(minColumnWidth, availableWidth / columnCount);
372
			for (int i = 0; i < columnCount; i++) {
373
				expandColumn[i] = expandCount > 0;
374
				widths[i] = columnWidth;
375
			}
376
		} else {
377
			if (width != SWT.DEFAULT && expandCount > 0) {
378
				int totalWidth = 0;
379
				for (int i = 0; i < columnCount; i++) {
380
					totalWidth += widths[i];
381
				}
382
				int count = expandCount;
383
				int delta = (availableWidth - totalWidth) / count;
384
				int remainder = (availableWidth - totalWidth) % count;
385
				int last = -1;
386
				while (totalWidth != availableWidth) {
387
					for (int j = 0; j < columnCount; j++) {
388
						if (expandColumn[j]) {
389
							if (widths[j] + delta > minWidths[j]) {
390
								widths[last = j] = widths[j] + delta;
391
							} else {
392
								widths[j] = minWidths[j];
393
								expandColumn[j] = false;
394
								count--;
395
							}
396
						}
397
					}
398
					if (last > -1)
399
						widths[last] += remainder;
400
401
					for (int j = 0; j < columnCount; j++) {
402
						for (int i = 0; i < rowCount; i++) {
403
							GridLayoutData data = getData(grid, i, j, rowCount,
404
									columnCount, false);
405
							if (data != null) {
406
								int hSpan = Math.max(1, Math.min(
407
										data.horizontalSpan, columnCount));
408
								if (hSpan > 1) {
409
									if (data.widthHint != SWT.DEFAULT
410
											|| !data.grabExcessHorizontalSpace) {
411
										int spanWidth = 0, spanExpandCount = 0;
412
										for (int k = 0; k < hSpan; k++) {
413
											spanWidth += widths[j - k];
414
											if (expandColumn[j - k])
415
												spanExpandCount++;
416
										}
417
										int w = data.cacheWidth
418
												+ data.horizontalIndent
419
												- spanWidth - (hSpan - 1)
420
												* horizontalSpacing;
421
										if (w > 0) {
422
											if (spanExpandCount == 0) {
423
												widths[j] += w;
424
											} else {
425
												int delta2 = w
426
														/ spanExpandCount;
427
												int remainder2 = w
428
														% spanExpandCount, last2 = -1;
429
												for (int k = 0; k < hSpan; k++) {
430
													if (expandColumn[j - k]) {
431
														widths[last2 = j - k] += delta2;
432
													}
433
												}
434
												if (last2 > -1)
435
													widths[last2] += remainder2;
436
											}
437
										}
438
									}
439
								}
440
							}
441
						}
442
					}
443
					if (count == 0)
444
						break;
445
					totalWidth = 0;
446
					for (int i = 0; i < columnCount; i++) {
447
						totalWidth += widths[i];
448
					}
449
					delta = (availableWidth - totalWidth) / count;
450
					remainder = (availableWidth - totalWidth) % count;
451
					last = -1;
452
				}
453
			}
454
		}
455
456
		/* Wrapping */
457
		GridLayoutData[] flush = null;
458
		int flushLength = 0;
459
		if (width != SWT.DEFAULT) {
460
			for (int j = 0; j < columnCount; j++) {
461
				for (int i = 0; i < rowCount; i++) {
462
					GridLayoutData data = getData(grid, i, j, rowCount, columnCount,
463
							false);
464
					if (data != null) {
465
						if (data.heightHint == SWT.DEFAULT) {
466
							IFigure child = grid[i][j];
467
							//TEMPORARY CODE
468
							int hSpan = Math.max(1, Math.min(
469
									data.horizontalSpan, columnCount));
470
							int currentWidth = 0;
471
							for (int k = 0; k < hSpan; k++) {
472
								currentWidth += widths[j - k];
473
							}
474
							currentWidth += (hSpan - 1) * horizontalSpacing
475
									- data.horizontalIndent;
476
							if ((currentWidth != data.cacheWidth && data.horizontalAlignment == SWT.FILL)
477
									|| (data.cacheWidth > currentWidth)) {
478
								int trim = 0;
479
								/*
480
								  // *Note*: Left this in place from SWT
481
								  // GridLayout. Not sure if Draw2D Borders or
482
								  // Scrollbars 'trim' will need to be takeninto account.
483
								  
484
								  if (child instanceof Group) { 
485
                                      Group g =(Group)child; trim = g.getSize ().x -
486
                                      g.getClientArea ().width; 
487
                                  } else if (child instanceof Scrollable) { 
488
                                      Rectangle rect =
489
                                          ((Scrollable) child).computeTrim (0, 0, 0,0);
490
                                           trim = rect.width; } 
491
                                  else {
492
    								  trim = child.getBorderWidth () * 2; 
493
                                  }
494
								 */
495
								int oldWidthHint = data.widthHint;
496
								data.widthHint = Math.max(0, currentWidth
497
										- trim);
498
								data.cacheWidth = data.cacheHeight = SWT.DEFAULT;
499
								data.computeSize(child, false);
500
								data.widthHint = oldWidthHint;
501
								if (flush == null)
502
									flush = new GridLayoutData[children.size()];
503
								flush[flushLength++] = data;
504
							}
505
						}
506
					}
507
				}
508
			}
509
		}
510
511
		/* Row heights */
512
		int availableHeight = height - verticalSpacing * (rowCount - 1)
513
				- marginHeight * 2;
514
		expandCount = 0;
515
		int[] heights = new int[rowCount];
516
		int[] minHeights = new int[rowCount];
517
		boolean[] expandRow = new boolean[rowCount];
518
		for (int i = 0; i < rowCount; i++) {
519
			for (int j = 0; j < columnCount; j++) {
520
				GridLayoutData data = getData(grid, i, j, rowCount, columnCount, true);
521
				if (data != null) {
522
					int vSpan = Math.max(1, Math.min(data.verticalSpan,
523
							rowCount));
524
					if (vSpan == 1) {
525
						int h = data.cacheHeight; // + data.verticalIndent;
526
						heights[i] = Math.max(heights[i], h);
527
						if (data.grabExcessVerticalSpace) {
528
							if (!expandRow[i])
529
								expandCount++;
530
							expandRow[i] = true;
531
						}
532
						if (data.heightHint != SWT.DEFAULT
533
								|| !data.grabExcessVerticalSpace) {
534
							minHeights[i] = Math.max(minHeights[i], h);
535
						}
536
					}
537
				}
538
			}
539
			for (int j = 0; j < columnCount; j++) {
540
				GridLayoutData data = getData(grid, i, j, rowCount, columnCount,
541
						false);
542
				if (data != null) {
543
					int vSpan = Math.max(1, Math.min(data.verticalSpan,
544
							rowCount));
545
					if (vSpan > 1) {
546
						int spanHeight = 0, spanMinHeight = 0, spanExpandCount = 0;
547
						for (int k = 0; k < vSpan; k++) {
548
							spanHeight += heights[i - k];
549
							spanMinHeight += minHeights[i - k];
550
							if (expandRow[i - k])
551
								spanExpandCount++;
552
						}
553
						if (data.grabExcessVerticalSpace
554
								&& spanExpandCount == 0) {
555
							expandCount++;
556
							expandRow[i] = true;
557
						}
558
						int h = data.cacheHeight - spanHeight - (vSpan - 1)
559
								* verticalSpacing; // + data.verticalalIndent
560
						if (h > 0) {
561
							if (spanExpandCount == 0) {
562
								heights[i] += h;
563
							} else {
564
								int delta = h / spanExpandCount;
565
								int remainder = h % spanExpandCount, last = -1;
566
								for (int k = 0; k < vSpan; k++) {
567
									if (expandRow[i - k]) {
568
										heights[last = i - k] += delta;
569
									}
570
								}
571
								if (last > -1)
572
									heights[last] += remainder;
573
							}
574
						}
575
						if (data.heightHint != SWT.DEFAULT
576
								|| !data.grabExcessVerticalSpace) {
577
							h = data.cacheHeight - spanMinHeight - (vSpan - 1)
578
									* verticalSpacing; // + data.verticalIndent
579
							if (h > 0) {
580
								if (spanExpandCount == 0) {
581
									minHeights[i] += h;
582
								} else {
583
									int delta = h / spanExpandCount;
584
									int remainder = h % spanExpandCount, last = -1;
585
									for (int k = 0; k < vSpan; k++) {
586
										if (expandRow[i - k]) {
587
											minHeights[last = i - k] += delta;
588
										}
589
									}
590
									if (last > -1)
591
										minHeights[last] += remainder;
592
								}
593
							}
594
						}
595
					}
596
				}
597
			}
598
		}
599
		if (height != SWT.DEFAULT && expandCount > 0) {
600
			int totalHeight = 0;
601
			for (int i = 0; i < rowCount; i++) {
602
				totalHeight += heights[i];
603
			}
604
			int count = expandCount;
605
			int delta = (availableHeight - totalHeight) / count;
606
			int remainder = (availableHeight - totalHeight) % count;
607
			int last = -1;
608
			while (totalHeight != availableHeight) {
609
				for (int i = 0; i < rowCount; i++) {
610
					if (expandRow[i]) {
611
						if (heights[i] + delta > minHeights[i]) {
612
							heights[last = i] = heights[i] + delta;
613
						} else {
614
							heights[i] = minHeights[i];
615
							expandRow[i] = false;
616
							count--;
617
						}
618
					}
619
				}
620
				if (last > -1)
621
					heights[last] += remainder;
622
623
				for (int i = 0; i < rowCount; i++) {
624
					for (int j = 0; j < columnCount; j++) {
625
						GridLayoutData data = getData(grid, i, j, rowCount,
626
								columnCount, false);
627
						if (data != null) {
628
							int vSpan = Math.max(1, Math.min(data.verticalSpan,
629
									rowCount));
630
							if (vSpan > 1) {
631
								if (data.heightHint != SWT.DEFAULT
632
										|| !data.grabExcessVerticalSpace) {
633
									int spanHeight = 0, spanExpandCount = 0;
634
									for (int k = 0; k < vSpan; k++) {
635
										spanHeight += heights[i - k];
636
										if (expandRow[i - k])
637
											spanExpandCount++;
638
									}
639
									int h = data.cacheHeight - spanHeight
640
											- (vSpan - 1) * verticalSpacing; // +
641
																			 // data.verticalIndent
642
									if (h > 0) {
643
										if (spanExpandCount == 0) {
644
											heights[i] += h;
645
										} else {
646
											int delta2 = h / spanExpandCount;
647
											int remainder2 = h
648
													% spanExpandCount, last2 = -1;
649
											for (int k = 0; k < vSpan; k++) {
650
												if (expandRow[i - k]) {
651
													heights[last2 = i - k] += delta2;
652
												}
653
											}
654
											if (last2 > -1)
655
												heights[last2] += remainder2;
656
										}
657
									}
658
								}
659
							}
660
						}
661
					}
662
				}
663
				if (count == 0)
664
					break;
665
				totalHeight = 0;
666
				for (int i = 0; i < rowCount; i++) {
667
					totalHeight += heights[i];
668
				}
669
				delta = (availableHeight - totalHeight) / count;
670
				remainder = (availableHeight - totalHeight) % count;
671
				last = -1;
672
			}
673
		}
674
675
		/* Position the IFigures */
676
		if (move) {
677
			int gridY = y + marginHeight;
678
			for (int i = 0; i < rowCount; i++) {
679
				int gridX = x + marginWidth;
680
				for (int j = 0; j < columnCount; j++) {
681
					GridLayoutData data = getData(grid, i, j, rowCount, columnCount,
682
							true);
683
					if (data != null) {
684
						int hSpan = Math.max(1, Math.min(data.horizontalSpan,
685
								columnCount));
686
						int vSpan = Math.max(1, data.verticalSpan);
687
						int cellWidth = 0, cellHeight = 0;
688
						for (int k = 0; k < hSpan; k++) {
689
							cellWidth += widths[j + k];
690
						}
691
						for (int k = 0; k < vSpan; k++) {
692
							cellHeight += heights[i + k];
693
						}
694
						cellWidth += horizontalSpacing * (hSpan - 1);
695
						int childX = gridX + data.horizontalIndent;
696
						int childWidth = Math.min(data.cacheWidth, cellWidth);
697
						switch (data.horizontalAlignment) {
698
							case SWT.CENTER :
699
							case GridLayoutData.CENTER :
700
								childX = gridX
701
										+ Math.max(0,
702
												(cellWidth - childWidth) / 2);
703
								break;
704
							case SWT.RIGHT :
705
							case SWT.END :
706
							case GridLayoutData.END :
707
								childX = gridX
708
										+ Math.max(0, cellWidth - childWidth);
709
								break;
710
							case SWT.FILL :
711
								childWidth = cellWidth - data.horizontalIndent;
712
								break;
713
						}
714
						cellHeight += verticalSpacing * (vSpan - 1);
715
						int childY = gridY; // + data.verticalIndent;
716
						int childHeight = Math
717
								.min(data.cacheHeight, cellHeight);
718
						switch (data.verticalAlignment) {
719
							case SWT.CENTER :
720
							case GridLayoutData.CENTER :
721
								childY = gridY
722
										+ Math.max(0,
723
												(cellHeight - childHeight) / 2);
724
								break;
725
							case SWT.BOTTOM :
726
							case SWT.END :
727
							case GridLayoutData.END :
728
								childY = gridY
729
										+ Math.max(0, cellHeight - childHeight);
730
								break;
731
							case SWT.FILL :
732
								childHeight = cellHeight; // -
733
														  // data.verticalIndent;
734
								break;
735
						}
736
						IFigure child = grid[i][j];
737
						if (child != null) {
738
							// following param could be replaced by
739
							// Rectangle.SINGLETON
740
							child.setBounds(new Rectangle(childX, childY,
741
									childWidth, childHeight));
742
						}
743
					}
744
					gridX += widths[j] + horizontalSpacing;
745
				}
746
				gridY += heights[i] + verticalSpacing;
747
			}
748
		}
749
750
		// clean up cache
751
		for (int i = 0; i < flushLength; i++) {
752
			flush[i].cacheWidth = flush[i].cacheHeight = -1;
753
		}
754
755
		int totalDefaultWidth = 0;
756
		int totalDefaultHeight = 0;
757
		for (int i = 0; i < columnCount; i++) {
758
			totalDefaultWidth += widths[i];
759
		}
760
		for (int i = 0; i < rowCount; i++) {
761
			totalDefaultHeight += heights[i];
762
		}
763
		totalDefaultWidth += horizontalSpacing * (columnCount - 1)
764
				+ marginWidth * 2;
765
		totalDefaultHeight += verticalSpacing * (rowCount - 1) + marginHeight
766
				* 2;
767
		return new Dimension(totalDefaultWidth, totalDefaultHeight);
768
	}
769
770
	/*
771
	 * (non-Javadoc)
772
	 * 
773
	 * @see org.eclipse.draw2d.LayoutManager#getConstraint(org.eclipse.draw2d.IFigure)
774
	 */
775
	public Object getConstraint(IFigure child) {
776
		return constraints.get(child);
777
	}
778
779
	/**
780
	 * Sets the layout constraint of the given figure. The constraints can only
781
	 * be of type {@link GridLayoutData}.
782
	 * 
783
	 * @see LayoutManager#setConstraint(IFigure, Object)
784
	 */
785
	public void setConstraint(IFigure figure, Object newConstraint) {
786
		super.setConstraint(figure, newConstraint);
787
		if (newConstraint != null)
788
        {
789
			constraints.put(figure, newConstraint);
790
            
791
        }
792
	}
793
794
}
(-)src/org/eclipse/gmf/internal/codegen/draw2d/GridLayoutData.java (+453 lines)
Added Link Here
1
package org.eclipse.gmf.internal.codegen.draw2d;
2
3
import org.eclipse.draw2d.IFigure;
4
import org.eclipse.draw2d.geometry.Dimension;
5
import org.eclipse.swt.SWT;
6
7
8
/**
9
 * <code>GridLayoutData</code> is the layout data object associated with
10
 * <code>GridLayout</code>. To set a <code>GridLayoutData</code> object into a
11
 * <code>Figure</code>, you use the <code>setConstraint()</code> method of
12
 * <code>GridLayout</code> to map the <code>Figure</code> to its layout
13
 * <code>GridLayoutData</code>.
14
 * <p>
15
 * There are two ways to create a <code>GridLayoutData</code> object with certain
16
 * fields set. The first is to set the fields directly, like this:
17
 * 
18
 * <pre>
19
 * GridLayoutData gridData = new GridLayoutData();
20
 * gridData.horizontalAlignment = GridLayoutData.FILL;
21
 * gridData.grabExcessHorizontalSpace = true;
22
 * 
23
 * // associate the figure to the GridLayoutData object
24
 * myGridlayout.setConstraint(myFigure, gridData);
25
 * </pre>
26
 * 
27
 * The second is to take advantage of convenience style bits defined by
28
 * <code>GridLayoutData</code>:
29
 * 
30
 * <pre>
31
 * GridLayoutData gridData = new GridLayoutData(GridLayoutData.HORIZONTAL_ALIGN_FILL | GridLayoutData.GRAB_HORIZONTAL);
32
 * </pre>
33
 * 
34
 * </p>
35
 * <p>
36
 * NOTE: Do not reuse <code>GridLayoutData</code> objects. Every child in the parent
37
 * <code>Figure</code> that is managed by the <code>GridLayout</code> must
38
 * have a unique <code>GridLayoutData</code> object. If the layout data for a Grid
39
 * member in a <code>GridLayout</code> is null at layout time, a unique
40
 * <code>GridLayoutData</code> object is created for it.
41
 * </p>
42
 * 
43
 * [GMF]: NOTE: The set of the ALIGNMENT constants is changed in this class
44
 * comparing to original version to match the set of constants in the generated
45
 * code. E.g, <code>GridLayoutData.BEGINNING = SWT.BEGINNING - 1</code>.
46
 * Thus, this implementation is NOT intended to use SWT.* constants for
47
 * alignment.
48
 * 
49
 * @see GridLayout
50
 */
51
public final class GridLayoutData {
52
    /**
53
	 * verticalAlignment specifies how figures will be positioned vertically
54
	 * within a cell.
55
	 * 
56
	 * The default value is CENTER.
57
	 * 
58
	 * Possible values are:
59
	 * 
60
	 * <code>GridLayoutData.BEGINNING = SWT.BEGINNING - 1</code> (or
61
	 * <code>SWT.TOP - 1</code>): Position the figure at the top of the cell
62
	 * 
63
	 * <code>GridLayoutData.CENTER = SWT.CENTER - 1</code>: Position the
64
	 * figure in the vertical center of the cell
65
	 * 
66
	 * <code>GridLayoutData.END = SWT.END - 1</code> (or
67
	 * <code>SWT.BOTTOM - 1</code>): Position the figure at the bottom of the
68
	 * cell
69
	 * 
70
	 * <code>GridLayoutData.FILL = SWT.FILL - 1</code>: Resize the figure to
71
	 * fill the cell vertically
72
	 */
73
    public int verticalAlignment = CENTER;
74
    
75
    /**
76
	 * horizontalAlignment specifies how figures will be positioned horizontally
77
	 * within a cell.
78
	 * 
79
	 * The default value is BEGINNING.
80
	 * 
81
	 * Possible values are:
82
	 * 
83
	 * <code>GridLayoutData.BEGINNING = SWT.BEGINNING - 1</code> (or
84
	 * <code>SWT.TOP - 1</code>): Position the figure at the left of the cell
85
	 * 
86
	 * <code>GridLayoutData.CENTER = SWT.CENTER - 1</code>: Position the
87
	 * figure in the horizontal center of the cell
88
	 * 
89
	 * <code>GridLayoutData.END = SWT.END - 1</code> (or
90
	 * <code>SWT.BOTTOM - 1</code>): Position the figure at the right of the
91
	 * cell
92
	 * 
93
	 * <code>GridLayoutData.FILL = SWT.FILL - 1</code>: : Resize the figure
94
	 * to fill the cell horizontally
95
	 */
96
    public int horizontalAlignment = BEGINNING;
97
    
98
    /**
99
     * widthHint specifies a minimum width for the column. A value of 
100
     * SWT.DEFAULT indicates that no minimum width is specified.
101
     *
102
     * The default value is SWT.DEFAULT.
103
     */
104
    public int widthHint = SWT.DEFAULT;
105
    
106
    /**
107
     * heightHint specifies a minimum height for the row. A value of
108
     * SWT.DEFAULT indicates that no minimum height is specified.
109
     *
110
     * The default value is SWT.DEFAULT.
111
     */
112
    public int heightHint = SWT.DEFAULT;
113
    
114
    /**
115
     * horizontalIndent specifies the number of pixels of indentation
116
     * that will be placed along the left side of the cell.
117
     *
118
     * The default value is 0.
119
     */
120
    public int horizontalIndent = 0;
121
    
122
    /**
123
     * horizontalSpan specifies the number of column cells that the figure
124
     * will take up.
125
     *
126
     * The default value is 1.
127
     */
128
    public int horizontalSpan = 1;
129
    
130
    /**
131
     * verticalSpan specifies the number of row cells that the figure
132
     * will take up.
133
     *
134
     * The default value is 1.
135
     */
136
    public int verticalSpan = 1;
137
    
138
    /**
139
     * grabExcessHorizontalSpace specifies whether the cell will be made
140
     * wide enough to fit the remaining horizontal space.
141
     *
142
     * The default value is false.
143
     */ 
144
    public boolean grabExcessHorizontalSpace = false;
145
    
146
    /**
147
     * grabExcessVerticalSpace specifies whether the cell will be made
148
     * tall enough to fit the remaining vertical space.
149
     *
150
     * The default value is false.
151
     */ 
152
    public boolean grabExcessVerticalSpace = false;
153
154
    /**
155
     * Value for horizontalAlignment or verticalAlignment.
156
     * Position the figure at the top or left of the cell.
157
     */
158
    public static final int BEGINNING = 0; //SWT.BEGINNING - 1;
159
    
160
    /**
161
     * Value for horizontalAlignment or verticalAlignment.
162
     * Position the figure in the vertical or horizontal center of the cell
163
     */
164
    public static final int CENTER = 1;
165
    
166
    /**
167
     * Value for horizontalAlignment or verticalAlignment.
168
     * Position the figure at the bottom or right of the cell
169
     */
170
    public static final int END = 2;
171
    
172
    /**
173
     * Value for horizontalAlignment or verticalAlignment.
174
     * Resize the figure to fill the cell horizontally or vertically.
175
     */
176
    public static final int FILL = 3; //SWT.FILL - 1;
177
178
    /**
179
     * Style bit for <code>new GridLayoutData(int)</code>.
180
     * Position the figure at the top of the cell.
181
     * Not recommended. Use 
182
     * <code>new GridLayoutData(int, GridLayoutData.BEGINNING, boolean, boolean)</code>
183
     * instead.
184
     */
185
    public static final int VERTICAL_ALIGN_BEGINNING =  1 << 1;
186
    
187
    /**
188
     * Style bit for <code>new GridLayoutData(int)</code> to position the 
189
     * figure in the vertical center of the cell.
190
     * Not recommended. Use
191
     * <code>new GridLayoutData(int, GridLayoutData.CENTER, boolean, boolean)</code>
192
     * instead.
193
     */
194
    public static final int VERTICAL_ALIGN_CENTER = 1 << 2;
195
    
196
    /**
197
     * Style bit for <code>new GridLayoutData(int)</code> to position the 
198
     * figure at the bottom of the cell.
199
     * Not recommended. Use
200
     * <code>new GridLayoutData(int, GridLayoutData.END, boolean, boolean)</code>
201
     * instead.
202
     */
203
    public static final int VERTICAL_ALIGN_END = 1 << 3;
204
    
205
    /**
206
     * Style bit for <code>new GridLayoutData(int)</code> to resize the 
207
     * figure to fill the cell vertically.
208
     * Not recommended. Use
209
     * <code>new GridLayoutData(int, GridLayoutData.FILL, boolean, boolean)</code>
210
     * instead
211
     */
212
    public static final int VERTICAL_ALIGN_FILL = 1 << 4;
213
    
214
    /**
215
     * Style bit for <code>new GridLayoutData(int)</code> to position the 
216
     * figure at the left of the cell.
217
     * Not recommended. Use
218
     * <code>new GridLayoutData(GridLayoutData.BEGINNING, int, boolean, boolean)</code>
219
     * instead.
220
     */
221
    public static final int HORIZONTAL_ALIGN_BEGINNING =  1 << 5;
222
    
223
    /**
224
     * Style bit for <code>new GridLayoutData(int)</code> to position the 
225
     * figure in the horizontal center of the cell.
226
     * Not recommended. Use
227
     * <code>new GridLayoutData(GridLayoutData.CENTER, int, boolean, boolean)</code>
228
     * instead.
229
     */
230
    public static final int HORIZONTAL_ALIGN_CENTER = 1 << 6;
231
    
232
    /**
233
     * Style bit for <code>new GridLayoutData(int)</code> to position the 
234
     * figure at the right of the cell.
235
     * Not recommended. Use
236
     * <code>new GridLayoutData(GridLayoutData.END, int, boolean, boolean)</code>
237
     * instead.
238
     */
239
    public static final int HORIZONTAL_ALIGN_END = 1 << 7;
240
    
241
    /**
242
     * Style bit for <code>new GridLayoutData(int)</code> to resize the 
243
     * figure to fill the cell horizontally.
244
     * Not recommended. Use
245
     * <code>new GridLayoutData(GridLayoutData.FILL, int, boolean, boolean)</code>
246
     * instead.
247
     */
248
    public static final int HORIZONTAL_ALIGN_FILL = 1 << 8;
249
    
250
    /**
251
     * Style bit for <code>new GridLayoutData(int)</code> to resize the 
252
     * figure to fit the remaining horizontal space.
253
     * Not recommended. Use
254
     * <code>new GridLayoutData(int, int, true, boolean)</code>
255
     * instead.
256
     */
257
    public static final int GRAB_HORIZONTAL = 1 << 9;
258
    
259
    /**
260
     * Style bit for <code>new GridLayoutData(int)</code> to resize the 
261
     * figure to fit the remaining vertical space.
262
     * Not recommended. Use
263
     * <code>new GridLayoutData(int, int, boolean, true)</code>
264
     * instead.
265
     */
266
    public static final int GRAB_VERTICAL = 1 << 10;
267
    
268
    /**
269
     * Style bit for <code>new GridLayoutData(int)</code> to resize the 
270
     * figure to fill the cell vertically and to fit the remaining
271
     * vertical space.
272
     * FILL_VERTICAL = VERTICAL_ALIGN_FILL | GRAB_VERTICAL
273
     * Not recommended. Use
274
     * <code>new GridLayoutData(int, GridLayoutData.FILL, boolean, true)</code>
275
     * instead.
276
     */ 
277
    public static final int FILL_VERTICAL = VERTICAL_ALIGN_FILL | GRAB_VERTICAL;
278
    
279
    /**
280
     * Style bit for <code>new GridLayoutData(int)</code> to resize the 
281
     * figure to fill the cell horizontally and to fit the remaining
282
     * horizontal space.
283
     * FILL_HORIZONTAL = HORIZONTAL_ALIGN_FILL | GRAB_HORIZONTAL
284
     * Not recommended. Use
285
     * <code>new GridLayoutData(GridLayoutData.FILL, int, true, boolean)</code>
286
     * instead.
287
     */ 
288
    public static final int FILL_HORIZONTAL = HORIZONTAL_ALIGN_FILL | GRAB_HORIZONTAL;
289
    
290
    /**
291
     * Style bit for <code>new GridLayoutData(int)</code> to resize the 
292
     * figure to fill the cell horizontally and vertically and 
293
     * to fit the remaining horizontal and vertical space.
294
     * FILL_BOTH = FILL_VERTICAL | FILL_HORIZONTAL
295
     * Not recommended. Use
296
     * <code>new GridLayoutData(GridLayoutData.FILL, GridLayoutData.FILL, true, true)</code>
297
     * instead.
298
     */ 
299
    public static final int FILL_BOTH = FILL_VERTICAL | FILL_HORIZONTAL;
300
301
    int cacheWidth = -1, cacheHeight = -1;
302
    int [][] cache = new int[2][4];
303
    int cacheIndex = -1;
304
305
/**
306
 * Constructs a new instance of GridLayoutData using
307
 * default values.
308
 */
309
public GridLayoutData () {
310
    super ();
311
}
312
313
/**
314
 * Constructs a new instance based on the GridLayoutData style.
315
 * This constructor is not recommended.
316
 * 
317
 * @param style the GridLayoutData style
318
 */
319
public GridLayoutData (int style) {
320
    super ();
321
    if ((style & VERTICAL_ALIGN_BEGINNING) != 0) verticalAlignment = BEGINNING;
322
    if ((style & VERTICAL_ALIGN_CENTER) != 0) verticalAlignment = CENTER;
323
    if ((style & VERTICAL_ALIGN_FILL) != 0) verticalAlignment = FILL;
324
    if ((style & VERTICAL_ALIGN_END) != 0) verticalAlignment = END;
325
    if ((style & HORIZONTAL_ALIGN_BEGINNING) != 0) horizontalAlignment = BEGINNING;
326
    if ((style & HORIZONTAL_ALIGN_CENTER) != 0) horizontalAlignment = CENTER;
327
    if ((style & HORIZONTAL_ALIGN_FILL) != 0) horizontalAlignment = FILL;
328
    if ((style & HORIZONTAL_ALIGN_END) != 0) horizontalAlignment = END;
329
    grabExcessHorizontalSpace = (style & GRAB_HORIZONTAL) != 0;
330
    grabExcessVerticalSpace = (style & GRAB_VERTICAL) != 0;
331
}
332
333
/**
334
 * Constructs a new instance of GridLayoutData according to the parameters.
335
 * 
336
 * @param horizontalAlignment how figure will be positioned horizontally within a cell
337
 * @param verticalAlignment how figure will be positioned vertically within a cell
338
 * @param grabExcessHorizontalSpace whether cell will be made wide enough to fit the remaining horizontal space
339
 * @param grabExcessVerticalSpace whether cell will be made high enough to fit the remaining vertical space
340
 * 
341
 */
342
public GridLayoutData (int horizontalAlignment, int verticalAlignment, boolean grabExcessHorizontalSpace, boolean grabExcessVerticalSpace) {
343
    this (horizontalAlignment, verticalAlignment, grabExcessHorizontalSpace, grabExcessVerticalSpace, 1, 1);
344
}
345
346
/**
347
 * Constructs a new instance of GridLayoutData according to the parameters.
348
 *  
349
 * @param horizontalAlignment how figure will be positioned horizontally within a cell
350
 * @param verticalAlignment how figure will be positioned vertically within a cell
351
 * @param grabExcessHorizontalSpace whether cell will be made wide enough to fit the remaining horizontal space
352
 * @param grabExcessVerticalSpace whether cell will be made high enough to fit the remaining vertical space
353
 * @param horizontalSpan the number of column cells that the figure will take up
354
 * @param verticalSpan the number of row cells that the figure will take up
355
 * 
356
 */
357
public GridLayoutData (int horizontalAlignment, int verticalAlignment, boolean grabExcessHorizontalSpace, boolean grabExcessVerticalSpace, int horizontalSpan, int verticalSpan) {
358
    super ();
359
    this.horizontalAlignment = horizontalAlignment;
360
    this.verticalAlignment = verticalAlignment;
361
    this.grabExcessHorizontalSpace = grabExcessHorizontalSpace;
362
    this.grabExcessVerticalSpace = grabExcessVerticalSpace;
363
    this.horizontalSpan = horizontalSpan;
364
    this.verticalSpan = verticalSpan;
365
}
366
367
/**
368
 * Constructs a new instance of GridLayoutData according to the parameters.
369
 * A value of SWT.DEFAULT indicates that no minimum width or
370
 * no minumum height is specified.
371
 * 
372
 * @param width a minimum width for the column
373
 * @param height a minimum height for the row
374
 * 
375
 */
376
public GridLayoutData (int width, int height) {
377
    super ();
378
    this.widthHint = width;
379
    this.heightHint = height;
380
}
381
382
Dimension computeSize (IFigure figure, boolean flushCache) {
383
    if (cacheWidth != -1 && cacheHeight != -1) {
384
        return new Dimension (cacheWidth, cacheHeight);
385
    }
386
    for (int i = 0; i < cacheIndex + 1; i++) {
387
        if (cache [i][0] == widthHint && cache [i][1] == heightHint) {
388
            cacheWidth = cache [i][2];
389
            cacheHeight = cache [i][3];
390
            return new Dimension (cacheWidth, cacheHeight);
391
        }
392
    }
393
394
    Dimension size = figure.getPreferredSize(widthHint,heightHint);
395
    if (widthHint!=-1) size.width = widthHint;
396
    if (heightHint!=-1) size.height = heightHint;    
397
398
    if (cacheIndex < cache.length - 1) cacheIndex++;
399
    cache [cacheIndex][0] = widthHint;
400
    cache [cacheIndex][1] = heightHint;
401
    cacheWidth = cache [cacheIndex][2] = size.width;
402
    cacheHeight = cache [cacheIndex][3] = size.height;
403
    return size;
404
}
405
406
407
void flushCache () {
408
    cacheWidth = cacheHeight = -1;
409
    cacheIndex = -1;
410
}
411
412
String getName () {
413
    String string = getClass ().getName ();
414
    int index = string.lastIndexOf ('.');
415
    if (index == -1) return string;
416
    return string.substring (index + 1, string.length ());
417
}
418
419
public String toString () {
420
421
    String hAlign = "";
422
    switch (horizontalAlignment) {
423
        case FILL: hAlign = "GridLayoutData.FILL"; break;
424
        case BEGINNING: hAlign = "GridLayoutData.BEGINNING"; break;
425
        case END: hAlign = "GridLayoutData.LEFT"; break;
426
        case CENTER: hAlign = "GridLayoutData.CENTER"; break;
427
        default: hAlign = "Undefined "+horizontalAlignment; break;
428
    }
429
    String vAlign = "";
430
    switch (verticalAlignment) {
431
        case FILL: vAlign = "GridLayoutData.FILL"; break;
432
        case BEGINNING: vAlign = "GridLayoutData.BEGINNING"; break;
433
        case END: vAlign = "GridLayoutData.END"; break;
434
        case CENTER: vAlign = "GridLayoutData.CENTER"; break;
435
        default: vAlign = "Undefined "+verticalAlignment; break;
436
    }
437
    String string = getName()+" {";
438
    string += "horizontalAlignment="+hAlign+" ";
439
    if (horizontalIndent != 0) string += "horizontalIndent="+horizontalIndent+" ";
440
    if (horizontalSpan != 1) string += "horizontalSpan="+horizontalSpan+" ";
441
    if (grabExcessHorizontalSpace) string += "grabExcessHorizontalSpace="+grabExcessHorizontalSpace+" ";
442
    if (widthHint != SWT.DEFAULT) string += "widthHint="+widthHint+" ";
443
    string += "verticalAlignment="+vAlign+" ";
444
    if (verticalSpan != 1) string += "verticalSpan="+verticalSpan+" ";
445
    if (grabExcessVerticalSpace) string += "grabExcessVerticalSpace="+grabExcessVerticalSpace+" ";
446
    if (heightHint != SWT.DEFAULT) string += "heightHint="+heightHint+" ";
447
    string = string.trim();
448
    string += "}";
449
    return string;
450
451
}
452
453
}

Return to bug 133279