< 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 ***
              y = getYAdjustment(getVisualBounds()) + (float)getY();
          }
          return TransformedShape.translatedShape(shape, x, y);
      }
  
     /***************************************************************************
      *                                                                         *
      *                            Stylesheet Handling                          *
      *                                                                         *
      **************************************************************************/
  
      /*
       * Super-lazy instantiation pattern from Bill Pugh.
       */
!      private static class StyleableProperties {
  
!          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();
--- 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 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 ***
  
              @Override
              public StyleableProperty<Font> getStyleableProperty(Text node) {
                  return (StyleableProperty<Font>)node.fontProperty();
              }
!          };
  
!          private static final CssMetaData<Text,Boolean> UNDERLINE =
              new CssMetaData<Text,Boolean>("-fx-underline",
!                  BooleanConverter.getInstance(), Boolean.FALSE) {
  
              @Override
              public boolean isSettable(Text node) {
                  return node.attributes == null ||
                         node.attributes.underline == null ||
--- 1326,15 ---
  
              @Override
              public StyleableProperty<Font> getStyleableProperty(Text node) {
                  return (StyleableProperty<Font>)node.fontProperty();
              }
!         };
  
!         private static final CssMetaData<Text,Boolean> UNDERLINE =
              new CssMetaData<Text,Boolean>("-fx-underline",
!                 BooleanConverter.getInstance(), Boolean.FALSE) {
  
              @Override
              public boolean isSettable(Text node) {
                  return node.attributes == null ||
                         node.attributes.underline == null ||

*** 1305,15 ***
  
              @Override
              public StyleableProperty<Boolean> getStyleableProperty(Text node) {
                  return (StyleableProperty<Boolean>)node.underlineProperty();
              }
!          };
  
!          private static final CssMetaData<Text,Boolean> STRIKETHROUGH =
              new CssMetaData<Text,Boolean>("-fx-strikethrough",
!                  BooleanConverter.getInstance(), Boolean.FALSE) {
  
              @Override
              public boolean isSettable(Text node) {
                  return node.attributes == null ||
                         node.attributes.strikethrough == null ||
--- 1343,15 ---
  
              @Override
              public StyleableProperty<Boolean> getStyleableProperty(Text node) {
                  return (StyleableProperty<Boolean>)node.underlineProperty();
              }
!         };
  
!         private static final CssMetaData<Text,Boolean> STRIKETHROUGH =
              new CssMetaData<Text,Boolean>("-fx-strikethrough",
!                 BooleanConverter.getInstance(), Boolean.FALSE) {
  
              @Override
              public boolean isSettable(Text node) {
                  return node.attributes == null ||
                         node.attributes.strikethrough == null ||

*** 1322,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) {
  
              @Override
              public boolean isSettable(Text node) {
                  return node.attributes == null ||
                         node.attributes.textAlignment == null ||
--- 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) {
  
              @Override
              public boolean isSettable(Text node) {
                  return node.attributes == null ||
                         node.attributes.textAlignment == null ||

*** 1341,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) {
  
              @Override
              public boolean isSettable(Text node) {
                  return node.attributes == null ||
                         node.attributes.textOrigin == null ||
--- 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) {
  
              @Override
              public boolean isSettable(Text node) {
                  return node.attributes == null ||
                         node.attributes.textOrigin == null ||

*** 1359,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) {
  
              @Override
              public boolean isSettable(Text node) {
                  return node.fontSmoothingType == null ||
                         !node.fontSmoothingType.isBound();
--- 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) {
  
              @Override
              public boolean isSettable(Text node) {
                  return node.fontSmoothingType == null ||
                         !node.fontSmoothingType.isBound();

*** 1380,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) {
  
              @Override
              public boolean isSettable(Text node) {
                  return node.attributes == null ||
                         node.attributes.lineSpacing == null ||
--- 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) {
  
              @Override
              public boolean isSettable(Text node) {
                  return node.attributes == null ||
                         node.attributes.lineSpacing == null ||

*** 1398,44 ***
  
              @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) {
  
              @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 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 = Collections.unmodifiableList(styleables);
!          }
      }
  
      /**
       * @return The CssMetaData associated with this class, which may include the
       * CssMetaData of its superclasses.
--- 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) {
  
              @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();
+             }
  
!             @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 >