modules/controls/src/main/java/javafx/scene/control/skin/ColorPickerSkin.java

Print this page
rev 9240 : 8076423: JEP 253: Prepare JavaFX UI Controls & CSS APIs for Modularization

@@ -21,36 +21,39 @@
  * 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 com.sun.javafx.scene.control.skin;
+package javafx.scene.control.skin;
 
 import com.sun.javafx.css.StyleManager;
 
+import com.sun.javafx.scene.control.Properties;
+import com.sun.javafx.scene.control.behavior.ComboBoxBaseBehavior;
+import com.sun.javafx.scene.control.skin.Utils;
 import javafx.beans.property.StringProperty;
 import javafx.css.StyleOrigin;
 import javafx.css.StyleableBooleanProperty;
 import javafx.css.CssMetaData;
 
-import com.sun.javafx.css.converters.BooleanConverter;
+import javafx.css.converter.BooleanConverter;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-import java.util.Locale;
 
 import javafx.css.StyleableDoubleProperty;
 import javafx.css.StyleableStringProperty;
 import javafx.geometry.Pos;
 import javafx.scene.Node;
+import javafx.scene.control.Control;
 import javafx.scene.image.ImageView;
 import javafx.scene.layout.StackPane;
 import javafx.scene.shape.Rectangle;
 
-import com.sun.javafx.css.converters.SizeConverter;
-import com.sun.javafx.css.converters.StringConverter;
+import javafx.css.converter.SizeConverter;
+import javafx.css.converter.StringConverter;
 import com.sun.javafx.scene.control.behavior.ColorPickerBehavior;
 
 import java.util.HashMap;
 import java.util.Map;
 

@@ -58,27 +61,87 @@
 import javafx.scene.control.TextField;
 import javafx.beans.property.BooleanProperty;
 import javafx.beans.value.WritableValue;
 import javafx.css.Styleable;
 import javafx.css.StyleableProperty;
-import javafx.event.ActionEvent;
 import javafx.scene.control.Label;
 import javafx.scene.paint.Color;
 
