Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8242548

Wrapped labeled controls using -fx-line-spacing cut text off

XMLWordPrintable

    • x86_64
    • windows_10

      A DESCRIPTION OF THE PROBLEM :
      When using -fx-line-spacing in the JavaFX 14, both positive and negative values donot work as expected. In both cases the text height is computed correctly, however the calculation which decides when to cut-off text does not use the line spacing resulting in the text being cut off early.

      The computeClippedWrappedText needs to be passed the line spacing parameter, and make use of it. It should set it on the helper object and also increase the height with it in order to calculate the resulting String correctly.

      Patch:

      diff --git a/modules/javafx.controls/src/main/java/com/sun/javafx/scene/control/skin/Utils.java b/modules/javafx.controls/src/main/java/com/sun/javafx/scene/control/skin/Utils.java
      index f0c3bd6b0e..fed2435857 100644
      --- a/modules/javafx.controls/src/main/java/com/sun/javafx/scene/control/skin/Utils.java
      +++ b/modules/javafx.controls/src/main/java/com/sun/javafx/scene/control/skin/Utils.java
      @@ -417,12 +417,14 @@ public class Utils {
           }

           public static String computeClippedWrappedText(Font font, String text, double width,
      - double height, OverrunStyle truncationStyle,
      + double height, double lineSpacing, OverrunStyle truncationStyle,
                                                   String ellipsisString, TextBoundsType boundsType) {
               if (font == null) {
                   throw new IllegalArgumentException("Must specify a font");
               }

      + height += lineSpacing;
      +
               String ellipsis = (truncationStyle == CLIP) ? "" : ellipsisString;
               int eLen = ellipsis.length();
               // Do this before using helper, as it's not reentrant.
      @@ -438,7 +440,7 @@ public class Utils {
               helper.setFont(font);
               helper.setWrappingWidth((int)Math.ceil(width));
               helper.setBoundsType(boundsType);
      - helper.setLineSpacing(0);
      + helper.setLineSpacing(lineSpacing);

               boolean leading = (truncationStyle == LEADING_ELLIPSIS ||
                                   truncationStyle == LEADING_WORD_ELLIPSIS);
      diff --git a/modules/javafx.controls/src/main/java/javafx/scene/control/skin/LabeledSkinBase.java b/modules/javafx.controls/src/main/java/javafx/scene/control/skin/LabeledSkinBase.java
      index 119df7dabc..2efcc5a6fc 100644
      --- a/modules/javafx.controls/src/main/java/javafx/scene/control/skin/LabeledSkinBase.java
      +++ b/modules/javafx.controls/src/main/java/javafx/scene/control/skin/LabeledSkinBase.java
      @@ -1107,7 +1107,7 @@ public abstract class LabeledSkinBase<C extends Labeled> extends SkinBase<C> {
                   String ellipsisString = labeled.getEllipsisString();

                   if (labeled.isWrapText()) {
      - result = Utils.computeClippedWrappedText(font, s, wrapWidth, wrapHeight, truncationStyle, ellipsisString, text.getBoundsType());
      + result = Utils.computeClippedWrappedText(font, s, wrapWidth, wrapHeight, labeled.getLineSpacing(), truncationStyle, ellipsisString, text.getBoundsType());
                   } else if (multiline) {
                       StringBuilder sb = new StringBuilder();






      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the attached program. It will display 3 reflowed labels. On the left one with a positive line spacing, in the middle one with a negative spacing and on the right one with standard spacing.

      Only the label on the right display correctly and fully.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      All three labels should display their text correctly and fully without it getting cut off.
      ACTUAL -
      Only the (right) label with the standard line spacing is displayed correctly.

      ---------- BEGIN SOURCE ----------
      import javafx.application.Application;
      import javafx.scene.Scene;
      import javafx.scene.control.Label;
      import javafx.scene.layout.HBox;
      import javafx.stage.Stage;

      public class Main extends Application {

        public static void main(String[] args) {
          Application.launch(args);
        }

        @Override
        public void start(Stage stage) throws Exception {
          System.out.println("Hello World");
          HBox hbox = new HBox();

          Label label1 = new Label("Note, if you add a junit test that for the new package, you will likely also need an export to ALL-UNNAMED (which the junit jar is a member of). The result may be two exports in buildSrc/addExport to add the temporary workarounds required for both development and test. If you are not modifying unit tests - do not add the ALL-UNNAMED line.\n" +
            "\n" +
            "Complete development of your new package and adding unit test coverage, and all of the other process we normally do.\n" +
            "\n" +
            "Your complete change set will now contain all of the delta required for the nightly build and test your changes. The promotion process will soon merge your module-info changes into the JDK. Once there is a promoted JDK that has the new module-info changes, it is possible to move to the second step."
          );

          label1.setStyle("-fx-border-width: 3px; -fx-border-color: red; -fx-line-spacing: 15; -fx-wrap-text: true; -fx-font-size: 20;");

          Label label2 = new Label("Note, if you add a junit test that for the new package, you will likely also need an export to ALL-UNNAMED (which the junit jar is a member of). The result may be two exports in buildSrc/addExport to add the temporary workarounds required for both development and test. If you are not modifying unit tests - do not add the ALL-UNNAMED line.\n" +
              "\n" +
              "Complete development of your new package and adding unit test coverage, and all of the other process we normally do.\n" +
              "\n" +
              "Your complete change set will now contain all of the delta required for the nightly build and test your changes. The promotion process will soon merge your module-info changes into the JDK. Once there is a promoted JDK that has the new module-info changes, it is possible to move to the second step."
          );

          label2.setStyle("-fx-border-width: 3px; -fx-border-color: red; -fx-line-spacing: -5; -fx-wrap-text: true; -fx-font-size: 20;");

          Label label3 = new Label("Note, if you add a junit test that for the new package, you will likely also need an export to ALL-UNNAMED (which the junit jar is a member of). The result may be two exports in buildSrc/addExport to add the temporary workarounds required for both development and test. If you are not modifying unit tests - do not add the ALL-UNNAMED line.\n" +
              "\n" +
              "Complete development of your new package and adding unit test coverage, and all of the other process we normally do.\n" +
              "\n" +
              "Your complete change set will now contain all of the delta required for the nightly build and test your changes. The promotion process will soon merge your module-info changes into the JDK. Once there is a promoted JDK that has the new module-info changes, it is possible to move to the second step."
          );

          label3.setStyle("-fx-border-width: 3px; -fx-border-color: red; -fx-line-spacing: 0; -fx-wrap-text: true; -fx-font-size: 20;");


          label1.setPrefWidth(500);
          label2.setPrefWidth(500);
          label3.setPrefWidth(500);
          hbox.getChildren().addAll(label1, label2, label3);

          Scene scene = new Scene(hbox);

          stage.setScene(scene);
          stage.show();
        }
      }

      ---------- END SOURCE ----------

      FREQUENCY : always


        1. Main.java
          4 kB
          Pardeep Sharma

            jhendrikx John Hendrikx
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: