486 } else { 487 graphicWidth = Utils.boundedSize(w, graphic.minWidth(-1), graphic.maxWidth(-1)); 488 graphicHeight = Utils.boundedSize(h, graphic.minHeight(-1), graphic.maxHeight(-1)); 489 } 490 graphic.resize(graphicWidth, graphicHeight); 491 } else { 492 graphicWidth = graphic.getLayoutBounds().getWidth(); 493 graphicHeight = graphic.getLayoutBounds().getHeight(); 494 } 495 } else { 496 graphic.autosize(); // We have to do this before getting metrics 497 graphicWidth = graphic.getLayoutBounds().getWidth(); 498 graphicHeight = graphic.getLayoutBounds().getHeight(); 499 } 500 501 if (ignoreText) { 502 textWidth = textHeight = 0; 503 text.setText(""); 504 } else { 505 updateDisplayedText(w, h); // Have to do this just in case it needs to be recomputed 506 textWidth = snapSize(Math.min(text.getLayoutBounds().getWidth(), wrapWidth)); 507 textHeight = snapSize(Math.min(text.getLayoutBounds().getHeight(), wrapHeight)); 508 } 509 510 final double gap = (ignoreText || ignoreGraphic) ? 0 : labeled.getGraphicTextGap(); 511 512 // Figure out the contentWidth and contentHeight. This is the width 513 // and height of the Labeled and Graphic together, not the available 514 // content area (which would be a different calculation). 515 double contentWidth = Math.max(graphicWidth, textWidth); 516 double contentHeight = Math.max(graphicHeight, textHeight); 517 if (contentDisplay == ContentDisplay.TOP || contentDisplay == ContentDisplay.BOTTOM) { 518 contentHeight = graphicHeight + gap + textHeight; 519 } else if (contentDisplay == ContentDisplay.LEFT || contentDisplay == ContentDisplay.RIGHT) { 520 contentWidth = graphicWidth + gap + textWidth; 521 } 522 523 // Now we want to compute the x/y location to place the content at. 524 525 // Compute the contentX position based on hpos and the space available 526 double contentX; 527 if (hpos == HPos.LEFT) { 561 // Now to position the graphic and text. At this point I know the 562 // contentX and contentY locations (including the padding and whatnot 563 // that was defined on the Labeled). I also know the content width and 564 // height. So now I just need to lay out the graphic and text within 565 // that content x/y/w/h area. 566 if ((!ignoreGraphic || !ignoreText) && !text.isManaged()) { 567 text.setManaged(true); 568 } 569 570 if (ignoreGraphic && ignoreText) { 571 // There might be a text node as a child, or a graphic node as 572 // a child. However we don't have to do anything for the graphic 573 // node because the only way it can be a child and still have 574 // ignoreGraphic true is if it is unmanaged. Text however might 575 // be a child but still not matter, in which case we will just 576 // stop managing it (although really I wish it just wasn't here 577 // all all in that case) 578 if (text.isManaged()) { 579 text.setManaged(false); 580 } 581 text.relocate(snapPosition(contentX), snapPosition(contentY)); 582 } else if (ignoreGraphic) { 583 // Since I only have to position the text, it goes at the 584 // contentX/contentY location. Note that positionNode will 585 // adjust the text based on the text's minX/minY so no need to 586 // worry about that here 587 text.relocate(snapPosition(contentX), snapPosition(contentY)); 588 if (containsMnemonic) { 589 mnemonic_underscore.setEndX(mnemonicWidth-2.0); 590 mnemonic_underscore.relocate(contentX+preMnemonicWidth, contentY+mnemonicHeight-1); 591 } 592 593 } else if (ignoreText) { 594 // there isn't text to display, so we need to position it 595 // such that it doesn't affect the content area (although when 596 // there is a graphic, the text isn't even in the scene) 597 text.relocate(snapPosition(contentX), snapPosition(contentY)); 598 graphic.relocate(snapPosition(contentX), snapPosition(contentY)); 599 if (containsMnemonic) { 600 mnemonic_underscore.setEndX(mnemonicWidth); 601 mnemonic_underscore.setStrokeWidth(mnemonicHeight/10.0); 602 mnemonic_underscore.relocate(contentX+preMnemonicWidth, contentY+mnemonicHeight-1); 603 604 } 605 } else { 606 // There is both text and a graphic, so I need to position them 607 // relative to each other 608 double graphicX = 0; 609 double graphicY = 0; 610 double textX = 0; 611 double textY = 0; 612 613 if (contentDisplay == ContentDisplay.TOP) { 614 graphicX = contentX + ((contentWidth - graphicWidth) / 2.0); 615 textX = contentX + ((contentWidth - textWidth) / 2.0); 616 // The graphic is above the text, so it is positioned at 617 // graphicY and the text below it. 618 graphicY = contentY; 625 textY = contentY + ((contentHeight - textHeight) / 2.0); 626 } else if (contentDisplay == ContentDisplay.BOTTOM) { 627 graphicX = contentX + ((contentWidth - graphicWidth) / 2.0); 628 textX = contentX + ((contentWidth - textWidth) / 2.0); 629 // The graphic is below the text 630 textY = contentY; 631 graphicY = textY + textHeight + gap; 632 } else if (contentDisplay == ContentDisplay.LEFT) { 633 // The graphic is to the left of the text, so the graphicX is 634 // simply the contentX and the textX is to the right of it. 635 graphicX = contentX; 636 textX = graphicX + graphicWidth + gap; 637 graphicY = contentY + ((contentHeight - graphicHeight) / 2.0); 638 textY = contentY + ((contentHeight - textHeight) / 2.0); 639 } else if (contentDisplay == ContentDisplay.CENTER) { 640 graphicX = contentX + ((contentWidth - graphicWidth) / 2.0); 641 textX = contentX + ((contentWidth - textWidth) / 2.0); 642 graphicY = contentY + ((contentHeight - graphicHeight) / 2.0); 643 textY = contentY + ((contentHeight - textHeight) / 2.0); 644 } 645 text.relocate(snapPosition(textX), snapPosition(textY)); 646 if (containsMnemonic) { 647 mnemonic_underscore.setEndX(mnemonicWidth); 648 mnemonic_underscore.setStrokeWidth(mnemonicHeight/10.0); 649 mnemonic_underscore.relocate(snapPosition(textX+preMnemonicWidth), snapPosition(textY+mnemonicHeight-1)); 650 } 651 graphic.relocate(snapPosition(graphicX), snapPosition(graphicY)); 652 } 653 654 /** 655 * check if the label text overflows it's bounds. 656 * If there's an overflow, and no text clip then 657 * we'll clip it. 658 * If there is no overflow, and the label text has a 659 * clip, then remove it. 660 */ 661 if ((text != null) && 662 ((text.getLayoutBounds().getHeight() > wrapHeight) || 663 (text.getLayoutBounds().getWidth() > wrapWidth))) { 664 665 if (textClip == null) { 666 textClip = new Rectangle(); 667 } 668 669 if (labeled.getEffectiveNodeOrientation() == NodeOrientation.LEFT_TO_RIGHT) { 670 textClip.setX(text.getLayoutBounds().getMinX()); 671 } else { 805 double s = labeled.getLineSpacing(); 806 final double textHeight = Utils.computeTextHeight(font, str, 0, s, text.getBoundsType()); 807 808 double h = textHeight; 809 810 // Now we want to add on the graphic if necessary! 811 if (!isIgnoreGraphic()) { 812 final Node graphic = labeled.getGraphic(); 813 if (labeled.getContentDisplay() == ContentDisplay.TOP 814 || labeled.getContentDisplay() == ContentDisplay.BOTTOM) { 815 h = graphic.minHeight(width) + labeled.getGraphicTextGap() + textHeight; 816 } else { 817 h = Math.max(textHeight, graphic.minHeight(width)); 818 } 819 } 820 821 return topInset + h + bottomInset + topLabelPadding() - bottomLabelPadding(); 822 } 823 824 double topLabelPadding() { 825 return snapSize(getSkinnable().getLabelPadding().getTop()); 826 } 827 828 double bottomLabelPadding() { 829 return snapSize(getSkinnable().getLabelPadding().getBottom()); 830 } 831 832 double leftLabelPadding() { 833 return snapSize(getSkinnable().getLabelPadding().getLeft()); 834 } 835 836 double rightLabelPadding() { 837 return snapSize(getSkinnable().getLabelPadding().getRight()); 838 } 839 840 841 /** 842 * Called whenever some state has changed that affects the text metrics. 843 * Changes here will involve invalidating the display text so the next 844 * call to updateDisplayedText computes a new value, and call requestLayout. 845 */ 846 private void textMetricsChanged() { 847 invalidText = true; 848 getSkinnable().requestLayout(); 849 } 850 851 /* 852 ** The Label is a mnemonic, and it's target node 853 ** has changed, but it's label hasn't so just 854 ** swap them over, and tidy up. 855 */ 856 void mnemonicTargetChanged() { 857 if (containsMnemonic == true) { | 486 } else { 487 graphicWidth = Utils.boundedSize(w, graphic.minWidth(-1), graphic.maxWidth(-1)); 488 graphicHeight = Utils.boundedSize(h, graphic.minHeight(-1), graphic.maxHeight(-1)); 489 } 490 graphic.resize(graphicWidth, graphicHeight); 491 } else { 492 graphicWidth = graphic.getLayoutBounds().getWidth(); 493 graphicHeight = graphic.getLayoutBounds().getHeight(); 494 } 495 } else { 496 graphic.autosize(); // We have to do this before getting metrics 497 graphicWidth = graphic.getLayoutBounds().getWidth(); 498 graphicHeight = graphic.getLayoutBounds().getHeight(); 499 } 500 501 if (ignoreText) { 502 textWidth = textHeight = 0; 503 text.setText(""); 504 } else { 505 updateDisplayedText(w, h); // Have to do this just in case it needs to be recomputed 506 textWidth = snapSizeX(Math.min(text.getLayoutBounds().getWidth(), wrapWidth)); 507 textHeight = snapSizeY(Math.min(text.getLayoutBounds().getHeight(), wrapHeight)); 508 } 509 510 final double gap = (ignoreText || ignoreGraphic) ? 0 : labeled.getGraphicTextGap(); 511 512 // Figure out the contentWidth and contentHeight. This is the width 513 // and height of the Labeled and Graphic together, not the available 514 // content area (which would be a different calculation). 515 double contentWidth = Math.max(graphicWidth, textWidth); 516 double contentHeight = Math.max(graphicHeight, textHeight); 517 if (contentDisplay == ContentDisplay.TOP || contentDisplay == ContentDisplay.BOTTOM) { 518 contentHeight = graphicHeight + gap + textHeight; 519 } else if (contentDisplay == ContentDisplay.LEFT || contentDisplay == ContentDisplay.RIGHT) { 520 contentWidth = graphicWidth + gap + textWidth; 521 } 522 523 // Now we want to compute the x/y location to place the content at. 524 525 // Compute the contentX position based on hpos and the space available 526 double contentX; 527 if (hpos == HPos.LEFT) { 561 // Now to position the graphic and text. At this point I know the 562 // contentX and contentY locations (including the padding and whatnot 563 // that was defined on the Labeled). I also know the content width and 564 // height. So now I just need to lay out the graphic and text within 565 // that content x/y/w/h area. 566 if ((!ignoreGraphic || !ignoreText) && !text.isManaged()) { 567 text.setManaged(true); 568 } 569 570 if (ignoreGraphic && ignoreText) { 571 // There might be a text node as a child, or a graphic node as 572 // a child. However we don't have to do anything for the graphic 573 // node because the only way it can be a child and still have 574 // ignoreGraphic true is if it is unmanaged. Text however might 575 // be a child but still not matter, in which case we will just 576 // stop managing it (although really I wish it just wasn't here 577 // all all in that case) 578 if (text.isManaged()) { 579 text.setManaged(false); 580 } 581 text.relocate(snapPositionX(contentX), snapPositionY(contentY)); 582 } else if (ignoreGraphic) { 583 // Since I only have to position the text, it goes at the 584 // contentX/contentY location. Note that positionNode will 585 // adjust the text based on the text's minX/minY so no need to 586 // worry about that here 587 text.relocate(snapPositionX(contentX), snapPositionY(contentY)); 588 if (containsMnemonic) { 589 mnemonic_underscore.setEndX(mnemonicWidth-2.0); 590 mnemonic_underscore.relocate(contentX+preMnemonicWidth, contentY+mnemonicHeight-1); 591 } 592 593 } else if (ignoreText) { 594 // there isn't text to display, so we need to position it 595 // such that it doesn't affect the content area (although when 596 // there is a graphic, the text isn't even in the scene) 597 text.relocate(snapPositionX(contentX), snapPositionY(contentY)); 598 graphic.relocate(snapPositionX(contentX), snapPositionY(contentY)); 599 if (containsMnemonic) { 600 mnemonic_underscore.setEndX(mnemonicWidth); 601 mnemonic_underscore.setStrokeWidth(mnemonicHeight/10.0); 602 mnemonic_underscore.relocate(contentX+preMnemonicWidth, contentY+mnemonicHeight-1); 603 604 } 605 } else { 606 // There is both text and a graphic, so I need to position them 607 // relative to each other 608 double graphicX = 0; 609 double graphicY = 0; 610 double textX = 0; 611 double textY = 0; 612 613 if (contentDisplay == ContentDisplay.TOP) { 614 graphicX = contentX + ((contentWidth - graphicWidth) / 2.0); 615 textX = contentX + ((contentWidth - textWidth) / 2.0); 616 // The graphic is above the text, so it is positioned at 617 // graphicY and the text below it. 618 graphicY = contentY; 625 textY = contentY + ((contentHeight - textHeight) / 2.0); 626 } else if (contentDisplay == ContentDisplay.BOTTOM) { 627 graphicX = contentX + ((contentWidth - graphicWidth) / 2.0); 628 textX = contentX + ((contentWidth - textWidth) / 2.0); 629 // The graphic is below the text 630 textY = contentY; 631 graphicY = textY + textHeight + gap; 632 } else if (contentDisplay == ContentDisplay.LEFT) { 633 // The graphic is to the left of the text, so the graphicX is 634 // simply the contentX and the textX is to the right of it. 635 graphicX = contentX; 636 textX = graphicX + graphicWidth + gap; 637 graphicY = contentY + ((contentHeight - graphicHeight) / 2.0); 638 textY = contentY + ((contentHeight - textHeight) / 2.0); 639 } else if (contentDisplay == ContentDisplay.CENTER) { 640 graphicX = contentX + ((contentWidth - graphicWidth) / 2.0); 641 textX = contentX + ((contentWidth - textWidth) / 2.0); 642 graphicY = contentY + ((contentHeight - graphicHeight) / 2.0); 643 textY = contentY + ((contentHeight - textHeight) / 2.0); 644 } 645 text.relocate(snapPositionX(textX), snapPositionY(textY)); 646 if (containsMnemonic) { 647 mnemonic_underscore.setEndX(mnemonicWidth); 648 mnemonic_underscore.setStrokeWidth(mnemonicHeight/10.0); 649 mnemonic_underscore.relocate(snapPositionX(textX+preMnemonicWidth), snapPositionY(textY+mnemonicHeight-1)); 650 } 651 graphic.relocate(snapPositionX(graphicX), snapPositionY(graphicY)); 652 } 653 654 /** 655 * check if the label text overflows it's bounds. 656 * If there's an overflow, and no text clip then 657 * we'll clip it. 658 * If there is no overflow, and the label text has a 659 * clip, then remove it. 660 */ 661 if ((text != null) && 662 ((text.getLayoutBounds().getHeight() > wrapHeight) || 663 (text.getLayoutBounds().getWidth() > wrapWidth))) { 664 665 if (textClip == null) { 666 textClip = new Rectangle(); 667 } 668 669 if (labeled.getEffectiveNodeOrientation() == NodeOrientation.LEFT_TO_RIGHT) { 670 textClip.setX(text.getLayoutBounds().getMinX()); 671 } else { 805 double s = labeled.getLineSpacing(); 806 final double textHeight = Utils.computeTextHeight(font, str, 0, s, text.getBoundsType()); 807 808 double h = textHeight; 809 810 // Now we want to add on the graphic if necessary! 811 if (!isIgnoreGraphic()) { 812 final Node graphic = labeled.getGraphic(); 813 if (labeled.getContentDisplay() == ContentDisplay.TOP 814 || labeled.getContentDisplay() == ContentDisplay.BOTTOM) { 815 h = graphic.minHeight(width) + labeled.getGraphicTextGap() + textHeight; 816 } else { 817 h = Math.max(textHeight, graphic.minHeight(width)); 818 } 819 } 820 821 return topInset + h + bottomInset + topLabelPadding() - bottomLabelPadding(); 822 } 823 824 double topLabelPadding() { 825 return snapSizeY(getSkinnable().getLabelPadding().getTop()); 826 } 827 828 double bottomLabelPadding() { 829 return snapSizeY(getSkinnable().getLabelPadding().getBottom()); 830 } 831 832 double leftLabelPadding() { 833 return snapSizeX(getSkinnable().getLabelPadding().getLeft()); 834 } 835 836 double rightLabelPadding() { 837 return snapSizeX(getSkinnable().getLabelPadding().getRight()); 838 } 839 840 841 /** 842 * Called whenever some state has changed that affects the text metrics. 843 * Changes here will involve invalidating the display text so the next 844 * call to updateDisplayedText computes a new value, and call requestLayout. 845 */ 846 private void textMetricsChanged() { 847 invalidText = true; 848 getSkinnable().requestLayout(); 849 } 850 851 /* 852 ** The Label is a mnemonic, and it's target node 853 ** has changed, but it's label hasn't so just 854 ** swap them over, and tidy up. 855 */ 856 void mnemonicTargetChanged() { 857 if (containsMnemonic == true) { |