< prev index next >

modules/javafx.graphics/src/main/java/javafx/scene/text/Text.java

Print this page
@@ -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<Text,Font> FONT =
+         private static final CssMetaData<Text,Font> FONT =
              new FontCssMetaData<Text>("-fx-font", Font.getDefault()) {
  
              @Override
              public boolean isSettable(Text node) {
                  return node.font == null || !node.font.isBound();

@@ -1288,15 +1326,15 @@
  
              @Override
              public StyleableProperty<Font> getStyleableProperty(Text node) {
                  return (StyleableProperty<Font>)node.fontProperty();
              }
-          };
+         };
  
-          private static final CssMetaData<Text,Boolean> UNDERLINE =
+         private static final CssMetaData<Text,Boolean> UNDERLINE =
              new CssMetaData<Text,Boolean>("-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<Boolean> getStyleableProperty(Text node) {
                  return (StyleableProperty<Boolean>)node.underlineProperty();
              }
-          };
+         };
  
-          private static final CssMetaData<Text,Boolean> STRIKETHROUGH =
+         private static final CssMetaData<Text,Boolean> STRIKETHROUGH =
              new CssMetaData<Text,Boolean>("-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<Boolean> getStyleableProperty(Text node) {
                  return (StyleableProperty<Boolean>)node.strikethroughProperty();
              }
-          };
+         };
  
-          private static final
-              CssMetaData<Text,TextAlignment> TEXT_ALIGNMENT =
-                  new CssMetaData<Text,TextAlignment>("-fx-text-alignment",
-                  new EnumConverter<TextAlignment>(TextAlignment.class),
-                  TextAlignment.LEFT) {
+         private static final
+             CssMetaData<Text,TextAlignment> TEXT_ALIGNMENT =
+                 new CssMetaData<Text,TextAlignment>("-fx-text-alignment",
+                 new EnumConverter<TextAlignment>(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<TextAlignment> getStyleableProperty(Text node) {
                  return (StyleableProperty<TextAlignment>)node.textAlignmentProperty();
              }
-          };
+         };
  
-          private static final CssMetaData<Text,VPos> TEXT_ORIGIN =
-                  new CssMetaData<Text,VPos>("-fx-text-origin",
-                  new EnumConverter<VPos>(VPos.class),
-                  VPos.BASELINE) {
+         private static final CssMetaData<Text,VPos> TEXT_ORIGIN =
+                 new CssMetaData<Text,VPos>("-fx-text-origin",
+                 new EnumConverter<VPos>(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<VPos> getStyleableProperty(Text node) {
                  return (StyleableProperty<VPos>)node.textOriginProperty();
              }
-          };
+         };
  
-          private static final CssMetaData<Text,FontSmoothingType>
-              FONT_SMOOTHING_TYPE =
-              new CssMetaData<Text,FontSmoothingType>(
-                  "-fx-font-smoothing-type",
-                  new EnumConverter<FontSmoothingType>(FontSmoothingType.class),
-                  FontSmoothingType.GRAY) {
+         private static final CssMetaData<Text,FontSmoothingType>
+             FONT_SMOOTHING_TYPE =
+             new CssMetaData<Text,FontSmoothingType>(
+                 "-fx-font-smoothing-type",
+                 new EnumConverter<FontSmoothingType>(FontSmoothingType.class),
+                 FontSmoothingType.GRAY) {
  
              @Override
              public boolean isSettable(Text node) {
                  return node.fontSmoothingType == null ||
                         !node.fontSmoothingType.isBound();

@@ -1380,16 +1418,16 @@
              public StyleableProperty<FontSmoothingType>
                                   getStyleableProperty(Text node) {
  
                  return (StyleableProperty<FontSmoothingType>)node.fontSmoothingTypeProperty();
              }
-          };
+         };
  
-          private static final
-              CssMetaData<Text,Number> LINE_SPACING =
-                  new CssMetaData<Text,Number>("-fx-line-spacing",
-                  SizeConverter.getInstance(), 0) {
+         private static final
+             CssMetaData<Text,Number> LINE_SPACING =
+                 new CssMetaData<Text,Number>("-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<Number> getStyleableProperty(Text node) {
                  return (StyleableProperty<Number>)node.lineSpacingProperty();
              }
-          };
+         };
  
-          private static final CssMetaData<Text, TextBoundsType>
-              BOUNDS_TYPE =
-              new CssMetaData<Text,TextBoundsType>(
-                  "-fx-bounds-type",
-                  new EnumConverter<TextBoundsType>(TextBoundsType.class),
-                  DEFAULT_BOUNDS_TYPE) {
+         private static final CssMetaData<Text, TextBoundsType>
+             BOUNDS_TYPE =
+             new CssMetaData<Text,TextBoundsType>(
+                 "-fx-bounds-type",
+                 new EnumConverter<TextBoundsType>(TextBoundsType.class),
+                 DEFAULT_BOUNDS_TYPE) {
  
              @Override
              public boolean isSettable(Text node) {
                  return node.boundsType == null || !node.boundsType.isBound();
              }
  
              @Override
              public StyleableProperty<TextBoundsType> getStyleableProperty(Text node) {
                  return (StyleableProperty<TextBoundsType>)node.boundsTypeProperty();
              }
-          };
+         };
+ 
+         private static final CssMetaData<Text,Number> TAB_SIZE =
+                 new CssMetaData<Text,Number>("-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<CssMetaData<? extends Styleable, ?>> STYLEABLES;
-          static {
+             @Override
+             public StyleableProperty<Number> getStyleableProperty(Text node) {
+                 return (StyleableProperty<Number>)node.tabSizeProperty();
+             }
+         };
+ 
+     private final static List<CssMetaData<? extends Styleable, ?>> STYLEABLES;
+         static {
              final List<CssMetaData<? extends Styleable, ?>> styleables =
                  new ArrayList<CssMetaData<? extends Styleable, ?>>(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.
< prev index next >