552 private VPos getRowValignmentInternal() { 553 VPos localPos = getRowValignment(); 554 return localPos == null ? VPos.CENTER : localPos; 555 } 556 557 @Override public Orientation getContentBias() { 558 return getOrientation(); 559 } 560 561 @Override protected double computeMinWidth(double height) { 562 if (getContentBias() == HORIZONTAL) { 563 double maxPref = 0; 564 final List<Node> children = getChildren(); 565 for (int i=0, size=children.size(); i<size; i++) { 566 Node child = children.get(i); 567 if (child.isManaged()) { 568 maxPref = Math.max(maxPref, child.prefWidth(-1)); 569 } 570 } 571 final Insets insets = getInsets(); 572 return insets.getLeft() + snapSize(maxPref) + insets.getRight(); 573 } 574 return computePrefWidth(height); 575 } 576 577 @Override protected double computeMinHeight(double width) { 578 if (getContentBias() == VERTICAL) { 579 double maxPref = 0; 580 final List<Node> children = getChildren(); 581 for (int i=0, size=children.size(); i<size; i++) { 582 Node child = children.get(i); 583 if (child.isManaged()) { 584 maxPref = Math.max(maxPref, child.prefHeight(-1)); 585 } 586 } 587 final Insets insets = getInsets(); 588 return insets.getTop() + snapSize(maxPref) + insets.getBottom(); 589 } 590 return computePrefHeight(width); 591 } 592 593 @Override protected double computePrefWidth(double forHeight) { 594 final Insets insets = getInsets(); 595 if (getOrientation() == HORIZONTAL) { 596 // horizontal 597 double maxRunWidth = getPrefWrapLength(); 598 List<Run> hruns = getRuns(maxRunWidth); 599 double w = computeContentWidth(hruns); 600 w = getPrefWrapLength() > w ? getPrefWrapLength() : w; 601 return insets.getLeft() + snapSize(w) + insets.getRight(); 602 } else { 603 // vertical 604 double maxRunHeight = forHeight != -1? 605 forHeight - insets.getTop() - insets.getBottom() : getPrefWrapLength(); 606 List<Run> vruns = getRuns(maxRunHeight); 607 return insets.getLeft() + computeContentWidth(vruns) + insets.getRight(); 608 } 609 } 610 611 @Override protected double computePrefHeight(double forWidth) { 612 final Insets insets = getInsets(); 613 if (getOrientation() == HORIZONTAL) { 614 // horizontal 615 double maxRunWidth = forWidth != -1? 616 forWidth - insets.getLeft() - insets.getRight() : getPrefWrapLength(); 617 List<Run> hruns = getRuns(maxRunWidth); 618 return insets.getTop() + computeContentHeight(hruns) + insets.getBottom(); 619 } else { 620 // vertical 621 double maxRunHeight = getPrefWrapLength(); 622 List<Run> vruns = getRuns(maxRunHeight); 623 double h = computeContentHeight(vruns); 624 h = getPrefWrapLength() > h ? getPrefWrapLength() : h; 625 return insets.getTop() + snapSize(h) + insets.getBottom(); 626 } 627 } 628 629 @Override public void requestLayout() { 630 if (!computingRuns) { 631 runs = null; 632 } 633 super.requestLayout(); 634 } 635 636 private List<Run> runs = null; 637 private double lastMaxRunLength = -1; 638 boolean computingRuns = false; 639 640 private List<Run> getRuns(double maxRunLength) { 641 if (runs == null || maxRunLength != lastMaxRunLength) { 642 computingRuns = true; 643 lastMaxRunLength = maxRunLength; 644 runs = new ArrayList(); 645 double runLength = 0; 646 double runOffset = 0; 647 Run run = new Run(); 648 double vgap = snapSpace(this.getVgap()); 649 double hgap = snapSpace(this.getHgap()); 650 651 final List<Node> children = getChildren(); 652 for (int i=0, size=children.size(); i<size; i++) { 653 Node child = children.get(i); 654 if (child.isManaged()) { 655 LayoutRect nodeRect = new LayoutRect(); 656 nodeRect.node = child; 657 Insets margin = getMargin(child); 658 nodeRect.width = computeChildPrefAreaWidth(child, margin); 659 nodeRect.height = computeChildPrefAreaHeight(child, margin); 660 double nodeLength = getOrientation() == HORIZONTAL ? nodeRect.width : nodeRect.height; 661 if (runLength + nodeLength > maxRunLength && runLength > 0) { 662 // wrap to next run *unless* its the only node in the run 663 normalizeRun(run, runOffset); 664 if (getOrientation() == HORIZONTAL) { 665 // horizontal 666 runOffset += run.height + vgap; 667 } else { 668 // vertical 669 runOffset += run.width + hgap; 680 // vertical 681 nodeRect.y = runLength; 682 runLength += nodeRect.height + vgap; 683 } 684 run.rects.add(nodeRect); 685 } 686 687 } 688 // insert last run 689 normalizeRun(run, runOffset); 690 runs.add(run); 691 computingRuns = false; 692 } 693 return runs; 694 } 695 696 private void normalizeRun(final Run run, double runOffset) { 697 if (getOrientation() == HORIZONTAL) { 698 // horizontal 699 ArrayList<Node> rownodes = new ArrayList(); 700 run.width = (run.rects.size()-1)*snapSpace(getHgap()); 701 for (int i=0, max=run.rects.size(); i<max; i++) { 702 LayoutRect lrect = run.rects.get(i); 703 rownodes.add(lrect.node); 704 run.width += lrect.width; 705 lrect.y = runOffset; 706 } 707 run.height = computeMaxPrefAreaHeight(rownodes, marginAccessor, getRowValignment()); 708 run.baselineOffset = getRowValignment() == VPos.BASELINE? 709 getAreaBaselineOffset(rownodes, marginAccessor, i -> run.rects.get(i).width, run.height, true) : 0; 710 711 } else { 712 // vertical 713 run.height = (run.rects.size()-1)*snapSpace(getVgap()); 714 double maxw = 0; 715 for (int i=0, max=run.rects.size(); i<max; i++) { 716 LayoutRect lrect = run.rects.get(i); 717 run.height += lrect.height; 718 lrect.x = runOffset; 719 maxw = Math.max(maxw, lrect.width); 720 } 721 722 run.width = maxw; 723 run.baselineOffset = run.height; 724 } 725 } 726 727 private double computeContentWidth(List<Run> runs) { 728 double cwidth = getOrientation() == HORIZONTAL ? 0 : (runs.size()-1)*snapSpace(getHgap()); 729 for (int i=0, max=runs.size(); i<max; i++) { 730 Run run = runs.get(i); 731 if (getOrientation() == HORIZONTAL) { 732 cwidth = Math.max(cwidth, run.width); 733 } else { 734 // vertical 735 cwidth += run.width; 736 } 737 } 738 return cwidth; 739 } 740 741 private double computeContentHeight(List<Run> runs) { 742 double cheight = getOrientation() == VERTICAL ? 0 : (runs.size()-1)*snapSpace(getVgap()); 743 for (int i=0, max=runs.size(); i<max; i++) { 744 Run run = runs.get(i); 745 if (getOrientation() == VERTICAL) { 746 cheight = Math.max(cheight, run.height); 747 } else { 748 // horizontal 749 cheight += run.height; 750 } 751 } 752 return cheight; 753 } 754 755 @Override protected void layoutChildren() { 756 final Insets insets = getInsets(); 757 final double width = getWidth(); 758 final double height = getHeight(); 759 final double top = insets.getTop(); 760 final double left = insets.getLeft(); 761 final double bottom = insets.getBottom(); 762 final double right = insets.getRight(); | 552 private VPos getRowValignmentInternal() { 553 VPos localPos = getRowValignment(); 554 return localPos == null ? VPos.CENTER : localPos; 555 } 556 557 @Override public Orientation getContentBias() { 558 return getOrientation(); 559 } 560 561 @Override protected double computeMinWidth(double height) { 562 if (getContentBias() == HORIZONTAL) { 563 double maxPref = 0; 564 final List<Node> children = getChildren(); 565 for (int i=0, size=children.size(); i<size; i++) { 566 Node child = children.get(i); 567 if (child.isManaged()) { 568 maxPref = Math.max(maxPref, child.prefWidth(-1)); 569 } 570 } 571 final Insets insets = getInsets(); 572 return insets.getLeft() + snapSizeX(maxPref) + insets.getRight(); 573 } 574 return computePrefWidth(height); 575 } 576 577 @Override protected double computeMinHeight(double width) { 578 if (getContentBias() == VERTICAL) { 579 double maxPref = 0; 580 final List<Node> children = getChildren(); 581 for (int i=0, size=children.size(); i<size; i++) { 582 Node child = children.get(i); 583 if (child.isManaged()) { 584 maxPref = Math.max(maxPref, child.prefHeight(-1)); 585 } 586 } 587 final Insets insets = getInsets(); 588 return insets.getTop() + snapSizeY(maxPref) + insets.getBottom(); 589 } 590 return computePrefHeight(width); 591 } 592 593 @Override protected double computePrefWidth(double forHeight) { 594 final Insets insets = getInsets(); 595 if (getOrientation() == HORIZONTAL) { 596 // horizontal 597 double maxRunWidth = getPrefWrapLength(); 598 List<Run> hruns = getRuns(maxRunWidth); 599 double w = computeContentWidth(hruns); 600 w = getPrefWrapLength() > w ? getPrefWrapLength() : w; 601 return insets.getLeft() + snapSizeX(w) + insets.getRight(); 602 } else { 603 // vertical 604 double maxRunHeight = forHeight != -1? 605 forHeight - insets.getTop() - insets.getBottom() : getPrefWrapLength(); 606 List<Run> vruns = getRuns(maxRunHeight); 607 return insets.getLeft() + computeContentWidth(vruns) + insets.getRight(); 608 } 609 } 610 611 @Override protected double computePrefHeight(double forWidth) { 612 final Insets insets = getInsets(); 613 if (getOrientation() == HORIZONTAL) { 614 // horizontal 615 double maxRunWidth = forWidth != -1? 616 forWidth - insets.getLeft() - insets.getRight() : getPrefWrapLength(); 617 List<Run> hruns = getRuns(maxRunWidth); 618 return insets.getTop() + computeContentHeight(hruns) + insets.getBottom(); 619 } else { 620 // vertical 621 double maxRunHeight = getPrefWrapLength(); 622 List<Run> vruns = getRuns(maxRunHeight); 623 double h = computeContentHeight(vruns); 624 h = getPrefWrapLength() > h ? getPrefWrapLength() : h; 625 return insets.getTop() + snapSizeY(h) + insets.getBottom(); 626 } 627 } 628 629 @Override public void requestLayout() { 630 if (!computingRuns) { 631 runs = null; 632 } 633 super.requestLayout(); 634 } 635 636 private List<Run> runs = null; 637 private double lastMaxRunLength = -1; 638 boolean computingRuns = false; 639 640 private List<Run> getRuns(double maxRunLength) { 641 if (runs == null || maxRunLength != lastMaxRunLength) { 642 computingRuns = true; 643 lastMaxRunLength = maxRunLength; 644 runs = new ArrayList(); 645 double runLength = 0; 646 double runOffset = 0; 647 Run run = new Run(); 648 double vgap = snapSpaceY(this.getVgap()); 649 double hgap = snapSpaceX(this.getHgap()); 650 651 final List<Node> children = getChildren(); 652 for (int i=0, size=children.size(); i<size; i++) { 653 Node child = children.get(i); 654 if (child.isManaged()) { 655 LayoutRect nodeRect = new LayoutRect(); 656 nodeRect.node = child; 657 Insets margin = getMargin(child); 658 nodeRect.width = computeChildPrefAreaWidth(child, margin); 659 nodeRect.height = computeChildPrefAreaHeight(child, margin); 660 double nodeLength = getOrientation() == HORIZONTAL ? nodeRect.width : nodeRect.height; 661 if (runLength + nodeLength > maxRunLength && runLength > 0) { 662 // wrap to next run *unless* its the only node in the run 663 normalizeRun(run, runOffset); 664 if (getOrientation() == HORIZONTAL) { 665 // horizontal 666 runOffset += run.height + vgap; 667 } else { 668 // vertical 669 runOffset += run.width + hgap; 680 // vertical 681 nodeRect.y = runLength; 682 runLength += nodeRect.height + vgap; 683 } 684 run.rects.add(nodeRect); 685 } 686 687 } 688 // insert last run 689 normalizeRun(run, runOffset); 690 runs.add(run); 691 computingRuns = false; 692 } 693 return runs; 694 } 695 696 private void normalizeRun(final Run run, double runOffset) { 697 if (getOrientation() == HORIZONTAL) { 698 // horizontal 699 ArrayList<Node> rownodes = new ArrayList(); 700 run.width = (run.rects.size()-1)*snapSpaceX(getHgap()); 701 for (int i=0, max=run.rects.size(); i<max; i++) { 702 LayoutRect lrect = run.rects.get(i); 703 rownodes.add(lrect.node); 704 run.width += lrect.width; 705 lrect.y = runOffset; 706 } 707 run.height = computeMaxPrefAreaHeight(rownodes, marginAccessor, getRowValignment()); 708 run.baselineOffset = getRowValignment() == VPos.BASELINE? 709 getAreaBaselineOffset(rownodes, marginAccessor, i -> run.rects.get(i).width, run.height, true) : 0; 710 711 } else { 712 // vertical 713 run.height = (run.rects.size()-1)*snapSpaceY(getVgap()); 714 double maxw = 0; 715 for (int i=0, max=run.rects.size(); i<max; i++) { 716 LayoutRect lrect = run.rects.get(i); 717 run.height += lrect.height; 718 lrect.x = runOffset; 719 maxw = Math.max(maxw, lrect.width); 720 } 721 722 run.width = maxw; 723 run.baselineOffset = run.height; 724 } 725 } 726 727 private double computeContentWidth(List<Run> runs) { 728 double cwidth = getOrientation() == HORIZONTAL ? 0 : (runs.size()-1)*snapSpaceX(getHgap()); 729 for (int i=0, max=runs.size(); i<max; i++) { 730 Run run = runs.get(i); 731 if (getOrientation() == HORIZONTAL) { 732 cwidth = Math.max(cwidth, run.width); 733 } else { 734 // vertical 735 cwidth += run.width; 736 } 737 } 738 return cwidth; 739 } 740 741 private double computeContentHeight(List<Run> runs) { 742 double cheight = getOrientation() == VERTICAL ? 0 : (runs.size()-1)*snapSpaceY(getVgap()); 743 for (int i=0, max=runs.size(); i<max; i++) { 744 Run run = runs.get(i); 745 if (getOrientation() == VERTICAL) { 746 cheight = Math.max(cheight, run.height); 747 } else { 748 // horizontal 749 cheight += run.height; 750 } 751 } 752 return cheight; 753 } 754 755 @Override protected void layoutChildren() { 756 final Insets insets = getInsets(); 757 final double width = getWidth(); 758 final double height = getHeight(); 759 final double top = insets.getTop(); 760 final double left = insets.getLeft(); 761 final double bottom = insets.getBottom(); 762 final double right = insets.getRight(); |