-import com.sun.javafx.scene.control.skin.resources.ControlResources;
-
 import static javafx.scene.paint.Color.*;
 
 /**
+ * Default skin implementation for the {@link ColorPicker} control.
  *
+ * @see ColorPicker
+ * @since 9
  */
 public class ColorPickerSkin extends ComboBoxPopupControl<Color> {
 
+    /***************************************************************************
+     *                                                                         *
+     * Private fields                                                          *
+     *                                                                         *
+     **************************************************************************/
+
     private Label displayNode; 
     private StackPane pickerColorBox;
     private Rectangle colorRect; 
     private ColorPalette popupContent;
+
+    private final ColorPickerBehavior behavior;
+
+
+
+    /***************************************************************************
+     *                                                                         *
+     * Constructors                                                            *
+     *                                                                         *
+     **************************************************************************/
+
+    /**
+     * Creates a new ColorPickerSkin instance, installing the necessary child
+     * nodes into the Control {@link Control#getChildren() children} list, as
+     * well as the necessary input mappings for handling key, mouse, etc events.
+     *
+     * @param control The control that this skin should be installed onto.
+     */
+    public ColorPickerSkin(final ColorPicker control) {
+        super(control);
+
+        // install default input map for the control
+        this.behavior = new ColorPickerBehavior(control);
+//        control.setInputMap(behavior.getInputMap());
+
+        updateComboBoxMode();
+        registerChangeListener(control.valueProperty(), e -> updateColor());
+
+        // create displayNode
+        displayNode = new Label();
+        displayNode.getStyleClass().add("color-picker-label");
+        displayNode.setManaged(false);
+
+        // label graphic
+        pickerColorBox = new PickerColorBox();
+        pickerColorBox.getStyleClass().add("picker-color");
+        colorRect = new Rectangle(12, 12);
+        colorRect.getStyleClass().add("picker-color-rect");
+
+        updateColor();
+
+        pickerColorBox.getChildren().add(colorRect);
+        displayNode.setGraphic(pickerColorBox);
+    }
+
+
+
+    /***************************************************************************
+     *                                                                         *
+     * Properties                                                              *
+     *                                                                         *
+     **************************************************************************/
+
+    // --- color label visible
     BooleanProperty colorLabelVisible = new StyleableBooleanProperty(true) {
         @Override public void invalidated() {
             if (displayNode != null) {
                 if (colorLabelVisible.get()) {
                     displayNode.setText(colorDisplayName(((ColorPicker)getSkinnable()).getValue()));

@@ -95,11 +158,13 @@
         }
         @Override public CssMetaData<ColorPicker,Boolean> getCssMetaData() {
             return StyleableProperties.COLOR_LABEL_VISIBLE;
         }
     };
-    public StringProperty imageUrlProperty() { return imageUrl; }
+
+    // --- image url
+    private final StringProperty imageUrlProperty() { return imageUrl; }
     private final StyleableStringProperty imageUrl = new StyleableStringProperty() {
         @Override public void applyStyle(StyleOrigin origin, String v) {
             super.applyStyle(origin, v);
             if (v == null) {
                 // remove old image view

@@ -121,10 +186,12 @@
         }
         @Override public CssMetaData<ColorPicker,String> getCssMetaData() {
             return StyleableProperties.GRAPHIC;
         }
     };
+
+    // --- color rect width
     private final StyleableDoubleProperty colorRectWidth =  new StyleableDoubleProperty(12) {
         @Override protected void invalidated() {
             if(pickerColorBox!=null) pickerColorBox.requestLayout();
         }
         @Override public CssMetaData<ColorPicker,Number> getCssMetaData() {

@@ -135,10 +202,12 @@
         }
         @Override public String getName() {
             return "colorRectWidth";
         }
     };
+
+    // --- color rect height
     private final StyleableDoubleProperty colorRectHeight =  new StyleableDoubleProperty(12) {
         @Override protected void invalidated() {
             if(pickerColorBox!=null) pickerColorBox.requestLayout();
         }
         @Override public CssMetaData<ColorPicker,Number> getCssMetaData() {

@@ -149,10 +218,12 @@
         }
         @Override public String getName() {
             return "colorRectHeight";
         }
     };
+
+    // --- color rect X
     private final StyleableDoubleProperty colorRectX =  new StyleableDoubleProperty(0) {
         @Override protected void invalidated() {
             if(pickerColorBox!=null) pickerColorBox.requestLayout();
         }
         @Override public CssMetaData<ColorPicker,Number> getCssMetaData() {

@@ -163,10 +234,12 @@
         }
         @Override public String getName() {
             return "colorRectX";
         }
     };
+
+    // --- color rect Y
     private final StyleableDoubleProperty colorRectY =  new StyleableDoubleProperty(0) {
         @Override protected void invalidated() {
             if(pickerColorBox!=null) pickerColorBox.requestLayout();
         }
         @Override public CssMetaData<ColorPicker,Number> getCssMetaData() {

@@ -178,86 +251,128 @@
         @Override public String getName() {
             return "colorRectY";
         }
     };
 
-    public ColorPickerSkin(final ColorPicker colorPicker) {
-        super(colorPicker, new ColorPickerBehavior(colorPicker));
-        updateComboBoxMode();
-        registerChangeListener(colorPicker.valueProperty(), "VALUE");
 
-        // create displayNode
-        displayNode = new Label();
-        displayNode.getStyleClass().add("color-picker-label");
-        displayNode.setManaged(false);
 
-        // label graphic
-        pickerColorBox = new PickerColorBox();
-        pickerColorBox.getStyleClass().add("picker-color");
-        colorRect = new Rectangle(12, 12);
-        colorRect.getStyleClass().add("picker-color-rect");
+    /***************************************************************************
+     *                                                                         *
+     * Public API                                                              *
+     *                                                                         *
+     **************************************************************************/
 
-        updateColor();
+    /** {@inheritDoc} */
+    @Override public void dispose() {
+        super.dispose();
 
-        pickerColorBox.getChildren().add(colorRect);
-        displayNode.setGraphic(pickerColorBox);
+        if (behavior != null) {
+            behavior.dispose();
+        }
     }
 
-
+    /** {@inheritDoc} */
     @Override protected double computePrefWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) {
         if (!colorLabelVisible.get()) {
             return super.computePrefWidth(height, topInset, rightInset, bottomInset, leftInset);
         }
         String displayNodeText = displayNode.getText();
         double width = 0;
         for (String name : colorNameMap.values()) {
             displayNode.setText(name);
             width = Math.max(width, super.computePrefWidth(height, topInset, rightInset, bottomInset, leftInset));
         }
-        displayNode.setText(formatHexString(Color.BLACK)); // #000000
+        displayNode.setText(Utils.formatHexString(Color.BLACK)); // #000000
         width = Math.max(width, super.computePrefWidth(height, topInset, rightInset, bottomInset, leftInset));
         displayNode.setText(displayNodeText);
         return width;
     }
 
+    /** {@inheritDoc} */
+    @Override protected Node getPopupContent() {
+        if (popupContent == null) {
+//            popupContent = new ColorPalette(colorPicker.getValue(), colorPicker);
+            popupContent = new ColorPalette((ColorPicker)getSkinnable());
+            popupContent.setPopupControl(getPopup());
+        }
+        return popupContent;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void show() {
+        super.show();
+        final ColorPicker colorPicker = (ColorPicker)getSkinnable();
+        popupContent.updateSelection(colorPicker.getValue());
+    }
+
+    /** {@inheritDoc} */
+    @Override public Node getDisplayNode() {
+        return displayNode;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void layoutChildren(final double x, final double y,
+                                            final double w, final double h) {
+        updateComboBoxMode();
+        super.layoutChildren(x, y, w, h);
+    }
+
+
+
+    /***************************************************************************
+     *                                                                         *
+     * Private implementation                                                  *
+     *                                                                         *
+     **************************************************************************/
+
+    /** {@inheritDoc} */
+    @Override void focusLost() {
+        // do nothing
+    }
+
+    /** {@inheritDoc} */
+    @Override ComboBoxBaseBehavior getBehavior() {
+        return behavior;
+    }
+
     private void updateComboBoxMode() {
         List<String> styleClass = getSkinnable().getStyleClass();
         if (styleClass.contains(ColorPicker.STYLE_CLASS_BUTTON)) {
             setMode(ComboBoxMode.BUTTON);
         } else if (styleClass.contains(ColorPicker.STYLE_CLASS_SPLIT_BUTTON)) {
             setMode(ComboBoxMode.SPLITBUTTON);
         }
     }
 
-    private static final Map<Color, String> colorNameMap = new HashMap<Color, String>(24);
-    private static final Map<Color, String> cssNameMap = new HashMap<Color, String>(139);
+    private static final Map<Color, String> colorNameMap = new HashMap<>(24);
+    private static final Map<Color, String> cssNameMap = new HashMap<>(139);
     static {
         // Translatable display names for the most common colors
-        colorNameMap.put(TRANSPARENT, getString("colorName.transparent"));
-        colorNameMap.put(BLACK,       getString("colorName.black"));
-        colorNameMap.put(BLUE,        getString("colorName.blue"));
-        colorNameMap.put(CYAN,        getString("colorName.cyan"));
-        colorNameMap.put(DARKBLUE,    getString("colorName.darkblue"));
-        colorNameMap.put(DARKCYAN,    getString("colorName.darkcyan"));
-        colorNameMap.put(DARKGRAY,    getString("colorName.darkgray"));
-        colorNameMap.put(DARKGREEN,   getString("colorName.darkgreen"));
-        colorNameMap.put(DARKMAGENTA, getString("colorName.darkmagenta"));
-        colorNameMap.put(DARKRED,     getString("colorName.darkred"));
-        colorNameMap.put(GRAY,        getString("colorName.gray"));
-        colorNameMap.put(GREEN,       getString("colorName.green"));
-        colorNameMap.put(LIGHTBLUE,   getString("colorName.lightblue"));
-        colorNameMap.put(LIGHTCYAN,   getString("colorName.lightcyan"));
-        colorNameMap.put(LIGHTGRAY,   getString("colorName.lightgray"));
-        colorNameMap.put(LIGHTGREEN,  getString("colorName.lightgreen"));
-        colorNameMap.put(LIGHTYELLOW, getString("colorName.lightyellow"));
-        colorNameMap.put(MAGENTA,     getString("colorName.magenta"));
-        colorNameMap.put(MEDIUMBLUE,  getString("colorName.mediumblue"));
-        colorNameMap.put(ORANGE,      getString("colorName.orange"));
-        colorNameMap.put(PINK,        getString("colorName.pink"));
-        colorNameMap.put(RED,         getString("colorName.red"));
-        colorNameMap.put(WHITE,       getString("colorName.white"));
-        colorNameMap.put(YELLOW,      getString("colorName.yellow"));
+        colorNameMap.put(TRANSPARENT, Properties.getColorPickerString("colorName.transparent"));
+        colorNameMap.put(BLACK,       Properties.getColorPickerString("colorName.black"));
+        colorNameMap.put(BLUE,        Properties.getColorPickerString("colorName.blue"));
+        colorNameMap.put(CYAN,        Properties.getColorPickerString("colorName.cyan"));
+        colorNameMap.put(DARKBLUE,    Properties.getColorPickerString("colorName.darkblue"));
+        colorNameMap.put(DARKCYAN,    Properties.getColorPickerString("colorName.darkcyan"));
+        colorNameMap.put(DARKGRAY,    Properties.getColorPickerString("colorName.darkgray"));
+        colorNameMap.put(DARKGREEN,   Properties.getColorPickerString("colorName.darkgreen"));
+        colorNameMap.put(DARKMAGENTA, Properties.getColorPickerString("colorName.darkmagenta"));
+        colorNameMap.put(DARKRED,     Properties.getColorPickerString("colorName.darkred"));
+        colorNameMap.put(GRAY,        Properties.getColorPickerString("colorName.gray"));
+        colorNameMap.put(GREEN,       Properties.getColorPickerString("colorName.green"));
+        colorNameMap.put(LIGHTBLUE,   Properties.getColorPickerString("colorName.lightblue"));
+        colorNameMap.put(LIGHTCYAN,   Properties.getColorPickerString("colorName.lightcyan"));
+        colorNameMap.put(LIGHTGRAY,   Properties.getColorPickerString("colorName.lightgray"));
+        colorNameMap.put(LIGHTGREEN,  Properties.getColorPickerString("colorName.lightgreen"));
+        colorNameMap.put(LIGHTYELLOW, Properties.getColorPickerString("colorName.lightyellow"));
+        colorNameMap.put(MAGENTA,     Properties.getColorPickerString("colorName.magenta"));
+        colorNameMap.put(MEDIUMBLUE,  Properties.getColorPickerString("colorName.mediumblue"));
+        colorNameMap.put(ORANGE,      Properties.getColorPickerString("colorName.orange"));
+        colorNameMap.put(PINK,        Properties.getColorPickerString("colorName.pink"));
+        colorNameMap.put(RED,         Properties.getColorPickerString("colorName.red"));
+        colorNameMap.put(WHITE,       Properties.getColorPickerString("colorName.white"));
+        colorNameMap.put(YELLOW,      Properties.getColorPickerString("colorName.yellow"));
 
         // CSS names.
         // Note that synonyms (such as "grey") have been removed here,
         // since a color can be presented with only one name in this
         // skin. If a reverse map is created for parsing names in the

@@ -406,11 +521,11 @@
 
     static String colorDisplayName(Color c) {
         if (c != null) {
             String displayName = colorNameMap.get(c);
             if (displayName == null) {
-                displayName = formatHexString(c);
+                displayName = Utils.formatHexString(c);
             }
             return displayName;
         } else {
             return null;
         }

@@ -422,11 +537,11 @@
             String displayName = colorNameMap.get(c);
             if (displayName != null) {
                 tooltipStr += displayName + " ";
             }
 
-            tooltipStr += formatHexString(c);
+            tooltipStr += Utils.formatHexString(c);
 
             String cssName = cssNameMap.get(c);
             if (cssName != null) {
                 tooltipStr += " (css: " + cssName + ")";
             }

@@ -434,87 +549,21 @@
         } else {
             return null;
         }
     }
 
-    static String formatHexString(Color c) {
-        if (c != null) {
-            return String.format((Locale) null, "#%02x%02x%02x",
-                                 Math.round(c.getRed() * 255),
-                                 Math.round(c.getGreen() * 255),
-                                 Math.round(c.getBlue() * 255));
-        } else {
-            return null;
-        }
-    }
-
-    @Override protected Node getPopupContent() {
-        if (popupContent == null) {
-//            popupContent = new ColorPalette(colorPicker.getValue(), colorPicker);
-            popupContent = new ColorPalette((ColorPicker)getSkinnable());
-            popupContent.setPopupControl(getPopup());
-        }
-       return popupContent;
-    }
-    
-    @Override protected void focusLost() {
-        // do nothing
-    }
-    
-    @Override public void show() {
-        super.show();
-        final ColorPicker colorPicker = (ColorPicker)getSkinnable();
-        popupContent.updateSelection(colorPicker.getValue());
-    }
-    
-    @Override protected void handleControlPropertyChanged(String p) {
-        super.handleControlPropertyChanged(p);
-    
-        if ("SHOWING".equals(p)) {
-            if (getSkinnable().isShowing()) {
-                show();
-            } else {
-                if (!popupContent.isCustomColorDialogShowing()) hide();
-            }
-        } else if ("VALUE".equals(p)) {
-            updateColor();
-           // Change the current selected color in the grid if ColorPicker value changes
-            if (popupContent != null) {
-//                popupContent.updateSelection(getSkinnable().getValue());
-            }
-        }
-    }
-    @Override public Node getDisplayNode() {
-        return displayNode;
-    }
-    
     private void updateColor() {
         final ColorPicker colorPicker = (ColorPicker)getSkinnable();
         colorRect.setFill(colorPicker.getValue());
         if (colorLabelVisible.get()) {
             displayNode.setText(colorDisplayName(colorPicker.getValue()));
         } else {
             displayNode.setText("");
         }
     }
-    public void syncWithAutoUpdate() {
-        if (!getPopup().isShowing() && getSkinnable().isShowing()) {
-            // Popup was dismissed. Maybe user clicked outside or typed ESCAPE.
-            // Make sure ColorPicker button is in sync.
-            getSkinnable().hide();
-        }
-    }
     
-    @Override protected void layoutChildren(final double x, final double y,
-            final double w, final double h) {
-        updateComboBoxMode();
-        super.layoutChildren(x,y,w,h);
-    }
 
-    static String getString(String key) {
-        return ControlResources.getString("ColorPicker."+key);
-    }
 
     /***************************************************************************
     *                                                                         *
     *                         picker-color-cell                               *
     *                                                                         *

@@ -642,11 +691,11 @@
             STYLEABLES = Collections.unmodifiableList(styleables);
         }
     }
      
     /**
-     * @return The CssMetaData associated with this class, which may include the
+     * Returns the CssMetaData associated with this class, which may include the
      * CssMetaData of its super classes.
      */
     public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() {
         return StyleableProperties.STYLEABLES;
     }

@@ -657,16 +706,18 @@
     @Override
     public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() {
         return getClassCssMetaData();
     }
 
+    /** {@inheritDoc} */
     @Override protected javafx.util.StringConverter<Color> getConverter() {
         return null;
     }
 
     /**
-     * ColorPicker does not use a main text field.
+     * ColorPicker does not use a main text field, so this method has been
+     * overridden to return null.
      */
     @Override protected TextField getEditor() {
         return null;
     }
 }