modules/graphics/src/main/java/javafx/scene/layout/HBox.java

Print this page




 379     @Override public Orientation getContentBias() {
 380         if (biasDirty) {
 381             bias = null;
 382             final List<Node> children = getManagedChildren();
 383             for (Node child : children) {
 384                 Orientation contentBias = child.getContentBias();
 385                 if (contentBias != null) {
 386                     bias = contentBias;
 387                     if (contentBias == Orientation.HORIZONTAL) {
 388                         break;
 389                     }
 390                 }
 391             }
 392             biasDirty = false;
 393         }
 394         return bias;
 395     }
 396 
 397     @Override protected double computeMinWidth(double height) {
 398         Insets insets = getInsets();
 399         return snapSpace(insets.getLeft()) +
 400                computeContentWidth(getManagedChildren(), height, true) +
 401                snapSpace(insets.getRight());
 402     }
 403 
 404     @Override protected double computeMinHeight(double width) {
 405         Insets insets = getInsets();
 406         List<Node>managed = getManagedChildren();
 407         double contentHeight = 0;
 408         if (width != -1 && getContentBias() != null) {
 409             double prefWidths[][] = getAreaWidths(managed, -1, false);
 410             adjustAreaWidths(managed, prefWidths, width, -1);
 411             contentHeight = computeMaxMinAreaHeight(managed, marginAccessor, prefWidths[0], getAlignmentInternal().getVpos());
 412         } else {
 413             contentHeight = computeMaxMinAreaHeight(managed, marginAccessor, getAlignmentInternal().getVpos());
 414         }
 415         return snapSpace(insets.getTop()) +
 416                contentHeight +
 417                snapSpace(insets.getBottom());
 418     }
 419 
 420     @Override protected double computePrefWidth(double height) {
 421         Insets insets = getInsets();
 422         return snapSpace(insets.getLeft()) +
 423                computeContentWidth(getManagedChildren(), height, false) +
 424                snapSpace(insets.getRight());
 425     }
 426 
 427     @Override protected double computePrefHeight(double width) {
 428         Insets insets = getInsets();
 429         List<Node>managed = getManagedChildren();
 430         double contentHeight = 0;
 431         if (width != -1 && getContentBias() != null) {
 432             double prefWidths[][] = getAreaWidths(managed, -1, false);
 433             adjustAreaWidths(managed, prefWidths, width, -1);
 434             contentHeight = computeMaxPrefAreaHeight(managed, marginAccessor, prefWidths[0], getAlignmentInternal().getVpos());
 435         } else {
 436             contentHeight = computeMaxPrefAreaHeight(managed, marginAccessor, getAlignmentInternal().getVpos());
 437         }
 438         return snapSpace(insets.getTop()) +
 439                contentHeight +
 440                snapSpace(insets.getBottom());
 441     }
 442 
 443     private double[][] getAreaWidths(List<Node>managed, double height, boolean minimum) {
 444         // height could be -1
 445         double[][] temp = getTempArray(managed.size());
 446         final double insideHeight = height == -1? -1 : height -
 447                                      snapSpace(getInsets().getTop()) - snapSpace(getInsets().getBottom());
 448         final boolean shouldFillHeight = shouldFillHeight();
 449         for (int i = 0, size = managed.size(); i < size; i++) {
 450             Node child = managed.get(i);
 451             Insets margin = getMargin(child);
 452             if (minimum) {
 453                 temp[0][i] = computeChildMinAreaWidth(child, getMinBaselineComplement(), margin, insideHeight, shouldFillHeight);
 454             } else {
 455                 temp[0][i] = computeChildPrefAreaWidth(child, getPrefBaselineComplement(), margin, insideHeight, shouldFillHeight);
 456             }
 457         }
 458         return temp;
 459     }
 460 
 461     private double adjustAreaWidths(List<Node>managed, double areaWidths[][], double width, double height) {
 462         Insets insets = getInsets();
 463         double top = snapSpace(insets.getTop());
 464         double bottom = snapSpace(insets.getBottom());
 465 
 466         double contentWidth = sum(areaWidths[0], managed.size()) + (managed.size()-1)*snapSpace(getSpacing());
 467         double extraWidth = width -
 468                 snapSpace(insets.getLeft()) - snapSpace(insets.getRight()) - contentWidth;
 469 
 470         if (extraWidth != 0) {
 471             final double refHeight = shouldFillHeight() && height != -1? height - top - bottom : -1;
 472             double remaining = growOrShrinkAreaWidths(managed, areaWidths, Priority.ALWAYS, extraWidth, refHeight);
 473             remaining = growOrShrinkAreaWidths(managed, areaWidths, Priority.SOMETIMES, remaining, refHeight);
 474             contentWidth += (extraWidth - remaining);
 475         }
 476         return contentWidth;
 477     }
 478 
 479     private double growOrShrinkAreaWidths(List<Node>managed, double areaWidths[][], Priority priority, double extraWidth, double height) {
 480         final boolean shrinking = extraWidth < 0;
 481         int adjustingNumber = 0;
 482 
 483         double[] usedWidths = areaWidths[0];
 484         double[] temp = areaWidths[1];
 485         final boolean shouldFillHeight = shouldFillHeight();
 486 
 487         if (shrinking) {
 488             adjustingNumber = managed.size();
 489             for (int i = 0, size = managed.size(); i < size; i++) {
 490                 final Node child = managed.get(i);
 491                 temp[i] = computeChildMinAreaWidth(child, getMinBaselineComplement(), getMargin(child), height, shouldFillHeight);
 492             }
 493         } else {
 494             for (int i = 0, size = managed.size(); i < size; i++) {
 495                 final Node child = managed.get(i);
 496                 if (getHgrow(child) == priority) {
 497                     temp[i] = computeChildMaxAreaWidth(child, getMinBaselineComplement(), getMargin(child), height, shouldFillHeight);
 498                     adjustingNumber++;
 499                 } else {
 500                     temp[i] = -1;
 501                 }
 502             }
 503         }
 504 
 505         double available = extraWidth; // will be negative in shrinking case
 506         outer:while (Math.abs(available) > 1 && adjustingNumber > 0) {
 507             final double portion = snapPortion(available / adjustingNumber); // negative in shrinking case
 508             for (int i = 0, size = managed.size(); i < size; i++) {
 509                 if (temp[i] == -1) {
 510                     continue;
 511                 }
 512                 final double limit = temp[i] - usedWidths[i]; // negative in shrinking case
 513                 final double change = Math.abs(limit) <= Math.abs(portion)? limit : portion;
 514                 usedWidths[i] += change;
 515                 available -= change;
 516                 if (Math.abs(available) < 1) {
 517                     break outer;
 518                 }
 519                 if (Math.abs(change) < Math.abs(portion)) {
 520                     temp[i] = -1;
 521                     adjustingNumber--;
 522                 }
 523             }
 524         }
 525 
 526         return available; // might be negative in shrinking case
 527     }
 528 
 529     private double computeContentWidth(List<Node> managedChildren, double height, boolean minimum) {
 530         return sum(getAreaWidths(managedChildren, height, minimum)[0], managedChildren.size())
 531                 + (managedChildren.size()-1)*snapSpace(getSpacing());
 532     }
 533 
 534     private static double sum(double[] array, int size) {
 535         int i = 0;
 536         double res = 0;
 537         while (i != size) {
 538             res += array[i++];
 539         }
 540         return res;
 541     }
 542 
 543     @Override public void requestLayout() {
 544         if (performingLayout) {
 545             return;
 546         }
 547         biasDirty = true;
 548         bias = null;
 549         minBaselineComplement = Double.NaN;
 550         prefBaselineComplement = Double.NaN;
 551         baselineOffset = Double.NaN;


 598                         max = Math.max(max, top + child.getLayoutBounds().getMinY() + offset);
 599                     }
 600                 }
 601                 baselineOffset = max + snappedTopInset();
 602             } else {
 603                 baselineOffset = BASELINE_OFFSET_SAME_AS_HEIGHT;
 604             }
 605         }
 606         return baselineOffset;
 607     }
 608 
 609     @Override protected void layoutChildren() {
 610         performingLayout = true;
 611         List<Node> managed = getManagedChildren();
 612         Insets insets = getInsets();
 613         Pos align = getAlignmentInternal();
 614         HPos alignHpos = align.getHpos();
 615         VPos alignVpos = align.getVpos();
 616         double width = getWidth();
 617         double height = getHeight();
 618         double top = snapSpace(insets.getTop());
 619         double left = snapSpace(insets.getLeft());
 620         double bottom = snapSpace(insets.getBottom());
 621         double right = snapSpace(insets.getRight());
 622         double space = snapSpace(getSpacing());
 623         boolean shouldFillHeight = shouldFillHeight();
 624 
 625         final double[][] actualAreaWidths = getAreaWidths(managed, height, false);
 626         double contentWidth = adjustAreaWidths(managed, actualAreaWidths, width, height);
 627         double contentHeight = height - top - bottom;
 628 
 629         double x = left + computeXOffset(width - left - right, contentWidth, align.getHpos());
 630         double y = top;
 631         double baselineOffset = -1;
 632         if (alignVpos == VPos.BASELINE) {
 633             double baselineComplement = getMinBaselineComplement();
 634             baselineOffset = getAreaBaselineOffset(managed, marginAccessor, i -> actualAreaWidths[0][i],
 635                     contentHeight, shouldFillHeight, baselineComplement);
 636         }
 637 
 638         for (int i = 0, size = managed.size(); i < size; i++) {
 639             Node child = managed.get(i);
 640             Insets margin = getMargin(child);
 641             layoutInArea(child, x, y, actualAreaWidths[0][i], contentHeight,
 642                     baselineOffset, margin, true, shouldFillHeight,




 379     @Override public Orientation getContentBias() {
 380         if (biasDirty) {
 381             bias = null;
 382             final List<Node> children = getManagedChildren();
 383             for (Node child : children) {
 384                 Orientation contentBias = child.getContentBias();
 385                 if (contentBias != null) {
 386                     bias = contentBias;
 387                     if (contentBias == Orientation.HORIZONTAL) {
 388                         break;
 389                     }
 390                 }
 391             }
 392             biasDirty = false;
 393         }
 394         return bias;
 395     }
 396 
 397     @Override protected double computeMinWidth(double height) {
 398         Insets insets = getInsets();
 399         return snapSpaceX(insets.getLeft()) +
 400                computeContentWidth(getManagedChildren(), height, true) +
 401                snapSpaceX(insets.getRight());
 402     }
 403 
 404     @Override protected double computeMinHeight(double width) {
 405         Insets insets = getInsets();
 406         List<Node>managed = getManagedChildren();
 407         double contentHeight = 0;
 408         if (width != -1 && getContentBias() != null) {
 409             double prefWidths[][] = getAreaWidths(managed, -1, false);
 410             adjustAreaWidths(managed, prefWidths, width, -1);
 411             contentHeight = computeMaxMinAreaHeight(managed, marginAccessor, prefWidths[0], getAlignmentInternal().getVpos());
 412         } else {
 413             contentHeight = computeMaxMinAreaHeight(managed, marginAccessor, getAlignmentInternal().getVpos());
 414         }
 415         return snapSpaceY(insets.getTop()) +
 416                contentHeight +
 417                snapSpaceY(insets.getBottom());
 418     }
 419 
 420     @Override protected double computePrefWidth(double height) {
 421         Insets insets = getInsets();
 422         return snapSpaceX(insets.getLeft()) +
 423                computeContentWidth(getManagedChildren(), height, false) +
 424                snapSpaceX(insets.getRight());
 425     }
 426 
 427     @Override protected double computePrefHeight(double width) {
 428         Insets insets = getInsets();
 429         List<Node>managed = getManagedChildren();
 430         double contentHeight = 0;
 431         if (width != -1 && getContentBias() != null) {
 432             double prefWidths[][] = getAreaWidths(managed, -1, false);
 433             adjustAreaWidths(managed, prefWidths, width, -1);
 434             contentHeight = computeMaxPrefAreaHeight(managed, marginAccessor, prefWidths[0], getAlignmentInternal().getVpos());
 435         } else {
 436             contentHeight = computeMaxPrefAreaHeight(managed, marginAccessor, getAlignmentInternal().getVpos());
 437         }
 438         return snapSpaceY(insets.getTop()) +
 439                contentHeight +
 440                snapSpaceY(insets.getBottom());
 441     }
 442 
 443     private double[][] getAreaWidths(List<Node>managed, double height, boolean minimum) {
 444         // height could be -1
 445         double[][] temp = getTempArray(managed.size());
 446         final double insideHeight = height == -1? -1 : height -
 447                                      snapSpaceY(getInsets().getTop()) - snapSpaceY(getInsets().getBottom());
 448         final boolean shouldFillHeight = shouldFillHeight();
 449         for (int i = 0, size = managed.size(); i < size; i++) {
 450             Node child = managed.get(i);
 451             Insets margin = getMargin(child);
 452             if (minimum) {
 453                 temp[0][i] = computeChildMinAreaWidth(child, getMinBaselineComplement(), margin, insideHeight, shouldFillHeight);
 454             } else {
 455                 temp[0][i] = computeChildPrefAreaWidth(child, getPrefBaselineComplement(), margin, insideHeight, shouldFillHeight);
 456             }
 457         }
 458         return temp;
 459     }
 460 
 461     private double adjustAreaWidths(List<Node>managed, double areaWidths[][], double width, double height) {
 462         Insets insets = getInsets();
 463         double top = snapSpaceY(insets.getTop());
 464         double bottom = snapSpaceY(insets.getBottom());
 465 
 466         double contentWidth = sum(areaWidths[0], managed.size()) + (managed.size()-1)*snapSpaceX(getSpacing());
 467         double extraWidth = width -
 468                 snapSpaceX(insets.getLeft()) - snapSpaceX(insets.getRight()) - contentWidth;
 469 
 470         if (extraWidth != 0) {
 471             final double refHeight = shouldFillHeight() && height != -1? height - top - bottom : -1;
 472             double remaining = growOrShrinkAreaWidths(managed, areaWidths, Priority.ALWAYS, extraWidth, refHeight);
 473             remaining = growOrShrinkAreaWidths(managed, areaWidths, Priority.SOMETIMES, remaining, refHeight);
 474             contentWidth += (extraWidth - remaining);
 475         }
 476         return contentWidth;
 477     }
 478 
 479     private double growOrShrinkAreaWidths(List<Node>managed, double areaWidths[][], Priority priority, double extraWidth, double height) {
 480         final boolean shrinking = extraWidth < 0;
 481         int adjustingNumber = 0;
 482 
 483         double[] usedWidths = areaWidths[0];
 484         double[] temp = areaWidths[1];
 485         final boolean shouldFillHeight = shouldFillHeight();
 486 
 487         if (shrinking) {
 488             adjustingNumber = managed.size();
 489             for (int i = 0, size = managed.size(); i < size; i++) {
 490                 final Node child = managed.get(i);
 491                 temp[i] = computeChildMinAreaWidth(child, getMinBaselineComplement(), getMargin(child), height, shouldFillHeight);
 492             }
 493         } else {
 494             for (int i = 0, size = managed.size(); i < size; i++) {
 495                 final Node child = managed.get(i);
 496                 if (getHgrow(child) == priority) {
 497                     temp[i] = computeChildMaxAreaWidth(child, getMinBaselineComplement(), getMargin(child), height, shouldFillHeight);
 498                     adjustingNumber++;
 499                 } else {
 500                     temp[i] = -1;
 501                 }
 502             }
 503         }
 504 
 505         double available = extraWidth; // will be negative in shrinking case
 506         outer:while (Math.abs(available) > 1 && adjustingNumber > 0) {
 507             final double portion = snapPortionX(available / adjustingNumber); // negative in shrinking case
 508             for (int i = 0, size = managed.size(); i < size; i++) {
 509                 if (temp[i] == -1) {
 510                     continue;
 511                 }
 512                 final double limit = temp[i] - usedWidths[i]; // negative in shrinking case
 513                 final double change = Math.abs(limit) <= Math.abs(portion)? limit : portion;
 514                 usedWidths[i] += change;
 515                 available -= change;
 516                 if (Math.abs(available) < 1) {
 517                     break outer;
 518                 }
 519                 if (Math.abs(change) < Math.abs(portion)) {
 520                     temp[i] = -1;
 521                     adjustingNumber--;
 522                 }
 523             }
 524         }
 525 
 526         return available; // might be negative in shrinking case
 527     }
 528 
 529     private double computeContentWidth(List<Node> managedChildren, double height, boolean minimum) {
 530         return sum(getAreaWidths(managedChildren, height, minimum)[0], managedChildren.size())
 531                 + (managedChildren.size()-1)*snapSpaceX(getSpacing());
 532     }
 533 
 534     private static double sum(double[] array, int size) {
 535         int i = 0;
 536         double res = 0;
 537         while (i != size) {
 538             res += array[i++];
 539         }
 540         return res;
 541     }
 542 
 543     @Override public void requestLayout() {
 544         if (performingLayout) {
 545             return;
 546         }
 547         biasDirty = true;
 548         bias = null;
 549         minBaselineComplement = Double.NaN;
 550         prefBaselineComplement = Double.NaN;
 551         baselineOffset = Double.NaN;


 598                         max = Math.max(max, top + child.getLayoutBounds().getMinY() + offset);
 599                     }
 600                 }
 601                 baselineOffset = max + snappedTopInset();
 602             } else {
 603                 baselineOffset = BASELINE_OFFSET_SAME_AS_HEIGHT;
 604             }
 605         }
 606         return baselineOffset;
 607     }
 608 
 609     @Override protected void layoutChildren() {
 610         performingLayout = true;
 611         List<Node> managed = getManagedChildren();
 612         Insets insets = getInsets();
 613         Pos align = getAlignmentInternal();
 614         HPos alignHpos = align.getHpos();
 615         VPos alignVpos = align.getVpos();
 616         double width = getWidth();
 617         double height = getHeight();
 618         double top = snapSpaceY(insets.getTop());
 619         double left = snapSpaceX(insets.getLeft());
 620         double bottom = snapSpaceY(insets.getBottom());
 621         double right = snapSpaceX(insets.getRight());
 622         double space = snapSpaceX(getSpacing());
 623         boolean shouldFillHeight = shouldFillHeight();
 624 
 625         final double[][] actualAreaWidths = getAreaWidths(managed, height, false);
 626         double contentWidth = adjustAreaWidths(managed, actualAreaWidths, width, height);
 627         double contentHeight = height - top - bottom;
 628 
 629         double x = left + computeXOffset(width - left - right, contentWidth, align.getHpos());
 630         double y = top;
 631         double baselineOffset = -1;
 632         if (alignVpos == VPos.BASELINE) {
 633             double baselineComplement = getMinBaselineComplement();
 634             baselineOffset = getAreaBaselineOffset(managed, marginAccessor, i -> actualAreaWidths[0][i],
 635                     contentHeight, shouldFillHeight, baselineComplement);
 636         }
 637 
 638         for (int i = 0, size = managed.size(); i < size; i++) {
 639             Node child = managed.get(i);
 640             Insets margin = getMargin(child);
 641             layoutInArea(child, x, y, actualAreaWidths[0][i], contentHeight,
 642                     baselineOffset, margin, true, shouldFillHeight,