Skip to content

Commit

Permalink
8307117: TextArea: wrapText property ignored when changing font
Browse files Browse the repository at this point in the history
Reviewed-by: kpk, arapte
  • Loading branch information
Andy Goryachev committed Feb 12, 2024
1 parent a7f6de8 commit de0255d
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand All @@ -25,8 +25,9 @@

package javafx.scene.control.skin;

import com.sun.javafx.scene.control.behavior.TextAreaBehavior;
import com.sun.javafx.scene.control.skin.Utils;
import static com.sun.javafx.PlatformUtil.isMac;
import static com.sun.javafx.PlatformUtil.isWindows;
import java.util.List;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Platform;
Expand Down Expand Up @@ -56,14 +57,11 @@
import javafx.scene.layout.Region;
import javafx.scene.shape.Path;
import javafx.scene.shape.PathElement;
import javafx.scene.text.Text;
import javafx.scene.text.HitInfo;
import javafx.scene.text.Text;
import javafx.util.Duration;

import java.util.List;

import static com.sun.javafx.PlatformUtil.isMac;
import static com.sun.javafx.PlatformUtil.isWindows;
import com.sun.javafx.scene.control.behavior.TextAreaBehavior;
import com.sun.javafx.scene.control.skin.Utils;
/**
* Default skin implementation for the {@link TextArea} control.
*
Expand Down Expand Up @@ -273,6 +271,10 @@ public TextAreaSkin(final TextArea control) {
updatePrefViewportHeight();
});

registerChangeListener(control.fontProperty(), e -> {
contentView.requestLayout();
});

updateFontMetrics();
fontMetrics.addListener(valueModel -> {
updateFontMetrics();
Expand Down Expand Up @@ -1311,8 +1313,7 @@ private class ContentView extends Region {
final double topPadding = snappedTopInset();
final double leftPadding = snappedLeftInset();

double wrappingWidth = Math.max(width - (leftPadding + snappedRightInset()), 0);

double wrappingWidth = textArea.isWrapText() ? Math.max(width - (leftPadding + snappedRightInset()), 0) : 0;
double y = topPadding;

final List<Node> paragraphNodesChildren = paragraphNodes.getChildren();
Expand Down Expand Up @@ -1472,19 +1473,24 @@ private class ContentView extends Region {
}
}

// RT-36454: Fit to width/height only if smaller than viewport.
// RT-36454 (JDK-8097060): Fit to width/height only if smaller than viewport.
// That is, grow to fit but don't shrink to fit.
Bounds viewportBounds = scrollPane.getViewportBounds();
boolean wasFitToWidth = scrollPane.isFitToWidth();
boolean wasFitToHeight = scrollPane.isFitToHeight();
boolean setFitToWidth = textArea.isWrapText() || computePrefWidth(-1) <= viewportBounds.getWidth();
boolean setFitToHeight = computePrefHeight(width) <= viewportBounds.getHeight();
if (wasFitToWidth != setFitToWidth || wasFitToHeight != setFitToHeight) {
scrollPane.setFitToWidth(setFitToWidth);
scrollPane.setFitToHeight(setFitToHeight);
getParent().requestLayout();

// if only there was a way to force a layout from within the layout!
// runlater causes flicker
Platform.runLater(() -> {
scrollPane.setFitToWidth(setFitToWidth);
scrollPane.setFitToHeight(setFitToHeight);
scrollPane.layout();
scrollCaretToVisible();
});
getParent().requestLayout();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -52,9 +52,12 @@
public abstract class BehaviorRobotTestBase<C extends Control> {

private static CountDownLatch startupLatch;
private static Scene scene;
private static Stage stage;
/** Scene valid only during test */
protected static Scene scene;
/** Stage valid only during test */
protected static Stage stage;
private static BorderPane content;
/** The Robot instance */
protected static Robot robot;
private int step;
private static HashMap<Character,KeyCode> keyCodes;
Expand Down Expand Up @@ -338,4 +341,11 @@ protected Runnable addKeyListener() {
control.addEventFilter(KeyEvent.ANY, keyListener);
};
}

/**
* Triggers and waits for 10 pulses to complete in this test's scene.
*/
protected void waitForIdle() {
Util.waitForIdle(scene);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

package test.robot.javafx.scene.control.behavior;

import javafx.geometry.Rectangle2D;
import javafx.scene.control.TextArea;
import javafx.scene.control.skin.TextAreaSkin;
import javafx.scene.text.Font;
import javafx.stage.Window;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import test.util.Util;

/**
* Tests TextArea layout functionality.
*/
public class TextAreaLayoutRobotTest extends TextInputBehaviorRobotTest<TextArea> {
private static final String TEXT = "| one two three four five six seven eight nine ten eleven twelve thirteen |";
private static final double EPSILON = 0.0001;

public TextAreaLayoutRobotTest() {
super(new TextArea());
}

/**
* Tests that the wrap text property is honored when changing font.
* JDK-8314683
*/
@Test
public void testWrapWhenChangingFont() {
waitForIdle();

Util.runAndWait(() -> {
Window w = control.getScene().getWindow();
w.setWidth(200);
w.setHeight(200);
control.setWrapText(false);
control.setText(TEXT);
});

waitForIdle();

Util.runAndWait(() -> {
int len = TEXT.length() - 1;
double y0 = getCharPositionY(0);
double y1 = getCharPositionY(len);
Assertions.assertEquals(y0, y1, EPSILON);
});

waitForIdle();

Util.runAndWait(() -> {
control.setFont(Font.font("Dialog", 24));
});

waitForIdle();

Util.runAndWait(() -> {
int len = TEXT.length() - 1;
double y0 = getCharPositionY(0);
double y1 = getCharPositionY(len);

Assertions.assertEquals(y0, y1, EPSILON);
});
}

private double getCharPositionY(int ix) {
TextAreaSkin skin = (TextAreaSkin)control.getSkin();
Rectangle2D r = skin.getCharacterBounds(ix);
return r.getMinY();
}
}

1 comment on commit de0255d

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.