changeset 2397:768175f757de

RT-16288: Add a TextField.setFont method Summary: Moved the font property to TextInputControl, so that it now has a font, the same as Labeled controls. This is properly spec'd for cases where the TextInputControl is rich text, and is styleable from CSS.
author Richard Bair <richard.bair@oracle.com>
date Wed, 23 Jan 2013 14:27:39 -0800
parents 63d458f96141
children 19fcfc090bf7
files javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TextAreaSkin.java javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TextFieldSkin.java javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TextInputControlSkin.java javafx-ui-controls/src/javafx/scene/control/SkinBase.java javafx-ui-controls/src/javafx/scene/control/TextField.java javafx-ui-controls/src/javafx/scene/control/TextInputControl.java
diffstat 6 files changed, 134 insertions(+), 67 deletions(-) [+]
line wrap: on
line diff
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TextAreaSkin.java	Wed Jan 23 11:39:06 2013 -0500
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TextAreaSkin.java	Wed Jan 23 14:27:39 2013 -0800
@@ -754,7 +754,7 @@
             promptNode.setManaged(false);
             promptNode.getStyleClass().add("text");
             promptNode.visibleProperty().bind(usePromptText);
-            promptNode.fontProperty().bind(font);
+            promptNode.fontProperty().bind(getSkinnable().fontProperty());
             promptNode.textProperty().bind(getSkinnable().promptTextProperty());
             promptNode.fillProperty().bind(promptTextFill);
         }
@@ -768,7 +768,7 @@
         paragraphNode.getStyleClass().add("text");
         paragraphNodes.getChildren().add(i, paragraphNode);
 
-        paragraphNode.fontProperty().bind(font);
+        paragraphNode.fontProperty().bind(textArea.fontProperty());
         paragraphNode.fillProperty().bind(textFill);
         paragraphNode.impl_selectionFillProperty().bind(highlightTextFill);
     }
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TextFieldSkin.java	Wed Jan 23 11:39:06 2013 -0500
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TextFieldSkin.java	Wed Jan 23 14:27:39 2013 -0800
@@ -185,7 +185,7 @@
         // Add text
         textNode.setManaged(false);
         textNode.getStyleClass().add("text");
