1 /******************************************************************************* 2 * Copyright (c) 2000, 2008 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 * Port to the D programming language: 11 * Frank Benoit <benoit@tionex.de> 12 *******************************************************************************/ 13 module org.eclipse.swt.layout.GridLayout; 14 15 import org.eclipse.swt.layout.GridData; 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.Control; 20 import org.eclipse.swt.widgets.Composite; 21 import org.eclipse.swt.widgets.Layout; 22 import org.eclipse.swt.widgets.Scrollable; 23 24 import java.lang.System; 25 26 import java.lang.all; 27 28 29 /** 30 * Instances of this class lay out the control children of a 31 * <code>Composite</code> in a grid. 32 * <p> 33 * <code>GridLayout</code> has a number of configuration fields, and the 34 * controls it lays out can have an associated layout data object, called 35 * <code>GridData</code>. The power of <code>GridLayout</code> lies in the 36 * ability to configure <code>GridData</code> for each control in the layout. 37 * </p> 38 * <p> 39 * The following code creates a shell managed by a <code>GridLayout</code> 40 * with 3 columns: 41 * <pre> 42 * Display display = new Display(); 43 * Shell shell = new Shell(display); 44 * GridLayout gridLayout = new GridLayout(); 45 * gridLayout.numColumns = 3; 46 * shell.setLayout(gridLayout); 47 * </pre> 48 * The <code>numColumns</code> field is the most important field in a 49 * <code>GridLayout</code>. Widgets are laid out in columns from left 50 * to right, and a new row is created when <code>numColumns</code> + 1 51 * controls are added to the <code>Composite<code>. 52 * </p> 53 * 54 * @see GridData 55 * @see <a href="http://www.eclipse.org/swt/snippets/#gridlayout">GridLayout snippets</a> 56 * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: LayoutExample</a> 57 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> 58 */ 59 public final class GridLayout : Layout { 60 61 /** 62 * numColumns specifies the number of cell columns in the layout. 63 * If numColumns has a value less than 1, the layout will not 64 * set the size and position of any controls. 65 * 66 * The default value is 1. 67 */ 68 public int numColumns = 1; 69 70 /** 71 * makeColumnsEqualWidth specifies whether all columns in the layout 72 * will be forced to have the same width. 73 * 74 * The default value is false. 75 */ 76 public bool makeColumnsEqualWidth = false; 77 78 /** 79 * marginWidth specifies the number of pixels of horizontal margin 80 * that will be placed along the left and right edges of the layout. 81 * 82 * The default value is 5. 83 */ 84 public int marginWidth = 5; 85 86 /** 87 * marginHeight specifies the number of pixels of vertical margin 88 * that will be placed along the top and bottom edges of the layout. 89 * 90 * The default value is 5. 91 */ 92 public int marginHeight = 5; 93 94 /** 95 * marginLeft specifies the number of pixels of horizontal margin 96 * that will be placed along the left edge of the layout. 97 * 98 * The default value is 0. 99 * 100 * @since 3.1 101 */ 102 public int marginLeft = 0; 103 104 /** 105 * marginTop specifies the number of pixels of vertical margin 106 * that will be placed along the top edge of the layout. 107 * 108 * The default value is 0. 109 * 110 * @since 3.1 111 */ 112 public int marginTop = 0; 113 114 /** 115 * marginRight specifies the number of pixels of horizontal margin 116 * that will be placed along the right edge of the layout. 117 * 118 * The default value is 0. 119 * 120 * @since 3.1 121 */ 122 public int marginRight = 0; 123 124 /** 125 * marginBottom specifies the number of pixels of vertical margin 126 * that will be placed along the bottom edge of the layout. 127 * 128 * The default value is 0. 129 * 130 * @since 3.1 131 */ 132 public int marginBottom = 0; 133 134 /** 135 * horizontalSpacing specifies the number of pixels between the right 136 * edge of one cell and the left edge of its neighbouring cell to 137 * the right. 138 * 139 * The default value is 5. 140 */ 141 public int horizontalSpacing = 5; 142 143 /** 144 * verticalSpacing specifies the number of pixels between the bottom 145 * edge of one cell and the top edge of its neighbouring cell underneath. 146 * 147 * The default value is 5. 148 */ 149 public int verticalSpacing = 5; 150 151 /** 152 * Constructs a new instance of this class. 153 */ 154 public this () {} 155 156 /** 157 * Constructs a new instance of this class given the 158 * number of columns, and whether or not the columns 159 * should be forced to have the same width. 160 * If numColumns has a value less than 1, the layout will not 161 * set the size and position of any controls. 162 * 163 * @param numColumns the number of columns in the grid 164 * @param makeColumnsEqualWidth whether or not the columns will have equal width 165 * 166 * @since 2.0 167 */ 168 public this (int numColumns, bool makeColumnsEqualWidth) { 169 this.numColumns = numColumns; 170 this.makeColumnsEqualWidth = makeColumnsEqualWidth; 171 } 172 173 override protected Point computeSize (Composite composite, int wHint, int hHint, bool flushCache_) { 174 Point size = layout (composite, false, 0, 0, wHint, hHint, flushCache_); 175 if (wHint !is SWT.DEFAULT) size.x = wHint; 176 if (hHint !is SWT.DEFAULT) size.y = hHint; 177 return size; 178 } 179 180 override protected bool flushCache (Control control) { 181 Object data = control.getLayoutData (); 182 if (data !is null) (cast(GridData) data).flushCache (); 183 return true; 184 } 185 186 GridData getData (Control [][] grid, int row, int column, int rowCount, int columnCount, bool first) { 187 Control control = grid [row] [column]; 188 if (control !is null) { 189 GridData data = cast(GridData) control.getLayoutData (); 190 int hSpan = Math.max (1, Math.min (data.horizontalSpan, columnCount)); 191 int vSpan = Math.max (1, data.verticalSpan); 192 int i = first ? row + vSpan - 1 : row - vSpan + 1; 193 int j = first ? column + hSpan - 1 : column - hSpan + 1; 194 if (0 <= i && i < rowCount) { 195 if (0 <= j && j < columnCount) { 196 if (control is grid [i][j]) return data; 197 } 198 } 199 } 200 return null; 201 } 202 203 override protected void layout (Composite composite, bool flushCache_) { 204 Rectangle rect = composite.getClientArea (); 205 layout (composite, true, rect.x, rect.y, rect.width, rect.height, flushCache_); 206 } 207 208 Point layout (Composite composite, bool move, int x, int y, int width, int height, bool flushCache_) { 209 if (numColumns < 1) { 210 return new Point (marginLeft + marginWidth * 2 + marginRight, marginTop + marginHeight * 2 + marginBottom); 211 } 212 Control [] children = composite.getChildren (); 213 int count = 0; 214 for (int i=0; i<children.length; i++) { 215 Control control = children [i]; 216 GridData data = cast(GridData) control.getLayoutData (); 217 if (data is null || !data.exclude) { 218 children [count++] = children [i]; 219 } 220 } 221 if (count is 0) { 222 return new Point (marginLeft + marginWidth * 2 + marginRight, marginTop + marginHeight * 2 + marginBottom); 223 } 224 for (int i=0; i<count; i++) { 225 Control child = children [i]; 226 GridData data = cast(GridData) child.getLayoutData (); 227 if (data is null) child.setLayoutData (data = new GridData ()); 228 if (flushCache_) data.flushCache (); 229 data.computeSize (child, data.widthHint, data.heightHint, flushCache_); 230 if (data.grabExcessHorizontalSpace && data.minimumWidth > 0) { 231 if (data.cacheWidth < data.minimumWidth) { 232 int trim = 0; 233 //TEMPORARY CODE 234 if ( auto sa = cast(Scrollable)child ) { 235 Rectangle rect = sa.computeTrim (0, 0, 0, 0); 236 trim = rect.width; 237 } else { 238 trim = child.getBorderWidth () * 2; 239 } 240 data.cacheWidth = data.cacheHeight = SWT.DEFAULT; 241 data.computeSize (child, Math.max (0, data.minimumWidth - trim), data.heightHint, false); 242 } 243 } 244 if (data.grabExcessVerticalSpace && data.minimumHeight > 0) { 245 data.cacheHeight = Math.max (data.cacheHeight, data.minimumHeight); 246 } 247 } 248 249 /* Build the grid */ 250 int row = 0, column = 0, rowCount = 0, columnCount = numColumns; 251 Control [][] grid = new Control [][]( 4, columnCount ); 252 for (int i=0; i<count; i++) { 253 Control child = children [i]; 254 GridData data = cast(GridData) child.getLayoutData (); 255 int hSpan = Math.max (1, Math.min (data.horizontalSpan, columnCount)); 256 int vSpan = Math.max (1, data.verticalSpan); 257 while (true) { 258 int lastRow = row + vSpan; 259 if (lastRow >= grid.length) { 260 Control [][] newGrid = new Control[][]( lastRow + 4, columnCount ); 261 SimpleType!(Control[]).arraycopy (grid, 0, newGrid, 0, cast(int)/*64bit*/grid.length); 262 grid = newGrid; 263 } 264 if (grid [row] is null) { 265 grid [row] = new Control [columnCount]; 266 } 267 while (column < columnCount && grid [row] [column] !is null) { 268 column++; 269 } 270 int endCount = column + hSpan; 271 if (endCount <= columnCount) { 272 int index = column; 273 while (index < endCount && grid [row] [index] is null) { 274 index++; 275 } 276 if (index is endCount) break; 277 column = index; 278 } 279 if (column + hSpan >= columnCount) { 280 column = 0; 281 row++; 282 } 283 } 284 for (int j=0; j<vSpan; j++) { 285 if (grid [row + j] is null) { 286 grid [row + j] = new Control [columnCount]; 287 } 288 for (int k=0; k<hSpan; k++) { 289 grid [row + j] [column + k] = child; 290 } 291 } 292 rowCount = Math.max (rowCount, row + vSpan); 293 column += hSpan; 294 } 295 296 /* Column widths */ 297 int availableWidth = width - horizontalSpacing * (columnCount - 1) - (marginLeft + marginWidth * 2 + marginRight); 298 int expandCount = 0; 299 int [] widths = new int [columnCount]; 300 int [] minWidths = new int [columnCount]; 301 bool [] expandColumn = new bool [columnCount]; 302 for (int j=0; j<columnCount; j++) { 303 for (int i=0; i<rowCount; i++) { 304 GridData data = getData (grid, i, j, rowCount, columnCount, true); 305 if (data !is null) { 306 int hSpan = Math.max (1, Math.min (data.horizontalSpan, columnCount)); 307 if (hSpan is 1) { 308 int w = data.cacheWidth + data.horizontalIndent; 309 widths [j] = Math.max (widths [j], w); 310 if (data.grabExcessHorizontalSpace) { 311 if (!expandColumn [j]) expandCount++; 312 expandColumn [j] = true; 313 } 314 if (!data.grabExcessHorizontalSpace || data.minimumWidth !is 0) { 315 w = !data.grabExcessHorizontalSpace || data.minimumWidth is SWT.DEFAULT ? data.cacheWidth : data.minimumWidth; 316 w += data.horizontalIndent; 317 minWidths [j] = Math.max (minWidths [j], w); 318 } 319 } 320 } 321 } 322 for (int i=0; i<rowCount; i++) { 323 GridData data = getData (grid, i, j, rowCount, columnCount, false); 324 if (data !is null) { 325 int hSpan = Math.max (1, Math.min (data.horizontalSpan, columnCount)); 326 if (hSpan > 1) { 327 int spanWidth = 0, spanMinWidth = 0, spanExpandCount = 0; 328 for (int k=0; k<hSpan; k++) { 329 spanWidth += widths [j-k]; 330 spanMinWidth += minWidths [j-k]; 331 if (expandColumn [j-k]) spanExpandCount++; 332 } 333 if (data.grabExcessHorizontalSpace && spanExpandCount is 0) { 334 expandCount++; 335 expandColumn [j] = true; 336 } 337 int w = data.cacheWidth + data.horizontalIndent - spanWidth - (hSpan - 1) * horizontalSpacing; 338 if (w > 0) { 339 if (makeColumnsEqualWidth) { 340 int equalWidth = (w + spanWidth) / hSpan; 341 int remainder = (w + spanWidth) % hSpan, last = -1; 342 for (int k = 0; k < hSpan; k++) { 343 widths [last=j-k] = Math.max (equalWidth, widths [j-k]); 344 } 345 if (last > -1) widths [last] += remainder; 346 } else { 347 if (spanExpandCount is 0) { 348 widths [j] += w; 349 } else { 350 int delta = w / spanExpandCount; 351 int remainder = w % spanExpandCount, last = -1; 352 for (int k = 0; k < hSpan; k++) { 353 if (expandColumn [j-k]) { 354 widths [last=j-k] += delta; 355 } 356 } 357 if (last > -1) widths [last] += remainder; 358 } 359 } 360 } 361 if (!data.grabExcessHorizontalSpace || data.minimumWidth !is 0) { 362 w = !data.grabExcessHorizontalSpace || data.minimumWidth is SWT.DEFAULT ? data.cacheWidth : data.minimumWidth; 363 w += data.horizontalIndent - spanMinWidth - (hSpan - 1) * horizontalSpacing; 364 if (w > 0) { 365 if (spanExpandCount is 0) { 366 minWidths [j] += w; 367 } else { 368 int delta = w / spanExpandCount; 369 int remainder = w % spanExpandCount, last = -1; 370 for (int k = 0; k < hSpan; k++) { 371 if (expandColumn [j-k]) { 372 minWidths [last=j-k] += delta; 373 } 374 } 375 if (last > -1) minWidths [last] += remainder; 376 } 377 } 378 } 379 } 380 } 381 } 382 } 383 if (makeColumnsEqualWidth) { 384 int minColumnWidth = 0; 385 int columnWidth = 0; 386 for (int i=0; i<columnCount; i++) { 387 minColumnWidth = Math.max (minColumnWidth, minWidths [i]); 388 columnWidth = Math.max (columnWidth, widths [i]); 389 } 390 columnWidth = width is SWT.DEFAULT || expandCount is 0 ? columnWidth : Math.max (minColumnWidth, availableWidth / columnCount); 391 for (int i=0; i<columnCount; i++) { 392 expandColumn [i] = expandCount > 0; 393 widths [i] = columnWidth; 394 } 395 } else { 396 if (width !is SWT.DEFAULT && expandCount > 0) { 397 int totalWidth = 0; 398 for (int i=0; i<columnCount; i++) { 399 totalWidth += widths [i]; 400 } 401 int c = expandCount; 402 int delta = (availableWidth - totalWidth) / c; 403 int remainder = (availableWidth - totalWidth) % c; 404 int last = -1; 405 while (totalWidth !is availableWidth) { 406 for (int j=0; j<columnCount; j++) { 407 if (expandColumn [j]) { 408 if (widths [j] + delta > minWidths [j]) { 409 widths [last = j] = widths [j] + delta; 410 } else { 411 widths [j] = minWidths [j]; 412 expandColumn [j] = false; 413 c--; 414 } 415 } 416 } 417 if (last > -1) widths [last] += remainder; 418 419 for (int j=0; j<columnCount; j++) { 420 for (int i=0; i<rowCount; i++) { 421 GridData data = getData (grid, i, j, rowCount, columnCount, false); 422 if (data !is null) { 423 int hSpan = Math.max (1, Math.min (data.horizontalSpan, columnCount)); 424 if (hSpan > 1) { 425 if (!data.grabExcessHorizontalSpace || data.minimumWidth !is 0) { 426 int spanWidth = 0, spanExpandCount = 0; 427 for (int k=0; k<hSpan; k++) { 428 spanWidth += widths [j-k]; 429 if (expandColumn [j-k]) spanExpandCount++; 430 } 431 int w = !data.grabExcessHorizontalSpace || data.minimumWidth is SWT.DEFAULT ? data.cacheWidth : data.minimumWidth; 432 w += data.horizontalIndent - spanWidth - (hSpan - 1) * horizontalSpacing; 433 if (w > 0) { 434 if (spanExpandCount is 0) { 435 widths [j] += w; 436 } else { 437 int delta2 = w / spanExpandCount; 438 int remainder2 = w % spanExpandCount, last2 = -1; 439 for (int k = 0; k < hSpan; k++) { 440 if (expandColumn [j-k]) { 441 widths [last2=j-k] += delta2; 442 } 443 } 444 if (last2 > -1) widths [last2] += remainder2; 445 } 446 } 447 } 448 } 449 } 450 } 451 } 452 if (c is 0) break; 453 totalWidth = 0; 454 for (int i=0; i<columnCount; i++) { 455 totalWidth += widths [i]; 456 } 457 delta = (availableWidth - totalWidth) / c; 458 remainder = (availableWidth - totalWidth) % c; 459 last = -1; 460 } 461 } 462 } 463 464 /* Wrapping */ 465 GridData [] flush = null; 466 int flushLength = 0; 467 if (width !is SWT.DEFAULT) { 468 for (int j=0; j<columnCount; j++) { 469 for (int i=0; i<rowCount; i++) { 470 GridData data = getData (grid, i, j, rowCount, columnCount, false); 471 if (data !is null) { 472 if (data.heightHint is SWT.DEFAULT) { 473 Control child = grid [i][j]; 474 //TEMPORARY CODE 475 int hSpan = Math.max (1, Math.min (data.horizontalSpan, columnCount)); 476 int currentWidth = 0; 477 for (int k=0; k<hSpan; k++) { 478 currentWidth += widths [j-k]; 479 } 480 currentWidth += (hSpan - 1) * horizontalSpacing - data.horizontalIndent; 481 if ((currentWidth !is data.cacheWidth && data.horizontalAlignment is SWT.FILL) || (data.cacheWidth > currentWidth)) { 482 int trim = 0; 483 if ( auto sa = cast(Scrollable)child ) { 484 Rectangle rect = sa.computeTrim (0, 0, 0, 0); 485 trim = rect.width; 486 } else { 487 trim = child.getBorderWidth () * 2; 488 } 489 data.cacheWidth = data.cacheHeight = SWT.DEFAULT; 490 data.computeSize (child, Math.max (0, currentWidth - trim), data.heightHint, false); 491 if (data.grabExcessVerticalSpace && data.minimumHeight > 0) { 492 data.cacheHeight = Math.max (data.cacheHeight, data.minimumHeight); 493 } 494 if (flush is null) flush = new GridData [count]; 495 flush [flushLength++] = data; 496 } 497 } 498 } 499 } 500 } 501 } 502 503 /* Row heights */ 504 int availableHeight = height - verticalSpacing * (rowCount - 1) - (marginTop + marginHeight * 2 + marginBottom); 505 expandCount = 0; 506 int [] heights = new int [rowCount]; 507 int [] minHeights = new int [rowCount]; 508 bool [] expandRow = new bool [rowCount]; 509 for (int i=0; i<rowCount; i++) { 510 for (int j=0; j<columnCount; j++) { 511 GridData data = getData (grid, i, j, rowCount, columnCount, true); 512 if (data !is null) { 513 int vSpan = Math.max (1, Math.min (data.verticalSpan, rowCount)); 514 if (vSpan is 1) { 515 int h = data.cacheHeight + data.verticalIndent; 516 heights [i] = Math.max (heights [i], h); 517 if (data.grabExcessVerticalSpace) { 518 if (!expandRow [i]) expandCount++; 519 expandRow [i] = true; 520 } 521 if (!data.grabExcessVerticalSpace || data.minimumHeight !is 0) { 522 h = !data.grabExcessVerticalSpace || data.minimumHeight is SWT.DEFAULT ? data.cacheHeight : data.minimumHeight; 523 h += data.verticalIndent; 524 minHeights [i] = Math.max (minHeights [i], h); 525 } 526 } 527 } 528 } 529 for (int j=0; j<columnCount; j++) { 530 GridData data = getData (grid, i, j, rowCount, columnCount, false); 531 if (data !is null) { 532 int vSpan = Math.max (1, Math.min (data.verticalSpan, rowCount)); 533 if (vSpan > 1) { 534 int spanHeight = 0, spanMinHeight = 0, spanExpandCount = 0; 535 for (int k=0; k<vSpan; k++) { 536 spanHeight += heights [i-k]; 537 spanMinHeight += minHeights [i-k]; 538 if (expandRow [i-k]) spanExpandCount++; 539 } 540 if (data.grabExcessVerticalSpace && spanExpandCount is 0) { 541 expandCount++; 542 expandRow [i] = true; 543 } 544 int h = data.cacheHeight + data.verticalIndent - spanHeight - (vSpan - 1) * verticalSpacing; 545 if (h > 0) { 546 if (spanExpandCount is 0) { 547 heights [i] += h; 548 } else { 549 int delta = h / spanExpandCount; 550 int remainder = h % spanExpandCount, last = -1; 551 for (int k = 0; k < vSpan; k++) { 552 if (expandRow [i-k]) { 553 heights [last=i-k] += delta; 554 } 555 } 556 if (last > -1) heights [last] += remainder; 557 } 558 } 559 if (!data.grabExcessVerticalSpace || data.minimumHeight !is 0) { 560 h = !data.grabExcessVerticalSpace || data.minimumHeight is SWT.DEFAULT ? data.cacheHeight : data.minimumHeight; 561 h += data.verticalIndent - spanMinHeight - (vSpan - 1) * verticalSpacing; 562 if (h > 0) { 563 if (spanExpandCount is 0) { 564 minHeights [i] += h; 565 } else { 566 int delta = h / spanExpandCount; 567 int remainder = h % spanExpandCount, last = -1; 568 for (int k = 0; k < vSpan; k++) { 569 if (expandRow [i-k]) { 570 minHeights [last=i-k] += delta; 571 } 572 } 573 if (last > -1) minHeights [last] += remainder; 574 } 575 } 576 } 577 } 578 } 579 } 580 } 581 if (height !is SWT.DEFAULT && expandCount > 0) { 582 int totalHeight = 0; 583 for (int i=0; i<rowCount; i++) { 584 totalHeight += heights [i]; 585 } 586 int c = expandCount; 587 int delta = (availableHeight - totalHeight) / c; 588 int remainder = (availableHeight - totalHeight) % c; 589 int last = -1; 590 while (totalHeight !is availableHeight) { 591 for (int i=0; i<rowCount; i++) { 592 if (expandRow [i]) { 593 if (heights [i] + delta > minHeights [i]) { 594 heights [last = i] = heights [i] + delta; 595 } else { 596 heights [i] = minHeights [i]; 597 expandRow [i] = false; 598 c--; 599 } 600 } 601 } 602 if (last > -1) heights [last] += remainder; 603 604 for (int i=0; i<rowCount; i++) { 605 for (int j=0; j<columnCount; j++) { 606 GridData data = getData (grid, i, j, rowCount, columnCount, false); 607 if (data !is null) { 608 int vSpan = Math.max (1, Math.min (data.verticalSpan, rowCount)); 609 if (vSpan > 1) { 610 if (!data.grabExcessVerticalSpace || data.minimumHeight !is 0) { 611 int spanHeight = 0, spanExpandCount = 0; 612 for (int k=0; k<vSpan; k++) { 613 spanHeight += heights [i-k]; 614 if (expandRow [i-k]) spanExpandCount++; 615 } 616 int h = !data.grabExcessVerticalSpace || data.minimumHeight is SWT.DEFAULT ? data.cacheHeight : data.minimumHeight; 617 h += data.verticalIndent - spanHeight - (vSpan - 1) * verticalSpacing; 618 if (h > 0) { 619 if (spanExpandCount is 0) { 620 heights [i] += h; 621 } else { 622 int delta2 = h / spanExpandCount; 623 int remainder2 = h % spanExpandCount, last2 = -1; 624 for (int k = 0; k < vSpan; k++) { 625 if (expandRow [i-k]) { 626 heights [last2=i-k] += delta2; 627 } 628 } 629 if (last2 > -1) heights [last2] += remainder2; 630 } 631 } 632 } 633 } 634 } 635 } 636 } 637 if (c is 0) break; 638 totalHeight = 0; 639 for (int i=0; i<rowCount; i++) { 640 totalHeight += heights [i]; 641 } 642 delta = (availableHeight - totalHeight) / c; 643 remainder = (availableHeight - totalHeight) % c; 644 last = -1; 645 } 646 } 647 648 /* Position the controls */ 649 if (move) { 650 int gridY = y + marginTop + marginHeight; 651 for (int i=0; i<rowCount; i++) { 652 int gridX = x + marginLeft + marginWidth; 653 for (int j=0; j<columnCount; j++) { 654 GridData data = getData (grid, i, j, rowCount, columnCount, true); 655 if (data !is null) { 656 int hSpan = Math.max (1, Math.min (data.horizontalSpan, columnCount)); 657 int vSpan = Math.max (1, data.verticalSpan); 658 int cellWidth = 0, cellHeight = 0; 659 for (int k=0; k<hSpan; k++) { 660 cellWidth += widths [j+k]; 661 } 662 for (int k=0; k<vSpan; k++) { 663 cellHeight += heights [i+k]; 664 } 665 cellWidth += horizontalSpacing * (hSpan - 1); 666 int childX = gridX + data.horizontalIndent; 667 int childWidth = Math.min (data.cacheWidth, cellWidth); 668 switch (data.horizontalAlignment) { 669 case SWT.CENTER: 670 case GridData.CENTER: 671 childX += Math.max (0, (cellWidth - data.horizontalIndent - childWidth) / 2); 672 break; 673 case SWT.RIGHT: 674 case SWT.END: 675 case GridData.END: 676 childX += Math.max (0, cellWidth - data.horizontalIndent - childWidth); 677 break; 678 case SWT.FILL: 679 childWidth = cellWidth - data.horizontalIndent; 680 break; 681 default: 682 } 683 cellHeight += verticalSpacing * (vSpan - 1); 684 int childY = gridY + data.verticalIndent; 685 int childHeight = Math.min (data.cacheHeight, cellHeight); 686 switch (data.verticalAlignment) { 687 case SWT.CENTER: 688 case GridData.CENTER: 689 childY += Math.max (0, (cellHeight - data.verticalIndent - childHeight) / 2); 690 break; 691 case SWT.BOTTOM: 692 case SWT.END: 693 case GridData.END: 694 childY += Math.max (0, cellHeight - data.verticalIndent - childHeight); 695 break; 696 case SWT.FILL: 697 childHeight = cellHeight - data.verticalIndent; 698 break; 699 default: 700 } 701 Control child = grid [i][j]; 702 if (child !is null) { 703 child.setBounds (childX, childY, childWidth, childHeight); 704 } 705 } 706 gridX += widths [j] + horizontalSpacing; 707 } 708 gridY += heights [i] + verticalSpacing; 709 } 710 } 711 712 // clean up cache 713 for (int i = 0; i < flushLength; i++) { 714 flush [i].cacheWidth = flush [i].cacheHeight = -1; 715 } 716 717 int totalDefaultWidth = 0; 718 int totalDefaultHeight = 0; 719 for (int i=0; i<columnCount; i++) { 720 totalDefaultWidth += widths [i]; 721 } 722 for (int i=0; i<rowCount; i++) { 723 totalDefaultHeight += heights [i]; 724 } 725 totalDefaultWidth += horizontalSpacing * (columnCount - 1) + marginLeft + marginWidth * 2 + marginRight; 726 totalDefaultHeight += verticalSpacing * (rowCount - 1) + marginTop + marginHeight * 2 + marginBottom; 727 return new Point (totalDefaultWidth, totalDefaultHeight); 728 } 729 730 String getName () { 731 String string = this.classinfo.name; 732 int index = string.lastIndexOf('.'); 733 if (index is -1 ) return string; 734 return string[ index + 1 .. string.length ]; 735 } 736 737 /** 738 * Returns a string containing a concise, human-readable 739 * description of the receiver. 740 * 741 * @return a string representation of the layout 742 */ 743 override public String toString () { 744 String string = getName ()~" {"; 745 if (numColumns !is 1) string ~= "numColumns="~String_valueOf(numColumns)~" "; 746 if (makeColumnsEqualWidth) string ~= "makeColumnsEqualWidth="~String_valueOf(makeColumnsEqualWidth)~" "; 747 if (marginWidth !is 0) string ~= "marginWidth="~String_valueOf(marginWidth)~" "; 748 if (marginHeight !is 0) string ~= "marginHeight="~String_valueOf(marginHeight)~" "; 749 if (marginLeft !is 0) string ~= "marginLeft="~String_valueOf(marginLeft)~" "; 750 if (marginRight !is 0) string ~= "marginRight="~String_valueOf(marginRight)~" "; 751 if (marginTop !is 0) string ~= "marginTop="~String_valueOf(marginTop)~" "; 752 if (marginBottom !is 0) string ~= "marginBottom="~String_valueOf(marginBottom)~" "; 753 if (horizontalSpacing !is 0) string ~= "horizontalSpacing="~String_valueOf(horizontalSpacing)~" "; 754 if (verticalSpacing !is 0) string ~= "verticalSpacing="~String_valueOf(verticalSpacing)~" "; 755 string = string.trim(); 756 string ~= "}"; 757 return string; 758 } 759 }