1 15 package org.eclipse.ui.internal; 16 17 import java.util.ArrayList ; 18 19 import org.eclipse.core.runtime.Assert; 20 import org.eclipse.jface.util.Geometry; 21 import org.eclipse.swt.SWT; 22 import org.eclipse.swt.graphics.Point; 23 import org.eclipse.swt.graphics.Rectangle; 24 import org.eclipse.swt.widgets.Composite; 25 import org.eclipse.swt.widgets.Sash; 26 import org.eclipse.ui.IPageLayout; 27 28 32 public class LayoutTreeNode extends LayoutTree { 33 34 static class ChildSizes { 35 int left; 36 int right; 37 boolean resizable = true; 38 39 public ChildSizes (int l, int r, boolean resize) { 40 left = l; 41 right = r; 42 resizable = resize; 43 } 44 } 45 46 47 private LayoutTree children[] = new LayoutTree[2]; 48 49 50 final static int SASH_WIDTH = 3; 51 52 55 public LayoutTreeNode(LayoutPartSash sash) { 56 super(sash); 57 } 58 59 62 public void flushChildren() { 63 super.flushChildren(); 64 65 children[0].flushChildren(); 66 children[1].flushChildren(); 67 } 68 69 75 public LayoutPart findPart(Point toFind) { 76 if (!children[0].isVisible()) { 77 if (!children[1].isVisible()) { 78 return null; 79 } 80 81 return children[1].findPart(toFind); 82 } else { 83 if (!children[1].isVisible()) { 84 return children[0].findPart(toFind); 85 } 86 } 87 88 LayoutPartSash sash = getSash(); 89 90 Rectangle bounds = sash.getBounds(); 91 92 if (sash.isVertical()) { 93 if (toFind.x < bounds.x + (bounds.width / 2)) { 94 return children[0].findPart(toFind); 95 } 96 return children[1].findPart(toFind); 97 } else { 98 if (toFind.y < bounds.y + (bounds.height / 2)) { 99 return children[0].findPart(toFind); 100 } 101 return children[1].findPart(toFind); 102 } 103 } 104 105 109 public LayoutPart computeRelation(ArrayList relations) { 110 PartSashContainer.RelationshipInfo r = new PartSashContainer.RelationshipInfo(); 111 r.relative = children[0].computeRelation(relations); 112 r.part = children[1].computeRelation(relations); 113 r.left = getSash().getLeft(); 114 r.right = getSash().getRight(); 115 r.relationship = getSash().isVertical() ? IPageLayout.RIGHT 116 : IPageLayout.BOTTOM; 117 relations.add(0, r); 118 return r.relative; 119 } 120 121 124 public void disposeSashes() { 125 children[0].disposeSashes(); 126 children[1].disposeSashes(); 127 getSash().dispose(); 128 } 129 130 134 public LayoutTree find(LayoutPart child) { 135 LayoutTree node = children[0].find(child); 136 if (node != null) { 137 return node; 138 } 139 node = children[1].find(child); 140 return node; 141 } 142 143 146 public LayoutPart findBottomRight() { 147 if (children[1].isVisible()) { 148 return children[1].findBottomRight(); 149 } 150 return children[0].findBottomRight(); 151 } 152 153 157 public LayoutTreeNode findCommonParent(LayoutPart child1, LayoutPart child2) { 158 return findCommonParent(child1, child2, false, false); 159 } 160 161 165 LayoutTreeNode findCommonParent(LayoutPart child1, LayoutPart child2, 166 boolean foundChild1, boolean foundChild2) { 167 if (!foundChild1) { 168 foundChild1 = find(child1) != null; 169 } 170 if (!foundChild2) { 171 foundChild2 = find(child2) != null; 172 } 173 if (foundChild1 && foundChild2) { 174 return this; 175 } 176 if (parent == null) { 177 return null; 178 } 179 return parent 180 .findCommonParent(child1, child2, foundChild1, foundChild2); 181 } 182 183 187 public LayoutTreeNode findSash(LayoutPartSash sash) { 188 if (this.getSash() == sash) { 189 return this; 190 } 191 LayoutTreeNode node = children[0].findSash(sash); 192 if (node != null) { 193 return node; 194 } 195 node = children[1].findSash(sash); 196 if (node != null) { 197 return node; 198 } 199 return null; 200 } 201 202 208 void findSashes(LayoutTree child, PartPane.Sashes sashes) { 209 Sash sash = (Sash) getSash().getControl(); 210 boolean leftOrTop = children[0] == child; 211 if (sash != null) { 212 LayoutPartSash partSash = getSash(); 213 if (leftOrTop) { 216 if (partSash.isVertical()) { 217 if (sashes.right == null) { 218 sashes.right = sash; 219 } 220 } else { 221 if (sashes.bottom == null) { 222 sashes.bottom = sash; 223 } 224 } 225 } else { 226 if (partSash.isVertical()) { 227 if (sashes.left == null) { 228 sashes.left = sash; 229 } 230 } else { 231 if (sashes.top == null) { 232 sashes.top = sash; 233 } 234 } 235 } 236 } 237 if (getParent() != null) { 238 getParent().findSashes(this, sashes); 239 } 240 } 241 242 245 public LayoutPartSash getSash() { 246 return (LayoutPartSash) part; 247 } 248 249 252 public boolean isVisible() { 253 return children[0].isVisible() || children[1].isVisible(); 254 } 255 256 259 LayoutTree remove(LayoutTree child) { 260 getSash().dispose(); 261 if (parent == null) { 262 if (children[0] == child) { 264 children[1].setParent(null); 265 return children[1]; 266 } 267 children[0].setParent(null); 268 return children[0]; 269 } 270 271 LayoutTreeNode oldParent = parent; 272 if (children[0] == child) { 273 oldParent.replaceChild(this, children[1]); 274 } else { 275 oldParent.replaceChild(this, children[0]); 276 } 277 return oldParent; 278 } 279 280 283 void replaceChild(LayoutTree oldChild, LayoutTree newChild) { 284 if (children[0] == oldChild) { 285 children[0] = newChild; 286 } else if (children[1] == oldChild) { 287 children[1] = newChild; 288 } 289 newChild.setParent(this); 290 if (!children[0].isVisible() || !children[0].isVisible()) { 291 getSash().dispose(); 292 } 293 294 flushCache(); 295 } 296 297 301 public boolean sameDirection(boolean isVertical, LayoutTreeNode subTree) { 302 boolean treeVertical = getSash().isVertical(); 303 if (treeVertical != isVertical) { 304 return false; 305 } 306 while (subTree != null) { 307 if (this == subTree) { 308 return true; 309 } 310 if (subTree.children[0].isVisible() 311 && subTree.children[1].isVisible()) { 312 if (subTree.getSash().isVertical() != isVertical) { 313 return false; 314 } 315 } 316 subTree = subTree.getParent(); 317 } 318 return true; 319 } 320 321 public int doComputePreferredSize(boolean width, int availableParallel, int availablePerpendicular, int preferredParallel) { 322 assertValidSize(availablePerpendicular); 323 assertValidSize(availableParallel); 324 assertValidSize(preferredParallel); 325 326 if (!children[0].isVisible()) { 328 return children[1].computePreferredSize(width, availableParallel, availablePerpendicular, preferredParallel); 329 } 330 331 if (!children[1].isVisible()) { 332 return children[0].computePreferredSize(width, availableParallel, availablePerpendicular, preferredParallel); 333 } 334 335 if (availableParallel == 0) { 336 return 0; 337 } 338 339 if (width == getSash().isVertical()) { 341 ChildSizes sizes = computeChildSizes(availableParallel, availablePerpendicular, 343 getSash().getLeft(), getSash().getRight(), preferredParallel); 344 345 return add(sizes.left, add(sizes.right, SASH_WIDTH)); 347 } else { 348 351 ChildSizes sizes; 352 sizes = computeChildSizes(availablePerpendicular, availableParallel, 354 getSash().getLeft(), getSash().getRight(), availablePerpendicular); 355 356 int leftSize = children[0].computePreferredSize(width, availableParallel, sizes.left, preferredParallel); 359 360 int rightSize = children[1].computePreferredSize(width, availableParallel, sizes.right, preferredParallel); 362 363 int result = rightSize; 365 if (leftSize > rightSize) { 366 result = leftSize; 367 } 368 369 assertValidSize(result); 370 371 return result; 372 } 373 } 374 375 388 ChildSizes computeChildSizes(int width, int height, int left, int right, int preferredWidth) { 389 Assert.isTrue(children[0].isVisible()); 390 Assert.isTrue(children[1].isVisible()); 391 assertValidSize(width); 392 assertValidSize(height); 393 assertValidSize(preferredWidth); 394 Assert.isTrue(left >= 0); 395 Assert.isTrue(right >= 0); 396 Assert.isTrue(preferredWidth >= 0); 397 Assert.isTrue(preferredWidth <= width); 398 boolean vertical = getSash().isVertical(); 399 400 if (width <= SASH_WIDTH) { 401 return new ChildSizes(0,0, false); 402 } 403 404 if (width == INFINITE) { 405 if (preferredWidth == INFINITE) { 406 return new ChildSizes(children[0].computeMaximumSize(vertical, height), 407 children[1].computeMaximumSize(vertical, height), false); 408 } 409 410 if (preferredWidth == 0) { 411 return new ChildSizes(children[0].computeMinimumSize(vertical, height), 412 children[1].computeMinimumSize(vertical, height), false); 413 } 414 } 415 416 int total = left + right; 417 418 double wLeft = left, wRight = right; 420 switch (getCompressionBias()) { 421 case -1: 422 wLeft = 0.0; 423 break; 424 case 1: 425 wRight = 0.0; 426 break; 427 default: 428 break; 429 } 430 double wTotal = wLeft + wRight; 431 432 preferredWidth = Math.max(0, subtract(preferredWidth, SASH_WIDTH)); 435 width = Math.max(0, subtract(width, SASH_WIDTH)); 436 437 int redistribute = subtract(preferredWidth, total); 438 439 int leftMinimum = children[0].computeMinimumSize(vertical, height); 441 int rightMinimum = children[1].computeMinimumSize(vertical, height); 442 int leftMaximum = children[0].computeMaximumSize(vertical, height); 443 int rightMaximum = children[1].computeMaximumSize(vertical, height); 444 445 int leftAvailable = Math.min(leftMaximum, Math.max(0, subtract(width, rightMinimum))); 447 int rightAvailable = Math.min(rightMaximum, Math.max(0, subtract(width, leftMinimum))); 448 449 int idealLeft = Math.max(leftMinimum, Math.min(preferredWidth, 451 left + (int) Math.round(redistribute * wLeft / wTotal))); 452 453 idealLeft = Math.max(idealLeft, preferredWidth - rightAvailable); 455 idealLeft = Math.min(idealLeft, leftAvailable); 457 458 idealLeft = children[0].computePreferredSize(vertical, leftAvailable, height, idealLeft); 460 461 idealLeft = Math.max(idealLeft, leftMinimum); 463 idealLeft = Math.min(idealLeft, leftAvailable); 464 465 int idealRight = Math.max(rightMinimum, preferredWidth - idealLeft); 467 468 rightAvailable = Math.max(0, Math.min(rightAvailable, subtract(width, idealLeft))); 469 idealRight = Math.min(idealRight, rightAvailable); 470 idealRight = children[1].computePreferredSize(vertical, rightAvailable, height, idealRight); 471 idealRight = Math.max(idealRight, rightMinimum); 472 473 return new ChildSizes(idealLeft, idealRight, leftMaximum > leftMinimum 474 && rightMaximum > rightMinimum 475 && leftMinimum + rightMinimum < width); 476 } 477 478 protected int doGetSizeFlags(boolean width) { 479 if (!children[0].isVisible()) { 480 return children[1].getSizeFlags(width); 481 } 482 483 if (!children[1].isVisible()) { 484 return children[0].getSizeFlags(width); 485 } 486 487 int leftFlags = children[0].getSizeFlags(width); 488 int rightFlags = children[1].getSizeFlags(width); 489 490 return ((leftFlags | rightFlags) & ~SWT.MAX) | (leftFlags & rightFlags & SWT.MAX); 491 } 492 493 496 public void doSetBounds(Rectangle bounds) { 497 if (!children[0].isVisible()) { 498 children[1].setBounds(bounds); 499 getSash().setVisible(false); 500 return; 501 } 502 if (!children[1].isVisible()) { 503 children[0].setBounds(bounds); 504 getSash().setVisible(false); 505 return; 506 } 507 508 bounds = Geometry.copy(bounds); 509 510 boolean vertical = getSash().isVertical(); 511 512 if (!vertical) { 515 Geometry.flipXY(bounds); 516 } 517 518 ChildSizes childSizes = computeChildSizes(bounds.width, bounds.height, getSash().getLeft(), getSash().getRight(), bounds.width); 519 520 getSash().setVisible(true); 521 getSash().setEnabled(childSizes.resizable); 522 523 Rectangle leftBounds = new Rectangle(bounds.x, bounds.y, childSizes.left, bounds.height); 524 Rectangle sashBounds = new Rectangle(leftBounds.x + leftBounds.width, bounds.y, SASH_WIDTH, bounds.height); 525 Rectangle rightBounds = new Rectangle(sashBounds.x + sashBounds.width, bounds.y, childSizes.right, bounds.height); 526 527 if (!vertical) { 528 Geometry.flipXY(leftBounds); 529 Geometry.flipXY(sashBounds); 530 Geometry.flipXY(rightBounds); 531 } 532 533 getSash().setBounds(sashBounds); 534 children[0].setBounds(leftBounds); 535 children[1].setBounds(rightBounds); 536 } 537 538 541 public void createControl(Composite parent) { 542 children[0].createControl(parent); 543 children[1].createControl(parent); 544 getSash().createControl(parent); 545 546 super.createControl(parent); 547 } 548 549 551 public boolean isCompressible() { 552 return children[0].isCompressible() || children[1].isCompressible(); 553 } 554 555 561 public int getCompressionBias() { 562 boolean left = children[0].isCompressible(); 563 boolean right = children[1].isCompressible(); 564 if (left == right) { 565 return 0; 566 } 567 if (right) { 568 return -1; 569 } 570 return 1; 571 } 572 573 boolean isLeftChild(LayoutTree toTest) { 574 return children[0] == toTest; 575 } 576 577 LayoutTree getChild(boolean left) { 578 int index = left ? 0 : 1; 579 return (children[index]); 580 } 581 582 585 void setChild(boolean left, LayoutPart part) { 586 LayoutTree child = new LayoutTree(part); 587 setChild(left, child); 588 flushCache(); 589 } 590 591 594 void setChild(boolean left, LayoutTree child) { 595 int index = left ? 0 : 1; 596 children[index] = child; 597 child.setParent(this); 598 flushCache(); 599 } 600 601 604 public String toString() { 605 String s = "<null>\n"; if (part.getControl() != null) { 607 s = "<@" + part.getControl().hashCode() + ">\n"; } 609 String result = "["; if (children[0].getParent() != this) { 611 result = result + "{" + children[0] + "}" + s; } else { 613 result = result + children[0] + s; 614 } 615 616 if (children[1].getParent() != this) { 617 result = result + "{" + children[1] + "}]"; } else { 619 result = result + children[1] + "]"; } 621 return result; 622 } 623 624 628 639 649 public void describeLayout(StringBuffer buf) { 650 if (!(children[0].isVisible())) { 651 if (!children[1].isVisible()) { 652 return; 653 } 654 655 children[1].describeLayout(buf); 656 return; 657 } 658 659 if (!children[1].isVisible()) { 660 children[0].describeLayout(buf); 661 return; 662 } 663 664 buf.append("("); children[0].describeLayout(buf); 666 667 buf.append(getSash().isVertical() ? "|" : "-"); 669 children[1].describeLayout(buf); 670 buf.append(")"); } 672 673 } 674 | Popular Tags |