-        textNode.fontProperty().bind(font);
+        textNode.fontProperty().bind(textField.fontProperty());
 
         textNode.layoutXProperty().bind(textTranslateX);
         textNode.textProperty().bind(new StringBinding() {
@@ -243,7 +243,7 @@
 
         // Be sure to get the control to request layout when the font changes,
         // since this will affect the pref height and pref width.
-        font.addListener(new InvalidationListener() {
+        textField.fontProperty().addListener(new InvalidationListener() {
             @Override public void invalidated(Observable observable) {
                 // I do both so that any cached values for prefWidth/height are cleared.
                 // The problem is that the skin is unmanaged and so calling request layout
@@ -393,7 +393,7 @@
         promptNode.setManaged(false);
         promptNode.getStyleClass().add("text");
         promptNode.visibleProperty().bind(usePromptText);
-        promptNode.fontProperty().bind(font);
+        promptNode.fontProperty().bind(getSkinnable().fontProperty());
 
         promptNode.textProperty().bind(getSkinnable().promptTextProperty());
         promptNode.fillProperty().bind(promptTextFill);
--- a/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TextInputControlSkin.java	Wed Jan 23 11:39:06 2013 -0500
+++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/skin/TextInputControlSkin.java	Wed Jan 23 14:27:39 2013 -0800
@@ -40,6 +40,10 @@
 import javafx.beans.value.ObservableBooleanValue;
 import javafx.beans.value.ObservableObjectValue;
 import javafx.collections.ObservableList;
+import javafx.css.CssMetaData;
+import javafx.css.StyleableBooleanProperty;
+import javafx.css.StyleableObjectProperty;
+import javafx.css.StyleableProperty;
 import javafx.event.ActionEvent;
 import javafx.event.EventHandler;
 import javafx.geometry.NodeOrientation;
@@ -70,13 +74,9 @@
 import javafx.scene.shape.PathElement;
 import javafx.scene.shape.Shape;
 import javafx.scene.shape.VLineTo;
-import javafx.scene.text.Font;
 import javafx.stage.Window;
 import javafx.util.Duration;
 import com.sun.javafx.PlatformUtil;
-import javafx.css.StyleableBooleanProperty;
-import javafx.css.StyleableObjectProperty;
-import javafx.css.CssMetaData;
 import com.sun.javafx.css.converters.BooleanConverter;
 import com.sun.javafx.css.converters.PaintConverter;
 import com.sun.javafx.scene.control.behavior.TextInputControlBehavior;
@@ -85,42 +85,13 @@
 
 import static com.sun.javafx.PlatformUtil.*;
 import static com.sun.javafx.scene.control.skin.resources.ControlResources.*;
-import javafx.css.FontCssMetaData;
-import javafx.css.StyleableProperty;
 
 /**
  * Abstract base class for text input skins.
  */
 public abstract class TextInputControlSkin<T extends TextInputControl, B extends TextInputControlBehavior<T>> extends BehaviorSkinBase<T, B> {
 
-    /**
-     * The font to use with this control. In 1.3 and prior we had a font property
-     * on the TextInputControl itself, however now we just do it via CSS
-     */
-    protected final ObjectProperty<Font> font = new StyleableObjectProperty<Font>(Font.getDefault()) {
-
-        @Override
-        public Object getBean() {
-            return TextInputControlSkin.this;
-        }
-
-        @Override
-        public String getName() {
-            return "font";
-        }
-
-        @Override
-        public CssMetaData getCssMetaData() {
-            return StyleableProperties.FONT;
-        }
-    };
-    protected final ObservableObjectValue<FontMetrics> fontMetrics = new ObjectBinding<FontMetrics>() {
-        { bind(font); }
-        @Override protected FontMetrics computeValue() {
-            invalidateMetrics();
-            return Toolkit.getToolkit().getFontLoader().getFontMetrics(font.get());
-        }
-    };
+    protected final ObservableObjectValue<FontMetrics> fontMetrics;
 
     /**
      * The fill to use for the text under normal conditions
@@ -292,6 +263,14 @@
     public TextInputControlSkin(final T textInput, final B behavior) {
         super(textInput, behavior);
 
+        fontMetrics = new ObjectBinding<FontMetrics>() {
+            { bind(textInput.fontProperty()); }
+            @Override protected FontMetrics computeValue() {
+                invalidateMetrics();
+                return Toolkit.getToolkit().getFontLoader().getFontMetrics(textInput.getFont());
+            }
+        };
+
         caretTimeline.setCycleCount(Timeline.INDEFINITE);
         caretTimeline.getKeyFrames().addAll(
             new KeyFrame(Duration.ZERO, new EventHandler<ActionEvent>() {
@@ -685,22 +664,6 @@
     }
 
     private static class StyleableProperties {
-        private static final CssMetaData<TextInputControl,Font> FONT =
-           new FontCssMetaData<TextInputControl>("-fx-font", Font.getDefault()) {
-
-            @Override
-            public boolean isSettable(TextInputControl n) {
-                final TextInputControlSkin skin = (TextInputControlSkin) n.getSkin();
-                return skin.font == null || !skin.font.isBound();
-            }
-
-            @Override
-            public StyleableProperty<Font> getStyleableProperty(TextInputControl n) {
-                final TextInputControlSkin skin = (TextInputControlSkin) n.getSkin();
-                return (StyleableProperty)skin.font;
-            }
-        };
-        
         private static final CssMetaData<TextInputControl,Paint> TEXT_FILL =
             new CssMetaData<TextInputControl,Paint>("-fx-text-fill",
                 PaintConverter.getInstance(), Color.BLACK) {
@@ -790,7 +753,6 @@
         static {
             List<CssMetaData> styleables = new ArrayList<CssMetaData>(SkinBase.getClassCssMetaData());
             Collections.addAll(styleables,
-                FONT,
                 TEXT_FILL,
                 PROMPT_TEXT_FILL,
                 HIGHLIGHT_FILL,
--- a/javafx-ui-controls/src/javafx/scene/control/SkinBase.java	Wed Jan 23 11:39:06 2013 -0500
+++ b/javafx-ui-controls/src/javafx/scene/control/SkinBase.java	Wed Jan 23 14:27:39 2013 -0800
@@ -420,7 +420,7 @@
     
     /** @see Node#pseudoClassStateChanged */
     public final void pseudoClassStateChanged(PseudoClass pseudoClass, boolean active) {
-        Control ctl = (Control)getSkinnable();
+        Control ctl = getSkinnable();
         if (ctl != null) {
             ctl.pseudoClassStateChanged(pseudoClass, active);
         }
--- a/javafx-ui-controls/src/javafx/scene/control/TextField.java	Wed Jan 23 11:39:06 2013 -0500
+++ b/javafx-ui-controls/src/javafx/scene/control/TextField.java	Wed Jan 23 14:27:39 2013 -0800
@@ -25,27 +25,25 @@
 
 package javafx.scene.control;
 
-import com.sun.javafx.beans.annotations.DuplicateInBuilderProperties;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-
 import javafx.beans.InvalidationListener;
 import javafx.beans.property.IntegerProperty;
 import javafx.beans.property.IntegerPropertyBase;
 import javafx.beans.property.ObjectProperty;
 import javafx.beans.property.ObjectPropertyBase;
 import javafx.beans.value.ChangeListener;
+import javafx.css.CssMetaData;
+import javafx.css.StyleableObjectProperty;
+import javafx.css.StyleableProperty;
 import javafx.event.ActionEvent;
 import javafx.event.EventHandler;
 import javafx.geometry.Pos;
-
+import com.sun.javafx.beans.annotations.DuplicateInBuilderProperties;
 import com.sun.javafx.binding.ExpressionHelper;
 import com.sun.javafx.css.converters.EnumConverter;
 import com.sun.javafx.scene.control.skin.TextFieldSkin;
-import javafx.css.CssMetaData;
-import javafx.css.StyleableObjectProperty;
-import javafx.css.StyleableProperty;
 
 
 /**
@@ -279,7 +277,7 @@
         private static final List<CssMetaData> STYLEABLES;
         static {
             final List<CssMetaData> styleables =
-                new ArrayList<CssMetaData>(Control.getClassCssMetaData());
+                new ArrayList<CssMetaData>(TextInputControl.getClassCssMetaData());
             Collections.addAll(styleables,
                 ALIGNMENT
             );
--- a/javafx-ui-controls/src/javafx/scene/control/TextInputControl.java	Wed Jan 23 11:39:06 2013 -0500
+++ b/javafx-ui-controls/src/javafx/scene/control/TextInputControl.java	Wed Jan 23 14:27:39 2013 -0800
@@ -26,13 +26,16 @@
 package javafx.scene.control;
 
 import java.text.BreakIterator;
-import java.util.Set;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 import javafx.beans.DefaultProperty;
 import javafx.beans.InvalidationListener;
 import javafx.beans.Observable;
 import javafx.beans.binding.IntegerBinding;
 import javafx.beans.binding.StringBinding;
 import javafx.beans.property.BooleanProperty;
+import javafx.beans.property.ObjectProperty;
 import javafx.beans.property.ReadOnlyIntegerProperty;
 import javafx.beans.property.ReadOnlyIntegerWrapper;
 import javafx.beans.property.ReadOnlyObjectProperty;
@@ -45,11 +48,17 @@
 import javafx.beans.value.ChangeListener;
 import javafx.beans.value.ObservableStringValue;
 import javafx.beans.value.ObservableValue;
+import javafx.css.CssMetaData;
+import javafx.css.FontCssMetaData;
+import javafx.css.PseudoClass;
+import javafx.css.StyleOrigin;
+import javafx.css.StyleableObjectProperty;
+import javafx.css.StyleableProperty;
 import javafx.scene.input.Clipboard;
 import javafx.scene.input.ClipboardContent;
+import javafx.scene.text.Font;
 import com.sun.javafx.Utils;
 import com.sun.javafx.binding.ExpressionHelper;
-import javafx.css.PseudoClass;
 
 /**
  * Abstract base class for text input controls.
@@ -154,6 +163,59 @@
      **************************************************************************/
 
     /**
+     * The default font to use for text in the TextInputControl. If the TextInputControl's text is
+     * rich text then this font may or may not be used depending on the font
+     * information embedded in the rich text, but in any case where a default
+     * font is required, this font will be used.
+     */
+    public final ObjectProperty<Font> fontProperty() {
+        if (font == null) {
+            font = new StyleableObjectProperty<Font>(Font.getDefault()) {
+
+                @Override
+                public void set(Font value) {
+                    final Font oldValue = get();
+                    if (value == null ? oldValue == null : value.equals(oldValue)) {
+                        return;
+                    }
+                    super.set(value);
+                }
+
+                @Override
+                protected void invalidated() {
+                    // RT-20727 - if font is changed by calling setFont, then
+                    // css might need to be reapplied since font size affects
+                    // calculated values for styles with relative values
+                    StyleOrigin origin = ((StyleableProperty)font).getStyleOrigin();
+                    if (origin == null || origin == StyleOrigin.USER) {
+                        TextInputControl.this.impl_reapplyCSS();
+                    }
+                }
+
+                @Override
+                public CssMetaData getCssMetaData() {
+                    return StyleableProperties.FONT;
+                }
+
+                @Override
+                public Object getBean() {
+                    return TextInputControl.this;
+                }
+
+                @Override
+                public String getName() {
+                    return "font";
+                }
+            };
+        }
+        return font;
+    }
+
+    private ObjectProperty<Font> font;
+    public final void setFont(Font value) { fontProperty().setValue(value); }
+    public final Font getFont() { return font == null ? Font.getDefault() : font.getValue(); }
+
+    /**
      * The prompt text to display in the {@code TextInputControl}, or
      * <tt>null</tt> if no prompt text is displayed.
      * @since 2.2
@@ -1036,7 +1098,6 @@
     }
 
 
-
     /***************************************************************************
      *                                                                         *
      * Stylesheet Handling                                                     *
@@ -1047,4 +1108,50 @@
     private static final PseudoClass PSEUDO_CLASS_READONLY
             = PseudoClass.getPseudoClass("readonly");
 
+    /**
+     * @treatAsPrivate implementation detail
+     */
+    private static class StyleableProperties {
+        private static final FontCssMetaData<TextInputControl> FONT =
+            new FontCssMetaData<TextInputControl>("-fx-font", Font.getDefault()) {
+
+            @Override
+            public boolean isSettable(TextInputControl n) {
+                return n.font == null || !n.font.isBound();
+            }
+
+            @Override
+            public StyleableProperty<Font> getStyleableProperty(TextInputControl n) {
+                return (StyleableProperty)n.fontProperty();
+            }
+        };
+
+        private static final List<CssMetaData> STYLEABLES;
+        static {
+            final List<CssMetaData> styleables =
+                new ArrayList<CssMetaData>(Control.getClassCssMetaData());
+            Collections.addAll(
+                    styleables,
+                    FONT
+            );
+            STYLEABLES = Collections.unmodifiableList(styleables);
+        }
+    }
+
+    /**
+     * @return The CssMetaData associated with this class, which may include the
+     * CssMetaData of its super classes.
+     */
+    public static List<CssMetaData> getClassCssMetaData() {
+        return StyleableProperties.STYLEABLES;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public List<CssMetaData> getControlCssMetaData() {
+        return getClassCssMetaData();
+    }
+
 }