diff a/modules/javafx.graphics/src/main/docs/javafx/scene/doc-files/cssref.html b/modules/javafx.graphics/src/main/docs/javafx/scene/doc-files/cssref.html
--- a/modules/javafx.graphics/src/main/docs/javafx/scene/doc-files/cssref.html
+++ b/modules/javafx.graphics/src/main/docs/javafx/scene/doc-files/cssref.html
@@ -3026,10 +3026,15 @@
<boolean> |
false |
|
+ -fx-tab-size |
+ <integer> |
+ 8 |
+ |
+
-fx-text-alignment |
[ left | center | right | justify ] |
left |
inherits |
diff a/modules/javafx.graphics/src/main/java/com/sun/javafx/scene/text/TextLayout.java b/modules/javafx.graphics/src/main/java/com/sun/javafx/scene/text/TextLayout.java
--- a/modules/javafx.graphics/src/main/java/com/sun/javafx/scene/text/TextLayout.java
+++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/scene/text/TextLayout.java
@@ -1,7 +1,7 @@
/*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, 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
@@ -73,10 +73,12 @@
public static final int TYPE_STRIKETHROUGH = 1 << 2;
public static final int TYPE_BASELINE = 1 << 3;
public static final int TYPE_TOP = 1 << 4;
public static final int TYPE_BEARINGS = 1 << 5;
+ static final int DEFAULT_TAB_SIZE = 8;
+
public static class Hit {
int charIndex;
int insertionIndex;
boolean leading;
@@ -186,10 +188,19 @@
* @param type the type of the shapes to include
* @return the shape
*/
public Shape getShape(int type, TextSpan filter);
+ /**
+ * Sets the tab size for the TextLayout.
+ *
+ * @param spaces the number of spaces represented by a tab. Default is 8.
+ * Minimum is 1, lower values will be clamped to 1.
+ * @return returns true if the call modifies the layout internal state.
+ */
+ public boolean setTabSize(int spaces);
+
public Hit getHitInfo(float x, float y);
public PathElement[] getCaretShape(int offset, boolean isLeading,
float x, float y);
public PathElement[] getRange(int start, int end, int type,
diff a/modules/javafx.graphics/src/main/java/com/sun/javafx/text/PrismTextLayout.java b/modules/javafx.graphics/src/main/java/com/sun/javafx/text/PrismTextLayout.java
--- a/modules/javafx.graphics/src/main/java/com/sun/javafx/text/PrismTextLayout.java
+++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/text/PrismTextLayout.java
@@ -1,7 +1,7 @@
/*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, 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
@@ -78,10 +78,11 @@
private float layoutWidth, layoutHeight;
private float wrapWidth, spacing;
private LayoutCache layoutCache;
private Shape shape;
private int flags;
+ private int tabSize = DEFAULT_TAB_SIZE;
public PrismTextLayout() {
logicalBounds = new RectBounds();
flags = ALIGN_LEFT;
}
@@ -646,10 +647,22 @@
shape = outline;
}
return outline;
}
+ @Override
+ public boolean setTabSize(int spaces) {
+ if (spaces < 1)
+ spaces = 1;
+ if (tabSize != spaces) {
+ tabSize = spaces;
+ relayout();
+ return true;
+ }
+ return false;
+ }
+
/***************************************************************************
* *
* Text Layout Implementation *
* *
**************************************************************************/
@@ -1002,11 +1015,11 @@
}
}
} else {
spaceAdvance = strike.getCharAdvance(' ');
}
- return 8 * spaceAdvance;
+ return tabSize * spaceAdvance;
}
private void layout() {
/* Try the cache */
initCache();
diff a/modules/javafx.graphics/src/main/java/javafx/scene/text/Text.java b/modules/javafx.graphics/src/main/java/javafx/scene/text/Text.java
--- a/modules/javafx.graphics/src/main/java/javafx/scene/text/Text.java
+++ b/modules/javafx.graphics/src/main/java/javafx/scene/text/Text.java
@@ -80,10 +80,11 @@
import javafx.css.CssMetaData;
import javafx.css.FontCssMetaData;
import javafx.css.Styleable;
import javafx.css.StyleableBooleanProperty;
import javafx.css.StyleableDoubleProperty;
+import javafx.css.StyleableIntegerProperty;
import javafx.css.StyleableObjectProperty;
import javafx.css.StyleableProperty;
import javafx.geometry.BoundingBox;
import javafx.geometry.Bounds;
import javafx.geometry.NodeOrientation;
@@ -305,10 +306,11 @@
if (getEffectiveNodeOrientation() == NodeOrientation.RIGHT_TO_LEFT) {
layout.setDirection(TextLayout.DIRECTION_RTL);
} else {
layout.setDirection(TextLayout.DIRECTION_LTR);
}
+ layout.setTabSize(getTabSize());
}
return layout;
}
private GlyphList[] textRuns = null;
@@ -1265,22 +1267,58 @@
y = getYAdjustment(getVisualBounds()) + (float)getY();
}
return TransformedShape.translatedShape(shape, x, y);
}
+ /**
+ * The size of a tab stop in spaces.
+ *
+ * @return the {@code tabSize} property
+ *
+ * @defaultValue {@code 8}
+ *
+ * @since 14
+ */
+ public final IntegerProperty tabSizeProperty() {
+ return getTextAttribute().tabSizeProperty();
+ }
+
+ /**
+ * Gets the size of a tab stop in spaces.
+ * @return the size of a tab in spaces
+ * @since 14
+ */
+ public final int getTabSize() {
+ if (attributes == null || attributes.tabSize == null) {
+ return TextLayout.DEFAULT_TAB_SIZE;
+ }
+ return getTextAttribute().getTabSize();
+ }
+
+ /**
+ * Sets the size of a tab stop.
+ * @param spaces the size of a tab in spaces. Defaults to 8.
+ * Minimum is 1, lower values will be clamped to 1.
+ * @since 14
+ */
+ public final void setTabSize(int spaces) {
+ tabSizeProperty().set(spaces);
+ }
+
+
/***************************************************************************
* *
* Stylesheet Handling *
* *
**************************************************************************/
/*
* Super-lazy instantiation pattern from Bill Pugh.
*/
- private static class StyleableProperties {
+ private static class StyleableProperties {
- private static final CssMetaData FONT =
+ private static final CssMetaData FONT =
new FontCssMetaData("-fx-font", Font.getDefault()) {
@Override
public boolean isSettable(Text node) {
return node.font == null || !node.font.isBound();
@@ -1288,15 +1326,15 @@
@Override
public StyleableProperty getStyleableProperty(Text node) {
return (StyleableProperty)node.fontProperty();
}
- };
+ };
- private static final CssMetaData UNDERLINE =
+ private static final CssMetaData UNDERLINE =
new CssMetaData("-fx-underline",
- BooleanConverter.getInstance(), Boolean.FALSE) {
+ BooleanConverter.getInstance(), Boolean.FALSE) {
@Override
public boolean isSettable(Text node) {
return node.attributes == null ||
node.attributes.underline == null ||
@@ -1305,15 +1343,15 @@
@Override
public StyleableProperty getStyleableProperty(Text node) {
return (StyleableProperty)node.underlineProperty();
}
- };
+ };
- private static final CssMetaData STRIKETHROUGH =
+ private static final CssMetaData STRIKETHROUGH =
new CssMetaData("-fx-strikethrough",
- BooleanConverter.getInstance(), Boolean.FALSE) {
+ BooleanConverter.getInstance(), Boolean.FALSE) {
@Override
public boolean isSettable(Text node) {
return node.attributes == null ||
node.attributes.strikethrough == null ||
@@ -1322,17 +1360,17 @@
@Override
public StyleableProperty getStyleableProperty(Text node) {
return (StyleableProperty)node.strikethroughProperty();
}
- };
+ };
- private static final
- CssMetaData TEXT_ALIGNMENT =
- new CssMetaData("-fx-text-alignment",
- new EnumConverter(TextAlignment.class),
- TextAlignment.LEFT) {
+ private static final
+ CssMetaData TEXT_ALIGNMENT =
+ new CssMetaData("-fx-text-alignment",
+ new EnumConverter(TextAlignment.class),
+ TextAlignment.LEFT) {
@Override
public boolean isSettable(Text node) {
return node.attributes == null ||
node.attributes.textAlignment == null ||
@@ -1341,16 +1379,16 @@
@Override
public StyleableProperty getStyleableProperty(Text node) {
return (StyleableProperty)node.textAlignmentProperty();
}
- };
+ };
- private static final CssMetaData TEXT_ORIGIN =
- new CssMetaData("-fx-text-origin",
- new EnumConverter(VPos.class),
- VPos.BASELINE) {
+ private static final CssMetaData TEXT_ORIGIN =
+ new CssMetaData("-fx-text-origin",
+ new EnumConverter(VPos.class),
+ VPos.BASELINE) {
@Override
public boolean isSettable(Text node) {
return node.attributes == null ||
node.attributes.textOrigin == null ||
@@ -1359,18 +1397,18 @@
@Override
public StyleableProperty getStyleableProperty(Text node) {
return (StyleableProperty)node.textOriginProperty();
}
- };
+ };
- private static final CssMetaData
- FONT_SMOOTHING_TYPE =
- new CssMetaData(
- "-fx-font-smoothing-type",
- new EnumConverter(FontSmoothingType.class),
- FontSmoothingType.GRAY) {
+ private static final CssMetaData
+ FONT_SMOOTHING_TYPE =
+ new CssMetaData(
+ "-fx-font-smoothing-type",
+ new EnumConverter(FontSmoothingType.class),
+ FontSmoothingType.GRAY) {
@Override
public boolean isSettable(Text node) {
return node.fontSmoothingType == null ||
!node.fontSmoothingType.isBound();
@@ -1380,16 +1418,16 @@
public StyleableProperty
getStyleableProperty(Text node) {
return (StyleableProperty)node.fontSmoothingTypeProperty();
}
- };
+ };
- private static final
- CssMetaData LINE_SPACING =
- new CssMetaData("-fx-line-spacing",
- SizeConverter.getInstance(), 0) {
+ private static final
+ CssMetaData LINE_SPACING =
+ new CssMetaData("-fx-line-spacing",
+ SizeConverter.getInstance(), 0) {
@Override
public boolean isSettable(Text node) {
return node.attributes == null ||
node.attributes.lineSpacing == null ||
@@ -1398,44 +1436,62 @@
@Override
public StyleableProperty getStyleableProperty(Text node) {
return (StyleableProperty)node.lineSpacingProperty();
}
- };
+ };
- private static final CssMetaData
- BOUNDS_TYPE =
- new CssMetaData(
- "-fx-bounds-type",
- new EnumConverter(TextBoundsType.class),
- DEFAULT_BOUNDS_TYPE) {
+ private static final CssMetaData
+ BOUNDS_TYPE =
+ new CssMetaData(
+ "-fx-bounds-type",
+ new EnumConverter(TextBoundsType.class),
+ DEFAULT_BOUNDS_TYPE) {
@Override
public boolean isSettable(Text node) {
return node.boundsType == null || !node.boundsType.isBound();
}
@Override
public StyleableProperty getStyleableProperty(Text node) {
return (StyleableProperty)node.boundsTypeProperty();
}
- };
+ };
+
+ private static final CssMetaData TAB_SIZE =
+ new CssMetaData("-fx-tab-size",
+ SizeConverter.getInstance(), TextLayout.DEFAULT_TAB_SIZE) {
+
+ @Override
+ public boolean isSettable(Text node) {
+ return node.attributes == null ||
+ node.attributes.tabSize == null ||
+ !node.attributes.tabSize.isBound();
+ }
- private final static List> STYLEABLES;
- static {
+ @Override
+ public StyleableProperty getStyleableProperty(Text node) {
+ return (StyleableProperty)node.tabSizeProperty();
+ }
+ };
+
+ private final static List> STYLEABLES;
+ static {
final List> styleables =
new ArrayList>(Shape.getClassCssMetaData());
styleables.add(FONT);
styleables.add(UNDERLINE);
styleables.add(STRIKETHROUGH);
styleables.add(TEXT_ALIGNMENT);
styleables.add(TEXT_ORIGIN);
styleables.add(FONT_SMOOTHING_TYPE);
styleables.add(LINE_SPACING);
styleables.add(BOUNDS_TYPE);
+ styleables.add(TAB_SIZE);
STYLEABLES = Collections.unmodifiableList(styleables);
- }
+ }
}
/**
* @return The CssMetaData associated with this class, which may include the
* CssMetaData of its superclasses.
@@ -1819,10 +1875,40 @@
caretBias =
new SimpleBooleanProperty(Text.this, "caretBias", DEFAULT_CARET_BIAS);
}
return caretBias;
}
+
+ private IntegerProperty tabSize;
+
+ final int getTabSize() {
+ return tabSize == null ? TextLayout.DEFAULT_TAB_SIZE : tabSize.get();
+ }
+
+ final IntegerProperty tabSizeProperty() {
+ if (tabSize == null) {
+ tabSize = new StyleableIntegerProperty(TextLayout.DEFAULT_TAB_SIZE) {
+ @Override public Object getBean() { return Text.this; }
+ @Override public String getName() { return "tabSize"; }
+ @Override public CssMetaData getCssMetaData() {
+ return StyleableProperties.TAB_SIZE;
+ }
+ @Override public void set(int v) { super.set((v < 1) ? 1 : v); }
+ @Override protected void invalidated() {
+ TextLayout layout = getTextLayout();
+ if (layout.setTabSize(get())) {
+ needsTextLayout();
+ }
+ NodeHelper.markDirty(Text.this, DirtyBits.TEXT_ATTRS);
+ if (getBoundsType() == TextBoundsType.VISUAL) {
+ NodeHelper.geomChanged(Text.this);
+ }
+ }
+ };
+ }
+ return tabSize;
+ }
}
/**
* Returns a string representation of this {@code Text} object.
* @return a string representation of this {@code Text} object.
diff a/modules/javafx.graphics/src/main/java/javafx/scene/text/TextFlow.java b/modules/javafx.graphics/src/main/java/javafx/scene/text/TextFlow.java
--- a/modules/javafx.graphics/src/main/java/javafx/scene/text/TextFlow.java
+++ b/modules/javafx.graphics/src/main/java/javafx/scene/text/TextFlow.java
@@ -51,11 +51,14 @@
import com.sun.javafx.scene.text.GlyphList;
import com.sun.javafx.scene.text.TextLayout;
import com.sun.javafx.scene.text.TextLayoutFactory;
import com.sun.javafx.scene.text.TextSpan;
import com.sun.javafx.tk.Toolkit;
+import javafx.beans.property.IntegerProperty;
+import javafx.beans.property.IntegerPropertyBase;
import javafx.css.Styleable;
+import javafx.css.StyleableIntegerProperty;
import javafx.css.StyleableProperty;
/**
* TextFlow is special layout designed to lay out rich text.
* It can be used to layout several {@link Text} nodes in a single text flow.
@@ -381,10 +384,11 @@
TextLayout getTextLayout() {
if (layout == null) {
TextLayoutFactory factory = Toolkit.getToolkit().getTextLayoutFactory();
layout = factory.createLayout();
+ layout.setTabSize(getTabSize());
needsContent = true;
}
if (needsContent) {
List children = getManagedChildren();
TextSpan[] spans = new TextSpan[children.size()];
@@ -481,10 +485,59 @@
}
};
}
return lineSpacing;
}
+ /**
+ * The size of a tab stop in spaces.
+ *
+ * @return the {@code tabSize} property
+ *
+ * @defaultValue {@code 8}
+ *
+ * @since 14
+ */
+ private IntegerProperty tabSize;
+
+ /**
+ * Gets the size of a tab stop in spaces.
+ * @return the size of a tab in spaces
+ * @since 14
+ */
+ public final int getTabSize() {
+ return tabSize == null ? TextLayout.DEFAULT_TAB_SIZE : tabSize.get();
+ }
+
+ /**
+ * Sets the size of a tab stop.
+ * @param spaces the size of a tab in spaces. Defaults to 8.
+ * Minimum is 1, lower values will be clamped to 1.
+ * @since 14
+ */
+ public final void setTabSize(int spaces) {
+ tabSizeProperty().set(spaces);
+ }
+
+ final IntegerProperty tabSizeProperty() {
+ if (tabSize == null) {
+ tabSize = new StyleableIntegerProperty(TextLayout.DEFAULT_TAB_SIZE) {
+ @Override public Object getBean() { return TextFlow.this; }
+ @Override public String getName() { return "tabSize"; }
+ @Override public CssMetaData getCssMetaData() {
+ return StyleableProperties.TAB_SIZE;
+ }
+ @Override public void set(int v) { super.set((v < 1) ? 1 : v); }
+ @Override protected void invalidated() {
+ TextLayout layout = getTextLayout();
+ if (layout.setTabSize(get())) {
+ requestLayout();
+ }
+ }
+ };
+ }
+ return tabSize;
+ }
@Override public final double getBaselineOffset() {
Insets insets = getInsets();
double top = snapSpaceY(insets.getTop());
return top - getTextLayout().getBounds().getMinY();
@@ -497,49 +550,65 @@
**************************************************************************/
/*
* Super-lazy instantiation pattern from Bill Pugh.
*/
- private static class StyleableProperties {
+ private static class StyleableProperties {
- private static final
- CssMetaData TEXT_ALIGNMENT =
- new CssMetaData("-fx-text-alignment",
- new EnumConverter(TextAlignment.class),
- TextAlignment.LEFT) {
+ private static final
+ CssMetaData TEXT_ALIGNMENT =
+ new CssMetaData("-fx-text-alignment",
+ new EnumConverter(TextAlignment.class),
+ TextAlignment.LEFT) {
@Override public boolean isSettable(TextFlow node) {
return node.textAlignment == null || !node.textAlignment.isBound();
}
@Override public StyleableProperty getStyleableProperty(TextFlow node) {
return (StyleableProperty)node.textAlignmentProperty();
}
- };
+ };
- private static final
- CssMetaData LINE_SPACING =
- new CssMetaData("-fx-line-spacing",
- SizeConverter.getInstance(), 0) {
+ private static final
+ CssMetaData LINE_SPACING =
+ new CssMetaData("-fx-line-spacing",
+ SizeConverter.getInstance(), 0) {
@Override public boolean isSettable(TextFlow node) {
return node.lineSpacing == null || !node.lineSpacing.isBound();
}
@Override public StyleableProperty getStyleableProperty(TextFlow node) {
return (StyleableProperty)node.lineSpacingProperty();
}
- };
+ };
+
+ private static final CssMetaData TAB_SIZE =
+ new CssMetaData("-fx-tab-size",
+ SizeConverter.getInstance(), TextLayout.DEFAULT_TAB_SIZE) {
+
+ @Override
+ public boolean isSettable(TextFlow node) {
+ return node.tabSize == null || !node.tabSize.isBound();
+ }
- private static final List> STYLEABLES;
- static {
+ @Override
+ public StyleableProperty getStyleableProperty(TextFlow node) {
+ return (StyleableProperty)node.tabSizeProperty();
+ }
+ };
+
+ private static final List> STYLEABLES;
+ static {
final List> styleables =
new ArrayList>(Pane.getClassCssMetaData());
styleables.add(TEXT_ALIGNMENT);
styleables.add(LINE_SPACING);
+ styleables.add(TAB_SIZE);
STYLEABLES = Collections.unmodifiableList(styleables);
- }
+ }
}
/**
* @return The CssMetaData associated with this class, which may include the
* CssMetaData of its superclasses.
diff a/modules/javafx.graphics/src/test/java/test/com/sun/javafx/pgstub/StubTextLayout.java b/modules/javafx.graphics/src/test/java/test/com/sun/javafx/pgstub/StubTextLayout.java
--- a/modules/javafx.graphics/src/test/java/test/com/sun/javafx/pgstub/StubTextLayout.java
+++ b/modules/javafx.graphics/src/test/java/test/com/sun/javafx/pgstub/StubTextLayout.java
@@ -1,7 +1,7 @@
/*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, 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
@@ -40,10 +40,12 @@
return true;
}
private String text;
private Font font;
+ private int tabSize = DEFAULT_TAB_SIZE;
+
@Override
public boolean setContent(String text, Object font) {
this.text = text;
final StubFontLoader.StubFont stub = ((StubFontLoader.StubFont)font);
this.font = stub == null ? null : stub.font;
@@ -85,11 +87,30 @@
final double fontSize = (font == null ? 0 : ((Font)font).getSize());
final String[] lines = text.split("\n");
double width = 0.0;
double height = fontSize * lines.length;
for (String line : lines) {
- width = Math.max(width, fontSize * line.length());
+ int tabs = 0;
+ final int length;
+ if (line.contains("\t")) {
+ // count chars but when encountering a tab round up to a tabSize boundary
+ char [] chrs = line.toCharArray();
+ int spaces = 0;
+ for (int i = 0; i < chrs.length; i++) {
+ if (chrs[i] == '\t') {
+ if (tabSize != 0) {
+ while ((++spaces % tabSize) != 0) {}
+ }
+ } else {
+ spaces++;
+ }
+ }
+ length = spaces;
+ } else {
+ length = line.length();
+ }
+ width = Math.max(width, fontSize * length);
}
return bounds.deriveWithNewBounds(0, (float)-fontSize, 0,
(float)width, (float)(height-fontSize), 0);
}
@@ -171,6 +192,17 @@
@Override
public BaseBounds getVisualBounds(int type) {
return new RectBounds();
}
+ @Override
+ public boolean setTabSize(int spaces) {
+ if (spaces < 1)
+ spaces = 1;
+ if (tabSize != spaces) {
+ tabSize = spaces;
+ return true;
+ }
+ return false;
+ }
+
}
diff a/modules/javafx.graphics/src/test/java/test/javafx/scene/text/TextTest.java b/modules/javafx.graphics/src/test/java/test/javafx/scene/text/TextTest.java
--- a/modules/javafx.graphics/src/test/java/test/javafx/scene/text/TextTest.java
+++ b/modules/javafx.graphics/src/test/java/test/javafx/scene/text/TextTest.java
@@ -1,7 +1,7 @@
/*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2019, 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
@@ -25,15 +25,22 @@
package test.javafx.scene.text;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertNotNull;
import javafx.geometry.VPos;
import test.javafx.scene.NodeTest;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
+import javafx.scene.layout.HBox;
+import javafx.scene.Scene;
+import javafx.stage.Stage;
+
+import test.com.sun.javafx.pgstub.StubToolkit;
+import com.sun.javafx.tk.Toolkit;
import org.junit.Test;
public class TextTest {
@@ -223,6 +230,43 @@
@Test public void toStringShouldReturnNonEmptyString() {
String s = new Text().toString();
assertNotNull(s);
assertFalse(s.isEmpty());
}
+
+ // Test for JDK-8130738
+ @Test public void testTabSize() {
+ Toolkit tk = (StubToolkit)Toolkit.getToolkit();
+ HBox root = new HBox();
+ Scene scene = new Scene(root);
+ Stage stage = new Stage();
+ stage.setScene(scene);
+ stage.setWidth(300);
+ stage.setHeight(200);
+
+ try {
+ Text text = new Text("\tHello");
+ root.getChildren().addAll(text);
+ stage.show();
+ tk.firePulse();
+ assertEquals(text.getTabSize(),8);
+ // initial width with default 8-space tab
+ double widthT8 = text.getBoundsInLocal().getWidth();
+ text.setTabSize(1);
+ tk.firePulse();
+ // width with tab at 1 spaces
+ double widthT1 = text.getBoundsInLocal().getWidth();
+ // approximate width of a single space
+ double widthSpace = (widthT8 - widthT1) / 7;
+ assertTrue(widthSpace > 0);
+ text.setTabSize(4);
+ tk.firePulse();
+ // width with tab at 4 spaces
+ double widthT4 = text.getBoundsInLocal().getWidth();
+ double expected = widthT8 - 4 * widthSpace;
+ // should be approximately 4 space-widths shorter
+ assertEquals(expected, widthT4, 0.5);
+ } finally {
+ stage.hide();
+ }
+ }
}
diff a/modules/javafx.graphics/src/test/java/test/javafx/scene/text/Text_cssMethods_Test.java b/modules/javafx.graphics/src/test/java/test/javafx/scene/text/Text_cssMethods_Test.java
--- a/modules/javafx.graphics/src/test/java/test/javafx/scene/text/Text_cssMethods_Test.java
+++ b/modules/javafx.graphics/src/test/java/test/javafx/scene/text/Text_cssMethods_Test.java
@@ -57,11 +57,12 @@
"-fx-text-alignment", TextAlignment.CENTER),
config(TEST_TEXT, "textOrigin", VPos.BASELINE,
"-fx-text-origin", VPos.BOTTOM),
config(TEST_TEXT, "translateX", 0.0, "-fx-translate-x", 10.0),
config(TEST_TEXT, "fontSmoothingType", FontSmoothingType.LCD,
- "-fx-font-smoothing-type", FontSmoothingType.GRAY)
+ "-fx-font-smoothing-type", FontSmoothingType.GRAY),
+ config(TEST_TEXT, "tabSize", 8, "-fx-tab-size", 4)
});
}
public Text_cssMethods_Test(final Configuration configuration) {
super(configuration);