1 11 package org.eclipse.swt.layout; 12 13 import org.eclipse.swt.*; 14 import org.eclipse.swt.graphics.*; 15 import org.eclipse.swt.widgets.*; 16 17 44 public final class GridLayout extends Layout { 45 46 53 public int numColumns = 1; 54 55 61 public boolean makeColumnsEqualWidth = false; 62 63 69 public int marginWidth = 5; 70 71 77 public int marginHeight = 5; 78 79 87 public int marginLeft = 0; 88 89 97 public int marginTop = 0; 98 99 107 public int marginRight = 0; 108 109 117 public int marginBottom = 0; 118 119 126 public int horizontalSpacing = 5; 127 128 134 public int verticalSpacing = 5; 135 136 139 public GridLayout () {} 140 141 153 public GridLayout (int numColumns, boolean makeColumnsEqualWidth) { 154 this.numColumns = numColumns; 155 this.makeColumnsEqualWidth = makeColumnsEqualWidth; 156 } 157 158 protected Point computeSize (Composite composite, int wHint, int hHint, boolean flushCache) { 159 Point size = layout (composite, false, 0, 0, wHint, hHint, flushCache); 160 if (wHint != SWT.DEFAULT) size.x = wHint; 161 if (hHint != SWT.DEFAULT) size.y = hHint; 162 return size; 163 } 164 165 protected boolean flushCache (Control control) { 166 Object data = control.getLayoutData (); 167 if (data != null) ((GridData) data).flushCache (); 168 return true; 169 } 170 171 GridData getData (Control [][] grid, int row, int column, int rowCount, int columnCount, boolean first) { 172 Control control = grid [row] [column]; 173 if (control != null) { 174 GridData data = (GridData) control.getLayoutData (); 175 int hSpan = Math.max (1, Math.min (data.horizontalSpan, columnCount)); 176 int vSpan = Math.max (1, data.verticalSpan); 177 int i = first ? row + vSpan - 1 : row - vSpan + 1; 178 int j = first ? column + hSpan - 1 : column - hSpan + 1; 179 if (0 <= i && i < rowCount) { 180 if (0 <= j && j < columnCount) { 181 if (control == grid [i][j]) return data; 182 } 183 } 184 } 185 return null; 186 } 187 188 protected void layout (Composite composite, boolean flushCache) { 189 Rectangle rect = composite.getClientArea (); 190 layout (composite, true, rect.x, rect.y, rect.width, rect.height, flushCache); 191 } 192 193 Point layout (Composite composite, boolean move, int x, int y, int width, int height, boolean flushCache) { 194 if (numColumns < 1) { 195 return new Point (marginLeft + marginWidth * 2 + marginRight, marginTop + marginHeight * 2 + marginBottom); 196 } 197 Control [] children = composite.getChildren (); 198 int count = 0; 199 for (int i=0; i<children.length; i++) { 200 Control control = children [i]; 201 GridData data = (GridData) control.getLayoutData (); 202 if (data == null || !data.exclude) { 203 children [count++] = children [i]; 204 } 205 } 206 if (count == 0) { 207 return new Point (marginLeft + marginWidth * 2 + marginRight, marginTop + marginHeight * 2 + marginBottom); 208 } 209 for (int i=0; i<count; i++) { 210 Control child = children [i]; 211 GridData data = (GridData) child.getLayoutData (); 212 if (data == null) child.setLayoutData (data = new GridData ()); 213 if (flushCache) data.flushCache (); 214 data.computeSize (child, data.widthHint, data.heightHint, flushCache); 215 if (data.grabExcessHorizontalSpace && data.minimumWidth > 0) { 216 if (data.cacheWidth < data.minimumWidth) { 217 int trim = 0; 218 if (child instanceof Scrollable) { 220 Rectangle rect = ((Scrollable) child).computeTrim (0, 0, 0, 0); 221 trim = rect.width; 222 } else { 223 trim = child.getBorderWidth () * 2; 224 } 225 data.cacheWidth = data.cacheHeight = SWT.DEFAULT; 226 data.computeSize (child, Math.max (0, data.minimumWidth - trim), data.heightHint, false); 227 } 228 } 229 if (data.grabExcessVerticalSpace && data.minimumHeight > 0) { 230 data.cacheHeight = Math.max (data.cacheHeight, data.minimumHeight); 231 } 232 } 233 234 235 int row = 0, column = 0, rowCount = 0, columnCount = numColumns; 236 Control [][] grid = new Control [4] [columnCount]; 237 for (int i=0; i<count; i++) { 238 Control child = children [i]; 239 GridData data = (GridData) child.getLayoutData (); 240 int hSpan = Math.max (1, Math.min (data.horizontalSpan, columnCount)); 241 int vSpan = Math.max (1, data.verticalSpan); 242 while (true) { 243 int lastRow = row + vSpan; 244 if (lastRow >= grid.length) { 245 Control [][] newGrid = new Control [lastRow + 4] [columnCount]; 246 System.arraycopy (grid, 0, newGrid, 0, grid.length); 247 grid = newGrid; 248 } 249 if (grid [row] == null) { 250 grid [row] = new Control [columnCount]; 251 } 252 while (column < columnCount && grid [row] [column] != null) { 253 column++; 254 } 255 int endCount = column + hSpan; 256 if (endCount <= columnCount) { 257 int index = column; 258 while (index < endCount && grid [row] [index] == null) { 259 index++; 260 } 261 if (index == endCount) break; 262 column = index; 263 } 264 if (column + hSpan >= columnCount) { 265 column = 0; 266 row++; 267 } 268 } 269 for (int j=0; j<vSpan; j++) { 270 if (grid [row + j] == null) { 271 grid [row + j] = new Control [columnCount]; 272 } 273 for (int k=0; k<hSpan; k++) { 274 grid [row + j] [column + k] = child; 275 } 276 } 277 rowCount = Math.max (rowCount, row + vSpan); 278 column += hSpan; 279 } 280 281 282 int availableWidth = width - horizontalSpacing * (columnCount - 1) - (marginLeft + marginWidth * 2 + marginRight); 283 int expandCount = 0; 284 int [] widths = new int [columnCount]; 285 int [] minWidths = new int [columnCount]; 286 boolean [] expandColumn = new boolean [columnCount]; 287 for (int j=0; j<columnCount; j++) { 288 for (int i=0; i<rowCount; i++) { 289 GridData data = getData (grid, i, j, rowCount, columnCount, true); 290 if (data != null) { 291 int hSpan = Math.max (1, Math.min (data.horizontalSpan, columnCount)); 292 if (hSpan == 1) { 293 int w = data.cacheWidth + data.horizontalIndent; 294 widths [j] = Math.max (widths [j], w); 295 if (data.grabExcessHorizontalSpace) { 296 if (!expandColumn [j]) expandCount++; 297 expandColumn [j] = true; 298 } 299 if (!data.grabExcessHorizontalSpace || data.minimumWidth != 0) { 300 w = !data.grabExcessHorizontalSpace || data.minimumWidth == SWT.DEFAULT ? data.cacheWidth : data.minimumWidth; 301 w += data.horizontalIndent; 302 minWidths [j] = Math.max (minWidths [j], w); 303 } 304 } 305 } 306 } 307 for (int i=0; i<rowCount; i++) { 308 GridData data = getData (grid, i, j, rowCount, columnCount, false); 309 if (data != null) { 310 int hSpan = Math.max (1, Math.min (data.horizontalSpan, columnCount)); 311 if (hSpan > 1) { 312 int spanWidth = 0, spanMinWidth = 0, spanExpandCount = 0; 313 for (int k=0; k<hSpan; k++) { 314 spanWidth += widths [j-k]; 315 spanMinWidth += minWidths [j-k]; 316 if (expandColumn [j-k]) spanExpandCount++; 317 } 318 if (data.grabExcessHorizontalSpace && spanExpandCount == 0) { 319 expandCount++; 320 expandColumn [j] = true; 321 } 322 int w = data.cacheWidth + data.horizontalIndent - spanWidth - (hSpan - 1) * horizontalSpacing; 323 if (w > 0) { 324 if (makeColumnsEqualWidth) { 325 int equalWidth = (w + spanWidth) / hSpan; 326 int remainder = (w + spanWidth) % hSpan, last = -1; 327 for (int k = 0; k < hSpan; k++) { 328 widths [last=j-k] = Math.max (equalWidth, widths [j-k]); 329 } 330 if (last > -1) widths [last] += remainder; 331 } else { 332 if (spanExpandCount == 0) { 333 widths [j] += w; 334 } else { 335 int delta = w / spanExpandCount; 336 int remainder = w % spanExpandCount, last = -1; 337 for (int k = 0; k < hSpan; k++) { 338 if (expandColumn [j-k]) { 339 widths [last=j-k] += delta; 340 } 341 } 342 if (last > -1) widths [last] += remainder; 343 } 344 } 345 } 346 if (!data.grabExcessHorizontalSpace || data.minimumWidth != 0) { 347 w = !data.grabExcessHorizontalSpace || data.minimumWidth == SWT.DEFAULT ? data.cacheWidth : data.minimumWidth; 348 w += data.horizontalIndent - spanMinWidth - (hSpan - 1) * horizontalSpacing; 349 if (w > 0) { 350 if (spanExpandCount == 0) { 351 minWidths [j] += w; 352 } else { 353 int delta = w / spanExpandCount; 354 int remainder = w % spanExpandCount, last = -1; 355 for (int k = 0; k < hSpan; k++) { 356 if (expandColumn [j-k]) { 357 minWidths [last=j-k] += delta; 358 } 359 } 360 if (last > -1) minWidths [last] += remainder; 361 } 362 } 363 } 364 } 365 } 366 } 367 } 368 if (makeColumnsEqualWidth) { 369 int minColumnWidth = 0; 370 int columnWidth = 0; 371 for (int i=0; i<columnCount; i++) { 372 minColumnWidth = Math.max (minColumnWidth, minWidths [i]); 373 columnWidth = Math.max (columnWidth, widths [i]); 374 } 375 columnWidth = width == SWT.DEFAULT || expandCount == 0 ? columnWidth : Math.max (minColumnWidth, availableWidth / columnCount); 376 for (int i=0; i<columnCount; i++) { 377 expandColumn [i] = expandCount > 0; 378 widths [i] = columnWidth; 379 } 380 } else { 381 if (width != SWT.DEFAULT && expandCount > 0) { 382 int totalWidth = 0; 383 for (int i=0; i<columnCount; i++) { 384 totalWidth += widths [i]; 385 } 386 int c = expandCount; 387 int delta = (availableWidth - totalWidth) / c; 388 int remainder = (availableWidth - totalWidth) % c; 389 int last = -1; 390 while (totalWidth != availableWidth) { 391 for (int j=0; j<columnCount; j++) { 392 if (expandColumn [j]) { 393 if (widths [j] + delta > minWidths [j]) { 394 widths [last = j] = widths [j] + delta; 395 } else { 396 widths [j] = minWidths [j]; 397 expandColumn [j] = false; 398 c--; 399 } 400 } 401 } 402 if (last > -1) widths [last] += remainder; 403 404 for (int j=0; j<columnCount; j++) { 405 for (int i=0; i<rowCount; i++) { 406 GridData data = getData (grid, i, j, rowCount, columnCount, false); 407 if (data != null) { 408 int hSpan = Math.max (1, Math.min (data.horizontalSpan, columnCount)); 409 if (hSpan > 1) { 410 if (!data.grabExcessHorizontalSpace || data.minimumWidth != 0) { 411 int spanWidth = 0, spanExpandCount = 0; 412 for (int k=0; k<hSpan; k++) { 413 spanWidth += widths [j-k]; 414 if (expandColumn [j-k]) spanExpandCount++; 415 } 416 int w = !data.grabExcessHorizontalSpace || data.minimumWidth == SWT.DEFAULT ? data.cacheWidth : data.minimumWidth; 417 w += data.horizontalIndent - spanWidth - (hSpan - 1) * horizontalSpacing; 418 if (w > 0) { 419 if (spanExpandCount == 0) { 420 widths [j] += w; 421 } else { 422 int delta2 = w / spanExpandCount; 423 int remainder2 = w % spanExpandCount, last2 = -1; 424 for (int k = 0; k < hSpan; k++) { 425 if (expandColumn [j-k]) { 426 widths [last2=j-k] += delta2; 427 } 428 } 429 if (last2 > -1) widths [last2] += remainder2; 430 } 431 } 432 } 433 } 434 } 435 } 436 } 437 if (c == 0) break; 438 totalWidth = 0; 439 for (int i=0; i<columnCount; i++) { 440 totalWidth += widths [i]; 441 } 442 delta = (availableWidth - totalWidth) / c; 443 remainder = (availableWidth - totalWidth) % c; 444 last = -1; 445 } 446 } 447 } 448 449 450 GridData [] flush = null; 451 int flushLength = 0; 452 if (width != SWT.DEFAULT) { 453 for (int j=0; j<columnCount; j++) { 454 for (int i=0; i<rowCount; i++) { 455 GridData data = getData (grid, i, j, rowCount, columnCount, false); 456 if (data != null) { 457 if (data.heightHint == SWT.DEFAULT) { 458 Control child = grid [i][j]; 459 int hSpan = Math.max (1, Math.min (data.horizontalSpan, columnCount)); 461 int currentWidth = 0; 462 for (int k=0; k<hSpan; k++) { 463 currentWidth += widths [j-k]; 464 } 465 currentWidth += (hSpan - 1) * horizontalSpacing - data.horizontalIndent; 466 if ((currentWidth != data.cacheWidth && data.horizontalAlignment == SWT.FILL) || (data.cacheWidth > currentWidth)) { 467 int trim = 0; 468 if (child instanceof Scrollable) { 469 Rectangle rect = ((Scrollable) child).computeTrim (0, 0, 0, 0); 470 trim = rect.width; 471 } else { 472 trim = child.getBorderWidth () * 2; 473 } 474 data.cacheWidth = data.cacheHeight = SWT.DEFAULT; 475 data.computeSize (child, Math.max (0, currentWidth - trim), data.heightHint, false); 476 if (data.grabExcessVerticalSpace && data.minimumHeight > 0) { 477 data.cacheHeight = Math.max (data.cacheHeight, data.minimumHeight); 478 } 479 if (flush == null) flush = new GridData [count]; 480 flush [flushLength++] = data; 481 } 482 } 483 } 484 } 485 } 486 } 487 488 489 int availableHeight = height - verticalSpacing * (rowCount - 1) - (marginTop + marginHeight * 2 + marginBottom); 490 expandCount = 0; 491 int [] heights = new int [rowCount]; 492 int [] minHeights = new int [rowCount]; 493 boolean [] expandRow = new boolean [rowCount]; 494 for (int i=0; i<rowCount; i++) { 495 for (int j=0; j<columnCount; j++) { 496 GridData data = getData (grid, i, j, rowCount, columnCount, true); 497 if (data != null) { 498 int vSpan = Math.max (1, Math.min (data.verticalSpan, rowCount)); 499 if (vSpan == 1) { 500 int h = data.cacheHeight + data.verticalIndent; 501 heights [i] = Math.max (heights [i], h); 502 if (data.grabExcessVerticalSpace) { 503 if (!expandRow [i]) expandCount++; 504 expandRow [i] = true; 505 } 506 if (!data.grabExcessVerticalSpace || data.minimumHeight != 0) { 507 h = !data.grabExcessVerticalSpace || data.minimumHeight == SWT.DEFAULT ? data.cacheHeight : data.minimumHeight; 508 h += data.verticalIndent; 509 minHeights [i] = Math.max (minHeights [i], h); 510 } 511 } 512 } 513 } 514 for (int j=0; j<columnCount; j++) { 515 GridData data = getData (grid, i, j, rowCount, columnCount, false); 516 if (data != null) { 517 int vSpan = Math.max (1, Math.min (data.verticalSpan, rowCount)); 518 if (vSpan > 1) { 519 int spanHeight = 0, spanMinHeight = 0, spanExpandCount = 0; 520 for (int k=0; k<vSpan; k++) { 521 spanHeight += heights [i-k]; 522 spanMinHeight += minHeights [i-k]; 523 if (expandRow [i-k]) spanExpandCount++; 524 } 525 if (data.grabExcessVerticalSpace && spanExpandCount == 0) { 526 expandCount++; 527 expandRow [i] = true; 528 } 529 int h = data.cacheHeight + data.verticalIndent - spanHeight - (vSpan - 1) * verticalSpacing; 530 if (h > 0) { 531 if (spanExpandCount == 0) { 532 heights [i] += h; 533 } else { 534 int delta = h / spanExpandCount; 535 int remainder = h % spanExpandCount, last = -1; 536 for (int k = 0; k < vSpan; k++) { 537 if (expandRow [i-k]) { 538 heights [last=i-k] += delta; 539 } 540 } 541 if (last > -1) heights [last] += remainder; 542 } 543 } 544 if (!data.grabExcessVerticalSpace || data.minimumHeight != 0) { 545 h = !data.grabExcessVerticalSpace || data.minimumHeight == SWT.DEFAULT ? data.cacheHeight : data.minimumHeight; 546 h += data.verticalIndent - spanMinHeight - (vSpan - 1) * verticalSpacing; 547 if (h > 0) { 548 if (spanExpandCount == 0) { 549 minHeights [i] += h; 550 } else { 551 int delta = h / spanExpandCount; 552 int remainder = h % spanExpandCount, last = -1; 553 for (int k = 0; k < vSpan; k++) { 554 if (expandRow [i-k]) { 555 minHeights [last=i-k] += delta; 556 } 557 } 558 if (last > -1) minHeights [last] += remainder; 559 } 560 } 561 } 562 } 563 } 564 } 565 } 566 if (height != SWT.DEFAULT && expandCount > 0) { 567 int totalHeight = 0; 568 for (int i=0; i<rowCount; i++) { 569 totalHeight += heights [i]; 570 } 571 int c = expandCount; 572 int delta = (availableHeight - totalHeight) / c; 573 int remainder = (availableHeight - totalHeight) % c; 574 int last = -1; 575 while (totalHeight != availableHeight) { 576 for (int i=0; i<rowCount; i++) { 577 if (expandRow [i]) { 578 if (heights [i] + delta > minHeights [i]) { 579 heights [last = i] = heights [i] + delta; 580 } else { 581 heights [i] = minHeights [i]; 582 expandRow [i] = false; 583 c--; 584 } 585 } 586 } 587 if (last > -1) heights [last] += remainder; 588 589 for (int i=0; i<rowCount; i++) { 590 for (int j=0; j<columnCount; j++) { 591 GridData data = getData (grid, i, j, rowCount, columnCount, false); 592 if (data != null) { 593 int vSpan = Math.max (1, Math.min (data.verticalSpan, rowCount)); 594 if (vSpan > 1) { 595 if (!data.grabExcessVerticalSpace || data.minimumHeight != 0) { 596 int spanHeight = 0, spanExpandCount = 0; 597 for (int k=0; k<vSpan; k++) { 598 spanHeight += heights [i-k]; 599 if (expandRow [i-k]) spanExpandCount++; 600 } 601 int h = !data.grabExcessVerticalSpace || data.minimumHeight == SWT.DEFAULT ? data.cacheHeight : data.minimumHeight; 602 h += data.verticalIndent - spanHeight - (vSpan - 1) * verticalSpacing; 603 if (h > 0) { 604 if (spanExpandCount == 0) { 605 heights [i] += h; 606 } else { 607 int delta2 = h / spanExpandCount; 608 int remainder2 = h % spanExpandCount, last2 = -1; 609 for (int k = 0; k < vSpan; k++) { 610 if (expandRow [i-k]) { 611 heights [last2=i-k] += delta2; 612 } 613 } 614 if (last2 > -1) heights [last2] += remainder2; 615 } 616 } 617 } 618 } 619 } 620 } 621 } 622 if (c == 0) break; 623 totalHeight = 0; 624 for (int i=0; i<rowCount; i++) { 625 totalHeight += heights [i]; 626 } 627 delta = (availableHeight - totalHeight) / c; 628 remainder = (availableHeight - totalHeight) % c; 629 last = -1; 630 } 631 } 632 633 634 if (move) { 635 int gridY = y + marginTop + marginHeight; 636 for (int i=0; i<rowCount; i++) { 637 int gridX = x + marginLeft + marginWidth; 638 for (int j=0; j<columnCount; j++) { 639 GridData data = getData (grid, i, j, rowCount, columnCount, true); 640 if (data != null) { 641 int hSpan = Math.max (1, Math.min (data.horizontalSpan, columnCount)); 642 int vSpan = Math.max (1, data.verticalSpan); 643 int cellWidth = 0, cellHeight = 0; 644 for (int k=0; k<hSpan; k++) { 645 cellWidth += widths [j+k]; 646 } 647 for (int k=0; k<vSpan; k++) { 648 cellHeight += heights [i+k]; 649 } 650 cellWidth += horizontalSpacing * (hSpan - 1); 651 int childX = gridX + data.horizontalIndent; 652 int childWidth = Math.min (data.cacheWidth, cellWidth); 653 switch (data.horizontalAlignment) { 654 case SWT.CENTER: 655 case GridData.CENTER: 656 childX += Math.max (0, (cellWidth - data.horizontalIndent - childWidth) / 2); 657 break; 658 case SWT.RIGHT: 659 case SWT.END: 660 case GridData.END: 661 childX += Math.max (0, cellWidth - data.horizontalIndent - childWidth); 662 break; 663 case SWT.FILL: 664 childWidth = cellWidth - data.horizontalIndent; 665 break; 666 } 667 cellHeight += verticalSpacing * (vSpan - 1); 668 int childY = gridY + data.verticalIndent; 669 int childHeight = Math.min (data.cacheHeight, cellHeight); 670 switch (data.verticalAlignment) { 671 case SWT.CENTER: 672 case GridData.CENTER: 673 childY += Math.max (0, (cellHeight - data.verticalIndent - childHeight) / 2); 674 break; 675 case SWT.BOTTOM: 676 case SWT.END: 677 case GridData.END: 678 childY += Math.max (0, cellHeight - data.verticalIndent - childHeight); 679 break; 680 case SWT.FILL: 681 childHeight = cellHeight - data.verticalIndent; 682 break; 683 } 684 Control child = grid [i][j]; 685 if (child != null) { 686 child.setBounds (childX, childY, childWidth, childHeight); 687 } 688 } 689 gridX += widths [j] + horizontalSpacing; 690 } 691 gridY += heights [i] + verticalSpacing; 692 } 693 } 694 695 for (int i = 0; i < flushLength; i++) { 697 flush [i].cacheWidth = flush [i].cacheHeight = -1; 698 } 699 700 int totalDefaultWidth = 0; 701 int totalDefaultHeight = 0; 702 for (int i=0; i<columnCount; i++) { 703 totalDefaultWidth += widths [i]; 704 } 705 for (int i=0; i<rowCount; i++) { 706 totalDefaultHeight += heights [i]; 707 } 708 totalDefaultWidth += horizontalSpacing * (columnCount - 1) + marginLeft + marginWidth * 2 + marginRight; 709 totalDefaultHeight += verticalSpacing * (rowCount - 1) + marginTop + marginHeight * 2 + marginBottom; 710 return new Point (totalDefaultWidth, totalDefaultHeight); 711 } 712 713 String getName () { 714 String string = getClass ().getName (); 715 int index = string.lastIndexOf ('.'); 716 if (index == -1) return string; 717 return string.substring (index + 1, string.length ()); 718 } 719 720 726 public String toString () { 727 String string = getName ()+" {"; 728 if (numColumns != 1) string += "numColumns="+numColumns+" "; 729 if (makeColumnsEqualWidth) string += "makeColumnsEqualWidth="+makeColumnsEqualWidth+" "; 730 if (marginWidth != 0) string += "marginWidth="+marginWidth+" "; 731 if (marginHeight != 0) string += "marginHeight="+marginHeight+" "; 732 if (marginLeft != 0) string += "marginLeft="+marginLeft+" "; 733 if (marginRight != 0) string += "marginRight="+marginRight+" "; 734 if (marginTop != 0) string += "marginTop="+marginTop+" "; 735 if (marginBottom != 0) string += "marginBottom="+marginBottom+" "; 736 if (horizontalSpacing != 0) string += "horizontalSpacing="+horizontalSpacing+" "; 737 if (verticalSpacing != 0) string += "verticalSpacing="+verticalSpacing+" "; 738 string = string.trim(); 739 string += "}"; 740 return string; 741 } 742 } 743 | Popular Tags |