370 break; 371 } 372 } 373 } 374 biasDirty = false; 375 } 376 return bias; 377 } 378 379 @Override protected double computeMinWidth(double height) { 380 Insets insets = getInsets(); 381 List<Node>managed = getManagedChildren(); 382 double contentWidth = 0; 383 if (height != -1 && getContentBias() != null) { 384 double prefHeights[][] = getAreaHeights(managed, -1, false); 385 adjustAreaHeights(managed, prefHeights, height, -1); 386 contentWidth = computeMaxMinAreaWidth(managed, marginAccessor, prefHeights[0], false); 387 } else { 388 contentWidth = computeMaxMinAreaWidth(managed, marginAccessor); 389 } 390 return snapSpace(insets.getLeft()) + contentWidth + snapSpace(insets.getRight()); 391 } 392 393 @Override protected double computeMinHeight(double width) { 394 Insets insets = getInsets(); 395 return snapSpace(insets.getTop()) + 396 computeContentHeight(getManagedChildren(), width, true) + 397 snapSpace(insets.getBottom()); 398 } 399 400 @Override protected double computePrefWidth(double height) { 401 Insets insets = getInsets(); 402 List<Node>managed = getManagedChildren(); 403 double contentWidth = 0; 404 if (height != -1 && getContentBias() != null) { 405 double prefHeights[][] = getAreaHeights(managed, -1, false); 406 adjustAreaHeights(managed, prefHeights, height, -1); 407 contentWidth = computeMaxPrefAreaWidth(managed, marginAccessor, prefHeights[0], false); 408 } else { 409 contentWidth = computeMaxPrefAreaWidth(managed, marginAccessor); 410 } 411 return snapSpace(insets.getLeft()) + contentWidth + snapSpace(insets.getRight()); 412 } 413 414 @Override protected double computePrefHeight(double width) { 415 Insets insets = getInsets(); 416 double d = snapSpace(insets.getTop()) + 417 computeContentHeight(getManagedChildren(), width, false) + 418 snapSpace(insets.getBottom()); 419 return d; 420 } 421 422 423 private double[][] getAreaHeights(List<Node>managed, double width, boolean minimum) { 424 // width could be -1 425 double[][] temp = getTempArray(managed.size()); 426 final double insideWidth = width == -1? -1 : width - 427 snapSpace(getInsets().getLeft()) - snapSpace(getInsets().getRight()); 428 final boolean isFillWidth = isFillWidth(); 429 for (int i = 0, size = managed.size(); i < size; i++) { 430 Node child = managed.get(i); 431 Insets margin = getMargin(child); 432 if (minimum) { 433 if (insideWidth != -1 && isFillWidth) { 434 temp[0][i] = computeChildMinAreaHeight(child, -1, margin, insideWidth); 435 } else { 436 temp[0][i] = computeChildMinAreaHeight(child, -1, margin, -1); 437 } 438 } else { 439 if (insideWidth != -1 && isFillWidth) { 440 temp[0][i] = computeChildPrefAreaHeight(child, -1, margin, insideWidth); 441 } else { 442 temp[0][i] = computeChildPrefAreaHeight(child, -1, margin, -1); 443 } 444 } 445 } 446 return temp; 447 } 448 449 private double adjustAreaHeights(List<Node>managed, double areaHeights[][], double height, double width) { 450 Insets insets = getInsets(); 451 double left = snapSpace(insets.getLeft()); 452 double right = snapSpace(insets.getRight()); 453 454 double contentHeight = sum(areaHeights[0], managed.size()) + (managed.size()-1)*snapSpace(getSpacing()); 455 double extraHeight = height - 456 snapSpace(insets.getTop()) - snapSpace(insets.getBottom()) - contentHeight; 457 458 if (extraHeight != 0) { 459 final double refWidth = isFillWidth()&& width != -1? width - left - right : -1; 460 double remaining = growOrShrinkAreaHeights(managed, areaHeights, Priority.ALWAYS, extraHeight, refWidth); 461 remaining = growOrShrinkAreaHeights(managed, areaHeights, Priority.SOMETIMES, remaining, refWidth); 462 contentHeight += (extraHeight - remaining); 463 } 464 465 return contentHeight; 466 } 467 468 private double growOrShrinkAreaHeights(List<Node>managed, double areaHeights[][], Priority priority, double extraHeight, double width) { 469 final boolean shrinking = extraHeight < 0; 470 int adjustingNumber = 0; 471 472 double[] usedHeights = areaHeights[0]; 473 double[] temp = areaHeights[1]; 474 475 if (shrinking) { 476 adjustingNumber = managed.size(); 477 for (int i = 0, size = managed.size(); i < size; i++) { 478 final Node child = managed.get(i); 479 temp[i] = computeChildMinAreaHeight(child, -1, getMargin(child), width); 480 } 481 } else { 482 for (int i = 0, size = managed.size(); i < size; i++) { 483 final Node child = managed.get(i); 484 if (getVgrow(child) == priority) { 485 temp[i] = computeChildMaxAreaHeight(child, -1, getMargin(child), width); 486 adjustingNumber++; 487 } else { 488 temp[i] = -1; 489 } 490 } 491 } 492 493 double available = extraHeight; // will be negative in shrinking case 494 outer: while (Math.abs(available) > 1 && adjustingNumber > 0) { 495 final double portion = snapPortion(available / adjustingNumber); // negative in shrinking case 496 for (int i = 0, size = managed.size(); i < size; i++) { 497 if (temp[i] == -1) { 498 continue; 499 } 500 final double limit = temp[i] - usedHeights[i]; // negative in shrinking case 501 final double change = Math.abs(limit) <= Math.abs(portion)? limit : portion; 502 usedHeights[i] += change; 503 available -= change; 504 if (Math.abs(available) < 1) { 505 break outer; 506 } 507 if (Math.abs(change) < Math.abs(portion)) { 508 temp[i] = -1; 509 adjustingNumber--; 510 } 511 } 512 } 513 514 return available; // might be negative in shrinking case 515 } 516 517 private double computeContentHeight(List<Node> managedChildren, double width, boolean minimum) { 518 return sum(getAreaHeights(managedChildren, width, minimum)[0], managedChildren.size()) 519 + (managedChildren.size()-1)*snapSpace(getSpacing()); 520 } 521 522 private static double sum(double[] array, int size) { 523 int i = 0; 524 double res = 0; 525 while (i != size) { 526 res += array[i++]; 527 } 528 return res; 529 } 530 531 @Override public void requestLayout() { 532 if (performingLayout) { 533 return; 534 } 535 biasDirty = true; 536 bias = null; 537 super.requestLayout(); 538 } 539 540 @Override protected void layoutChildren() { 541 performingLayout = true; 542 List<Node> managed = getManagedChildren(); 543 Insets insets = getInsets(); 544 double width = getWidth(); 545 double height = getHeight(); 546 double top = snapSpace(insets.getTop()); 547 double left = snapSpace(insets.getLeft()); 548 double bottom = snapSpace(insets.getBottom()); 549 double right = snapSpace(insets.getRight()); 550 double space = snapSpace(getSpacing()); 551 HPos hpos = getAlignmentInternal().getHpos(); 552 VPos vpos = getAlignmentInternal().getVpos(); 553 boolean isFillWidth = isFillWidth(); 554 555 double[][] actualAreaHeights = getAreaHeights(managed, width, false); 556 double contentWidth = width - left - right; 557 double contentHeight = adjustAreaHeights(managed, actualAreaHeights, height, width); 558 559 double x = left; 560 double y = top + computeYOffset(height - top - bottom, contentHeight, vpos); 561 562 for (int i = 0, size = managed.size(); i < size; i++) { 563 Node child = managed.get(i); 564 layoutInArea(child, x, y, contentWidth, actualAreaHeights[0][i], 565 /* baseline shouldn't matter */actualAreaHeights[0][i], 566 getMargin(child), isFillWidth, true, 567 hpos, vpos); 568 y += actualAreaHeights[0][i] + space; 569 } 570 performingLayout = false; | 370 break; 371 } 372 } 373 } 374 biasDirty = false; 375 } 376 return bias; 377 } 378 379 @Override protected double computeMinWidth(double height) { 380 Insets insets = getInsets(); 381 List<Node>managed = getManagedChildren(); 382 double contentWidth = 0; 383 if (height != -1 && getContentBias() != null) { 384 double prefHeights[][] = getAreaHeights(managed, -1, false); 385 adjustAreaHeights(managed, prefHeights, height, -1); 386 contentWidth = computeMaxMinAreaWidth(managed, marginAccessor, prefHeights[0], false); 387 } else { 388 contentWidth = computeMaxMinAreaWidth(managed, marginAccessor); 389 } 390 return snapSpaceX(insets.getLeft()) + contentWidth + snapSpaceX(insets.getRight()); 391 } 392 393 @Override protected double computeMinHeight(double width) { 394 Insets insets = getInsets(); 395 return snapSpaceY(insets.getTop()) + 396 computeContentHeight(getManagedChildren(), width, true) + 397 snapSpaceY(insets.getBottom()); 398 } 399 400 @Override protected double computePrefWidth(double height) { 401 Insets insets = getInsets(); 402 List<Node>managed = getManagedChildren(); 403 double contentWidth = 0; 404 if (height != -1 && getContentBias() != null) { 405 double prefHeights[][] = getAreaHeights(managed, -1, false); 406 adjustAreaHeights(managed, prefHeights, height, -1); 407 contentWidth = computeMaxPrefAreaWidth(managed, marginAccessor, prefHeights[0], false); 408 } else { 409 contentWidth = computeMaxPrefAreaWidth(managed, marginAccessor); 410 } 411 return snapSpaceX(insets.getLeft()) + contentWidth + snapSpaceX(insets.getRight()); 412 } 413 414 @Override protected double computePrefHeight(double width) { 415 Insets insets = getInsets(); 416 double d = snapSpaceY(insets.getTop()) + 417 computeContentHeight(getManagedChildren(), width, false) + 418 snapSpaceY(insets.getBottom()); 419 return d; 420 } 421 422 423 private double[][] getAreaHeights(List<Node>managed, double width, boolean minimum) { 424 // width could be -1 425 double[][] temp = getTempArray(managed.size()); 426 final double insideWidth = width == -1? -1 : width - 427 snapSpaceX(getInsets().getLeft()) - snapSpaceX(getInsets().getRight()); 428 final boolean isFillWidth = isFillWidth(); 429 for (int i = 0, size = managed.size(); i < size; i++) { 430 Node child = managed.get(i); 431 Insets margin = getMargin(child); 432 if (minimum) { 433 if (insideWidth != -1 && isFillWidth) { 434 temp[0][i] = computeChildMinAreaHeight(child, -1, margin, insideWidth); 435 } else { 436 temp[0][i] = computeChildMinAreaHeight(child, -1, margin, -1); 437 } 438 } else { 439 if (insideWidth != -1 && isFillWidth) { 440 temp[0][i] = computeChildPrefAreaHeight(child, -1, margin, insideWidth); 441 } else { 442 temp[0][i] = computeChildPrefAreaHeight(child, -1, margin, -1); 443 } 444 } 445 } 446 return temp; 447 } 448 449 private double adjustAreaHeights(List<Node>managed, double areaHeights[][], double height, double width) { 450 Insets insets = getInsets(); 451 double left = snapSpaceX(insets.getLeft()); 452 double right = snapSpaceX(insets.getRight()); 453 454 double contentHeight = sum(areaHeights[0], managed.size()) + (managed.size()-1)*snapSpaceY(getSpacing()); 455 double extraHeight = height - 456 snapSpaceY(insets.getTop()) - snapSpaceY(insets.getBottom()) - contentHeight; 457 458 if (extraHeight != 0) { 459 final double refWidth = isFillWidth()&& width != -1? width - left - right : -1; 460 double remaining = growOrShrinkAreaHeights(managed, areaHeights, Priority.ALWAYS, extraHeight, refWidth); 461 remaining = growOrShrinkAreaHeights(managed, areaHeights, Priority.SOMETIMES, remaining, refWidth); 462 contentHeight += (extraHeight - remaining); 463 } 464 465 return contentHeight; 466 } 467 468 private double growOrShrinkAreaHeights(List<Node>managed, double areaHeights[][], Priority priority, double extraHeight, double width) { 469 final boolean shrinking = extraHeight < 0; 470 int adjustingNumber = 0; 471 472 double[] usedHeights = areaHeights[0]; 473 double[] temp = areaHeights[1]; 474 475 if (shrinking) { 476 adjustingNumber = managed.size(); 477 for (int i = 0, size = managed.size(); i < size; i++) { 478 final Node child = managed.get(i); 479 temp[i] = computeChildMinAreaHeight(child, -1, getMargin(child), width); 480 } 481 } else { 482 for (int i = 0, size = managed.size(); i < size; i++) { 483 final Node child = managed.get(i); 484 if (getVgrow(child) == priority) { 485 temp[i] = computeChildMaxAreaHeight(child, -1, getMargin(child), width); 486 adjustingNumber++; 487 } else { 488 temp[i] = -1; 489 } 490 } 491 } 492 493 double available = extraHeight; // will be negative in shrinking case 494 outer: while (Math.abs(available) > 1 && adjustingNumber > 0) { 495 final double portion = snapPortionY(available / adjustingNumber); // negative in shrinking case 496 for (int i = 0, size = managed.size(); i < size; i++) { 497 if (temp[i] == -1) { 498 continue; 499 } 500 final double limit = temp[i] - usedHeights[i]; // negative in shrinking case 501 final double change = Math.abs(limit) <= Math.abs(portion)? limit : portion; 502 usedHeights[i] += change; 503 available -= change; 504 if (Math.abs(available) < 1) { 505 break outer; 506 } 507 if (Math.abs(change) < Math.abs(portion)) { 508 temp[i] = -1; 509 adjustingNumber--; 510 } 511 } 512 } 513 514 return available; // might be negative in shrinking case 515 } 516 517 private double computeContentHeight(List<Node> managedChildren, double width, boolean minimum) { 518 return sum(getAreaHeights(managedChildren, width, minimum)[0], managedChildren.size()) 519 + (managedChildren.size()-1)*snapSpaceY(getSpacing()); 520 } 521 522 private static double sum(double[] array, int size) { 523 int i = 0; 524 double res = 0; 525 while (i != size) { 526 res += array[i++]; 527 } 528 return res; 529 } 530 531 @Override public void requestLayout() { 532 if (performingLayout) { 533 return; 534 } 535 biasDirty = true; 536 bias = null; 537 super.requestLayout(); 538 } 539 540 @Override protected void layoutChildren() { 541 performingLayout = true; 542 List<Node> managed = getManagedChildren(); 543 Insets insets = getInsets(); 544 double width = getWidth(); 545 double height = getHeight(); 546 double top = snapSpaceY(insets.getTop()); 547 double left = snapSpaceX(insets.getLeft()); 548 double bottom = snapSpaceY(insets.getBottom()); 549 double right = snapSpaceX(insets.getRight()); 550 double space = snapSpaceY(getSpacing()); 551 HPos hpos = getAlignmentInternal().getHpos(); 552 VPos vpos = getAlignmentInternal().getVpos(); 553 boolean isFillWidth = isFillWidth(); 554 555 double[][] actualAreaHeights = getAreaHeights(managed, width, false); 556 double contentWidth = width - left - right; 557 double contentHeight = adjustAreaHeights(managed, actualAreaHeights, height, width); 558 559 double x = left; 560 double y = top + computeYOffset(height - top - bottom, contentHeight, vpos); 561 562 for (int i = 0, size = managed.size(); i < size; i++) { 563 Node child = managed.get(i); 564 layoutInArea(child, x, y, contentWidth, actualAreaHeights[0][i], 565 /* baseline shouldn't matter */actualAreaHeights[0][i], 566 getMargin(child), isFillWidth, true, 567 hpos, vpos); 568 y += actualAreaHeights[0][i] + space; 569 } 570 performingLayout = false; |