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


   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.javafx.scene.control.skin;
  27 
  28 import com.sun.javafx.css.StyleManager;
  29 



  30 import javafx.beans.property.StringProperty;
  31 import javafx.css.StyleOrigin;
  32 import javafx.css.StyleableBooleanProperty;
  33 import javafx.css.CssMetaData;
  34 
  35 import com.sun.javafx.css.converters.BooleanConverter;
  36 
  37 import java.util.ArrayList;
  38 import java.util.Collections;
  39 import java.util.List;
  40 import java.util.Locale;
  41 
  42 import javafx.css.StyleableDoubleProperty;
  43 import javafx.css.StyleableStringProperty;
  44 import javafx.geometry.Pos;
  45 import javafx.scene.Node;

  46 import javafx.scene.image.ImageView;
  47 import javafx.scene.layout.StackPane;
  48 import javafx.scene.shape.Rectangle;
  49 
  50 import com.sun.javafx.css.converters.SizeConverter;
  51 import com.sun.javafx.css.converters.StringConverter;
  52 import com.sun.javafx.scene.control.behavior.ColorPickerBehavior;
  53 
  54 import java.util.HashMap;
  55 import java.util.Map;
  56 
  57 import javafx.scene.control.ColorPicker;
  58 import javafx.scene.control.TextField;
  59 import javafx.beans.property.BooleanProperty;
  60 import javafx.beans.value.WritableValue;
  61 import javafx.css.Styleable;
  62 import javafx.css.StyleableProperty;
  63 import javafx.event.ActionEvent;
  64 import javafx.scene.control.Label;
  65 import javafx.scene.paint.Color;
  66 
  67 import com.sun.javafx.scene.control.skin.resources.ControlResources;
  68 
  69 import static javafx.scene.paint.Color.*;
  70 
  71 /**

  72  *


  73  */
  74 public class ColorPickerSkin extends ComboBoxPopupControl<Color> {
  75 






  76     private Label displayNode; 
  77     private StackPane pickerColorBox;
  78     private Rectangle colorRect; 
  79     private ColorPalette popupContent;






















































  80     BooleanProperty colorLabelVisible = new StyleableBooleanProperty(true) {
  81         @Override public void invalidated() {
  82             if (displayNode != null) {
  83                 if (colorLabelVisible.get()) {
  84                     displayNode.setText(colorDisplayName(((ColorPicker)getSkinnable()).getValue()));
  85                 } else {
  86                     displayNode.setText("");
  87                 }
  88             }
  89         }
  90         @Override public Object getBean() {
  91             return ColorPickerSkin.this;
  92         }
  93         @Override public String getName() {
  94             return "colorLabelVisible";
  95         }
  96         @Override public CssMetaData<ColorPicker,Boolean> getCssMetaData() {
  97             return StyleableProperties.COLOR_LABEL_VISIBLE;
  98         }
  99     };
 100     public StringProperty imageUrlProperty() { return imageUrl; }


 101     private final StyleableStringProperty imageUrl = new StyleableStringProperty() {
 102         @Override public void applyStyle(StyleOrigin origin, String v) {
 103             super.applyStyle(origin, v);
 104             if (v == null) {
 105                 // remove old image view
 106                 if (pickerColorBox.getChildren().size() == 2) pickerColorBox.getChildren().remove(1);
 107             } else {
 108                 if (pickerColorBox.getChildren().size() == 2) {
 109                     ImageView imageView = (ImageView)pickerColorBox.getChildren().get(1);
 110                     imageView.setImage(StyleManager.getInstance().getCachedImage(v));
 111                 } else {
 112                     pickerColorBox.getChildren().add(new ImageView(StyleManager.getInstance().getCachedImage(v)));
 113                 }
 114             }
 115         }
 116         @Override public Object getBean() {
 117             return ColorPickerSkin.this;
 118         }
 119         @Override public String getName() {
 120             return "imageUrl";
 121         }
 122         @Override public CssMetaData<ColorPicker,String> getCssMetaData() {
 123             return StyleableProperties.GRAPHIC;
 124         }
 125     };


 126     private final StyleableDoubleProperty colorRectWidth =  new StyleableDoubleProperty(12) {
 127         @Override protected void invalidated() {
 128             if(pickerColorBox!=null) pickerColorBox.requestLayout();
 129         }
 130         @Override public CssMetaData<ColorPicker,Number> getCssMetaData() {
 131             return StyleableProperties.COLOR_RECT_WIDTH;
 132         }
 133         @Override public Object getBean() {
 134             return ColorPickerSkin.this;
 135         }
 136         @Override public String getName() {
 137             return "colorRectWidth";
 138         }
 139     };


 140     private final StyleableDoubleProperty colorRectHeight =  new StyleableDoubleProperty(12) {
 141         @Override protected void invalidated() {
 142             if(pickerColorBox!=null) pickerColorBox.requestLayout();
 143         }
 144         @Override public CssMetaData<ColorPicker,Number> getCssMetaData() {
 145             return StyleableProperties.COLOR_RECT_HEIGHT;
 146         }
 147         @Override public Object getBean() {
 148             return ColorPickerSkin.this;
 149         }
 150         @Override public String getName() {
 151             return "colorRectHeight";
 152         }
 153     };


 154     private final StyleableDoubleProperty colorRectX =  new StyleableDoubleProperty(0) {
 155         @Override protected void invalidated() {
 156             if(pickerColorBox!=null) pickerColorBox.requestLayout();
 157         }
 158         @Override public CssMetaData<ColorPicker,Number> getCssMetaData() {
 159             return StyleableProperties.COLOR_RECT_X;
 160         }
 161         @Override public Object getBean() {
 162             return ColorPickerSkin.this;
 163         }
 164         @Override public String getName() {
 165             return "colorRectX";
 166         }
 167     };


 168     private final StyleableDoubleProperty colorRectY =  new StyleableDoubleProperty(0) {
 169         @Override protected void invalidated() {
 170             if(pickerColorBox!=null) pickerColorBox.requestLayout();
 171         }
 172         @Override public CssMetaData<ColorPicker,Number> getCssMetaData() {
 173             return StyleableProperties.COLOR_RECT_Y;
 174         }
 175         @Override public Object getBean() {
 176             return ColorPickerSkin.this;
 177         }
 178         @Override public String getName() {
 179             return "colorRectY";
 180         }
 181     };
 182 
 183     public ColorPickerSkin(final ColorPicker colorPicker) {
 184         super(colorPicker, new ColorPickerBehavior(colorPicker));
 185         updateComboBoxMode();
 186         registerChangeListener(colorPicker.valueProperty(), "VALUE");
 187 
 188         // create displayNode
 189         displayNode = new Label();
 190         displayNode.getStyleClass().add("color-picker-label");
 191         displayNode.setManaged(false);
 192 
 193         // label graphic
 194         pickerColorBox = new PickerColorBox();
 195         pickerColorBox.getStyleClass().add("picker-color");
 196         colorRect = new Rectangle(12, 12);
 197         colorRect.getStyleClass().add("picker-color-rect");
 198 
 199         updateColor();


 200 
 201         pickerColorBox.getChildren().add(colorRect);
 202         displayNode.setGraphic(pickerColorBox);

 203     }
 204 
 205 
 206     @Override protected double computePrefWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) {
 207         if (!colorLabelVisible.get()) {
 208             return super.computePrefWidth(height, topInset, rightInset, bottomInset, leftInset);
 209         }
 210         String displayNodeText = displayNode.getText();
 211         double width = 0;
 212         for (String name : colorNameMap.values()) {
 213             displayNode.setText(name);
 214             width = Math.max(width, super.computePrefWidth(height, topInset, rightInset, bottomInset, leftInset));
 215         }
 216         displayNode.setText(formatHexString(Color.BLACK)); // #000000
 217         width = Math.max(width, super.computePrefWidth(height, topInset, rightInset, bottomInset, leftInset));
 218         displayNode.setText(displayNodeText);
 219         return width;
 220     }
 221 















































 222     private void updateComboBoxMode() {
 223         List<String> styleClass = getSkinnable().getStyleClass();
 224         if (styleClass.contains(ColorPicker.STYLE_CLASS_BUTTON)) {
 225             setMode(ComboBoxMode.BUTTON);
 226         } else if (styleClass.contains(ColorPicker.STYLE_CLASS_SPLIT_BUTTON)) {
 227             setMode(ComboBoxMode.SPLITBUTTON);
 228         }
 229     }
 230 
 231     private static final Map<Color, String> colorNameMap = new HashMap<Color, String>(24);
 232     private static final Map<Color, String> cssNameMap = new HashMap<Color, String>(139);
 233     static {
 234         // Translatable display names for the most common colors
 235         colorNameMap.put(TRANSPARENT, getString("colorName.transparent"));
 236         colorNameMap.put(BLACK,       getString("colorName.black"));
 237         colorNameMap.put(BLUE,        getString("colorName.blue"));
 238         colorNameMap.put(CYAN,        getString("colorName.cyan"));
 239         colorNameMap.put(DARKBLUE,    getString("colorName.darkblue"));
 240         colorNameMap.put(DARKCYAN,    getString("colorName.darkcyan"));
 241         colorNameMap.put(DARKGRAY,    getString("colorName.darkgray"));
 242         colorNameMap.put(DARKGREEN,   getString("colorName.darkgreen"));
 243         colorNameMap.put(DARKMAGENTA, getString("colorName.darkmagenta"));
 244         colorNameMap.put(DARKRED,     getString("colorName.darkred"));
 245         colorNameMap.put(GRAY,        getString("colorName.gray"));
 246         colorNameMap.put(GREEN,       getString("colorName.green"));
 247         colorNameMap.put(LIGHTBLUE,   getString("colorName.lightblue"));
 248         colorNameMap.put(LIGHTCYAN,   getString("colorName.lightcyan"));
 249         colorNameMap.put(LIGHTGRAY,   getString("colorName.lightgray"));
 250         colorNameMap.put(LIGHTGREEN,  getString("colorName.lightgreen"));
 251         colorNameMap.put(LIGHTYELLOW, getString("colorName.lightyellow"));
 252         colorNameMap.put(MAGENTA,     getString("colorName.magenta"));
 253         colorNameMap.put(MEDIUMBLUE,  getString("colorName.mediumblue"));
 254         colorNameMap.put(ORANGE,      getString("colorName.orange"));
 255         colorNameMap.put(PINK,        getString("colorName.pink"));
 256         colorNameMap.put(RED,         getString("colorName.red"));
 257         colorNameMap.put(WHITE,       getString("colorName.white"));
 258         colorNameMap.put(YELLOW,      getString("colorName.yellow"));
 259 
 260         // CSS names.
 261         // Note that synonyms (such as "grey") have been removed here,
 262         // since a color can be presented with only one name in this
 263         // skin. If a reverse map is created for parsing names in the
 264         // future, then the synonyms should be included there. For a
 265         // full list of CSS names, see Color.java.
 266         cssNameMap.put(ALICEBLUE,            "aliceblue");
 267         cssNameMap.put(ANTIQUEWHITE,         "antiquewhite");
 268         cssNameMap.put(AQUAMARINE,           "aquamarine");
 269         cssNameMap.put(AZURE,                "azure");
 270         cssNameMap.put(BEIGE,                "beige");
 271         cssNameMap.put(BISQUE,               "bisque");
 272         cssNameMap.put(BLACK,                "black");
 273         cssNameMap.put(BLANCHEDALMOND,       "blanchedalmond");
 274         cssNameMap.put(BLUE,                 "blue");
 275         cssNameMap.put(BLUEVIOLET,           "blueviolet");
 276         cssNameMap.put(BROWN,                "brown");
 277         cssNameMap.put(BURLYWOOD,            "burlywood");
 278         cssNameMap.put(CADETBLUE,            "cadetblue");


 391         cssNameMap.put(SPRINGGREEN,          "springgreen");
 392         cssNameMap.put(STEELBLUE,            "steelblue");
 393         cssNameMap.put(TAN,                  "tan");
 394         cssNameMap.put(TEAL,                 "teal");
 395         cssNameMap.put(THISTLE,              "thistle");
 396         cssNameMap.put(TOMATO,               "tomato");
 397         cssNameMap.put(TRANSPARENT,          "transparent");
 398         cssNameMap.put(TURQUOISE,            "turquoise");
 399         cssNameMap.put(VIOLET,               "violet");
 400         cssNameMap.put(WHEAT,                "wheat");
 401         cssNameMap.put(WHITE,                "white");
 402         cssNameMap.put(WHITESMOKE,           "whitesmoke");
 403         cssNameMap.put(YELLOW,               "yellow");
 404         cssNameMap.put(YELLOWGREEN,          "yellowgreen");
 405     }
 406 
 407     static String colorDisplayName(Color c) {
 408         if (c != null) {
 409             String displayName = colorNameMap.get(c);
 410             if (displayName == null) {
 411                 displayName = formatHexString(c);
 412             }
 413             return displayName;
 414         } else {
 415             return null;
 416         }
 417     }
 418 
 419     static String tooltipString(Color c) {
 420         if (c != null) {
 421             String tooltipStr = "";
 422             String displayName = colorNameMap.get(c);
 423             if (displayName != null) {
 424                 tooltipStr += displayName + " ";
 425             }
 426 
 427             tooltipStr += formatHexString(c);
 428 
 429             String cssName = cssNameMap.get(c);
 430             if (cssName != null) {
 431                 tooltipStr += " (css: " + cssName + ")";
 432             }
 433             return tooltipStr;
 434         } else {
 435             return null;
 436         }
 437     }
 438 
 439     static String formatHexString(Color c) {
 440         if (c != null) {
 441             return String.format((Locale) null, "#%02x%02x%02x",
 442                                  Math.round(c.getRed() * 255),
 443                                  Math.round(c.getGreen() * 255),
 444                                  Math.round(c.getBlue() * 255));
 445         } else {
 446             return null;
 447         }
 448     }
 449 
 450     @Override protected Node getPopupContent() {
 451         if (popupContent == null) {
 452 //            popupContent = new ColorPalette(colorPicker.getValue(), colorPicker);
 453             popupContent = new ColorPalette((ColorPicker)getSkinnable());
 454             popupContent.setPopupControl(getPopup());
 455         }
 456        return popupContent;
 457     }
 458     
 459     @Override protected void focusLost() {
 460         // do nothing
 461     }
 462     
 463     @Override public void show() {
 464         super.show();
 465         final ColorPicker colorPicker = (ColorPicker)getSkinnable();
 466         popupContent.updateSelection(colorPicker.getValue());
 467     }
 468     
 469     @Override protected void handleControlPropertyChanged(String p) {
 470         super.handleControlPropertyChanged(p);
 471     
 472         if ("SHOWING".equals(p)) {
 473             if (getSkinnable().isShowing()) {
 474                 show();
 475             } else {
 476                 if (!popupContent.isCustomColorDialogShowing()) hide();
 477             }
 478         } else if ("VALUE".equals(p)) {
 479             updateColor();
 480            // Change the current selected color in the grid if ColorPicker value changes
 481             if (popupContent != null) {
 482 //                popupContent.updateSelection(getSkinnable().getValue());
 483             }
 484         }
 485     }
 486     @Override public Node getDisplayNode() {
 487         return displayNode;
 488     }
 489     
 490     private void updateColor() {
 491         final ColorPicker colorPicker = (ColorPicker)getSkinnable();
 492         colorRect.setFill(colorPicker.getValue());
 493         if (colorLabelVisible.get()) {
 494             displayNode.setText(colorDisplayName(colorPicker.getValue()));
 495         } else {
 496             displayNode.setText("");
 497         }
 498     }
 499     public void syncWithAutoUpdate() {
 500         if (!getPopup().isShowing() && getSkinnable().isShowing()) {
 501             // Popup was dismissed. Maybe user clicked outside or typed ESCAPE.
 502             // Make sure ColorPicker button is in sync.
 503             getSkinnable().hide();
 504         }
 505     }
 506     
 507     @Override protected void layoutChildren(final double x, final double y,
 508             final double w, final double h) {
 509         updateComboBoxMode();
 510         super.layoutChildren(x,y,w,h);
 511     }
 512 
 513     static String getString(String key) {
 514         return ControlResources.getString("ColorPicker."+key);
 515     }
 516 
 517     /***************************************************************************
 518     *                                                                         *
 519     *                         picker-color-cell                               *
 520     *                                                                         *
 521     **************************************************************************/
 522 
 523     private class PickerColorBox extends StackPane {
 524         @Override protected void layoutChildren() {
 525             final double top = snappedTopInset();
 526             final double left = snappedLeftInset();
 527             final double width = getWidth();
 528             final double height = getHeight();
 529             final double right = snappedRightInset();
 530             final double bottom = snappedBottomInset();
 531             colorRect.setX(snapPosition(colorRectX.get()));
 532             colorRect.setY(snapPosition(colorRectY.get()));
 533             colorRect.setWidth(snapSize(colorRectWidth.get()));
 534             colorRect.setHeight(snapSize(colorRectHeight.get()));
 535             if (getChildren().size() == 2) {


 627                 @Override public StyleableProperty<String> getStyleableProperty(ColorPicker n) {
 628                     final ColorPickerSkin skin = (ColorPickerSkin) n.getSkin();
 629                     return skin.imageUrl;
 630                 }
 631             };
 632         private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES;
 633         static {
 634             final List<CssMetaData<? extends Styleable, ?>> styleables =
 635                 new ArrayList<CssMetaData<? extends Styleable, ?>>(ComboBoxBaseSkin.getClassCssMetaData());
 636             styleables.add(COLOR_LABEL_VISIBLE);
 637             styleables.add(COLOR_RECT_WIDTH);
 638             styleables.add(COLOR_RECT_HEIGHT);
 639             styleables.add(COLOR_RECT_X);
 640             styleables.add(COLOR_RECT_Y);
 641             styleables.add(GRAPHIC);
 642             STYLEABLES = Collections.unmodifiableList(styleables);
 643         }
 644     }
 645      
 646     /**
 647      * @return The CssMetaData associated with this class, which may include the
 648      * CssMetaData of its super classes.
 649      */
 650     public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() {
 651         return StyleableProperties.STYLEABLES;
 652     }
 653 
 654     /**
 655      * {@inheritDoc}
 656      */
 657     @Override
 658     public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() {
 659         return getClassCssMetaData();
 660     }
 661 

 662     @Override protected javafx.util.StringConverter<Color> getConverter() {
 663         return null;
 664     }
 665 
 666     /**
 667      * ColorPicker does not use a main text field.

 668      */
 669     @Override protected TextField getEditor() {
 670         return null;
 671     }
 672 }


   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javafx.scene.control.skin;
  27 
  28 import com.sun.javafx.css.StyleManager;
  29 
  30 import com.sun.javafx.scene.control.Properties;
  31 import com.sun.javafx.scene.control.behavior.ComboBoxBaseBehavior;
  32 import com.sun.javafx.scene.control.skin.Utils;
  33 import javafx.beans.property.StringProperty;
  34 import javafx.css.StyleOrigin;
  35 import javafx.css.StyleableBooleanProperty;
  36 import javafx.css.CssMetaData;
  37 
  38 import javafx.css.converter.BooleanConverter;
  39 
  40 import java.util.ArrayList;
  41 import java.util.Collections;
  42 import java.util.List;

  43 
  44 import javafx.css.StyleableDoubleProperty;
  45 import javafx.css.StyleableStringProperty;
  46 import javafx.geometry.Pos;
  47 import javafx.scene.Node;
  48 import javafx.scene.control.Control;
  49 import javafx.scene.image.ImageView;
  50 import javafx.scene.layout.StackPane;
  51 import javafx.scene.shape.Rectangle;
  52 
  53 import javafx.css.converter.SizeConverter;
  54 import javafx.css.converter.StringConverter;
  55 import com.sun.javafx.scene.control.behavior.ColorPickerBehavior;
  56 
  57 import java.util.HashMap;
  58 import java.util.Map;
  59 
  60 import javafx.scene.control.ColorPicker;
  61 import javafx.scene.control.TextField;
  62 import javafx.beans.property.BooleanProperty;
  63 import javafx.beans.value.WritableValue;
  64 import javafx.css.Styleable;
  65 import javafx.css.StyleableProperty;

  66 import javafx.scene.control.Label;
  67 import javafx.scene.paint.Color;
  68 


  69 import static javafx.scene.paint.Color.*;
  70 
  71 /**
  72  * Default skin implementation for the {@link ColorPicker} control.
  73  *
  74  * @see ColorPicker
  75  * @since 9
  76  */
  77 public class ColorPickerSkin extends ComboBoxPopupControl<Color> {
  78 
  79     /***************************************************************************
  80      *                                                                         *
  81      * Private fields                                                          *
  82      *                                                                         *
  83      **************************************************************************/
  84 
  85     private Label displayNode;
  86     private StackPane pickerColorBox;
  87     private Rectangle colorRect; 
  88     private ColorPalette popupContent;
  89 
  90     private final ColorPickerBehavior behavior;
  91 
  92 
  93 
  94     /***************************************************************************
  95      *                                                                         *
  96      * Constructors                                                            *
  97      *                                                                         *
  98      **************************************************************************/
  99 
 100     /**
 101      * Creates a new ColorPickerSkin instance, installing the necessary child
 102      * nodes into the Control {@link Control#getChildren() children} list, as
 103      * well as the necessary input mappings for handling key, mouse, etc events.
 104      *
 105      * @param control The control that this skin should be installed onto.
 106      */
 107     public ColorPickerSkin(final ColorPicker control) {
 108         super(control);
 109 
 110         // install default input map for the control
 111         this.behavior = new ColorPickerBehavior(control);
 112 //        control.setInputMap(behavior.getInputMap());
 113 
 114         updateComboBoxMode();
 115         registerChangeListener(control.valueProperty(), e -> updateColor());
 116 
 117         // create displayNode
 118         displayNode = new Label();
 119         displayNode.getStyleClass().add("color-picker-label");
 120         displayNode.setManaged(false);
 121 
 122         // label graphic
 123         pickerColorBox = new PickerColorBox();
 124         pickerColorBox.getStyleClass().add("picker-color");
 125         colorRect = new Rectangle(12, 12);
 126         colorRect.getStyleClass().add("picker-color-rect");
 127 
 128         updateColor();
 129 
 130         pickerColorBox.getChildren().add(colorRect);
 131         displayNode.setGraphic(pickerColorBox);
 132     }
 133 
 134 
 135 
 136     /***************************************************************************
 137      *                                                                         *
 138      * Properties                                                              *
 139      *                                                                         *
 140      **************************************************************************/
 141 
 142     // --- color label visible
 143     BooleanProperty colorLabelVisible = new StyleableBooleanProperty(true) {
 144         @Override public void invalidated() {
 145             if (displayNode != null) {
 146                 if (colorLabelVisible.get()) {
 147                     displayNode.setText(colorDisplayName(((ColorPicker)getSkinnable()).getValue()));
 148                 } else {
 149                     displayNode.setText("");
 150                 }
 151             }
 152         }
 153         @Override public Object getBean() {
 154             return ColorPickerSkin.this;
 155         }
 156         @Override public String getName() {
 157             return "colorLabelVisible";
 158         }
 159         @Override public CssMetaData<ColorPicker,Boolean> getCssMetaData() {
 160             return StyleableProperties.COLOR_LABEL_VISIBLE;
 161         }
 162     };
 163 
 164     // --- image url
 165     private final StringProperty imageUrlProperty() { return imageUrl; }
 166     private final StyleableStringProperty imageUrl = new StyleableStringProperty() {
 167         @Override public void applyStyle(StyleOrigin origin, String v) {
 168             super.applyStyle(origin, v);
 169             if (v == null) {
 170                 // remove old image view
 171                 if (pickerColorBox.getChildren().size() == 2) pickerColorBox.getChildren().remove(1);
 172             } else {
 173                 if (pickerColorBox.getChildren().size() == 2) {
 174                     ImageView imageView = (ImageView)pickerColorBox.getChildren().get(1);
 175                     imageView.setImage(StyleManager.getInstance().getCachedImage(v));
 176                 } else {
 177                     pickerColorBox.getChildren().add(new ImageView(StyleManager.getInstance().getCachedImage(v)));
 178                 }
 179             }
 180         }
 181         @Override public Object getBean() {
 182             return ColorPickerSkin.this;
 183         }
 184         @Override public String getName() {
 185             return "imageUrl";
 186         }
 187         @Override public CssMetaData<ColorPicker,String> getCssMetaData() {
 188             return StyleableProperties.GRAPHIC;
 189         }
 190     };
 191 
 192     // --- color rect width
 193     private final StyleableDoubleProperty colorRectWidth =  new StyleableDoubleProperty(12) {
 194         @Override protected void invalidated() {
 195             if(pickerColorBox!=null) pickerColorBox.requestLayout();
 196         }
 197         @Override public CssMetaData<ColorPicker,Number> getCssMetaData() {
 198             return StyleableProperties.COLOR_RECT_WIDTH;
 199         }
 200         @Override public Object getBean() {
 201             return ColorPickerSkin.this;
 202         }
 203         @Override public String getName() {
 204             return "colorRectWidth";
 205         }
 206     };
 207 
 208     // --- color rect height
 209     private final StyleableDoubleProperty colorRectHeight =  new StyleableDoubleProperty(12) {
 210         @Override protected void invalidated() {
 211             if(pickerColorBox!=null) pickerColorBox.requestLayout();
 212         }
 213         @Override public CssMetaData<ColorPicker,Number> getCssMetaData() {
 214             return StyleableProperties.COLOR_RECT_HEIGHT;
 215         }
 216         @Override public Object getBean() {
 217             return ColorPickerSkin.this;
 218         }
 219         @Override public String getName() {
 220             return "colorRectHeight";
 221         }
 222     };
 223 
 224     // --- color rect X
 225     private final StyleableDoubleProperty colorRectX =  new StyleableDoubleProperty(0) {
 226         @Override protected void invalidated() {
 227             if(pickerColorBox!=null) pickerColorBox.requestLayout();
 228         }
 229         @Override public CssMetaData<ColorPicker,Number> getCssMetaData() {
 230             return StyleableProperties.COLOR_RECT_X;
 231         }
 232         @Override public Object getBean() {
 233             return ColorPickerSkin.this;
 234         }
 235         @Override public String getName() {
 236             return "colorRectX";
 237         }
 238     };
 239 
 240     // --- color rect Y
 241     private final StyleableDoubleProperty colorRectY =  new StyleableDoubleProperty(0) {
 242         @Override protected void invalidated() {
 243             if(pickerColorBox!=null) pickerColorBox.requestLayout();
 244         }
 245         @Override public CssMetaData<ColorPicker,Number> getCssMetaData() {
 246             return StyleableProperties.COLOR_RECT_Y;
 247         }
 248         @Override public Object getBean() {
 249             return ColorPickerSkin.this;
 250         }
 251         @Override public String getName() {
 252             return "colorRectY";
 253         }
 254     };
 255 




 256 




 257 
 258     /***************************************************************************
 259      *                                                                         *
 260      * Public API                                                              *
 261      *                                                                         *
 262      **************************************************************************/
 263 
 264     /** {@inheritDoc} */
 265     @Override public void dispose() {
 266         super.dispose();
 267 
 268         if (behavior != null) {
 269             behavior.dispose();
 270         }
 271     }
 272 
 273     /** {@inheritDoc} */
 274     @Override protected double computePrefWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) {
 275         if (!colorLabelVisible.get()) {
 276             return super.computePrefWidth(height, topInset, rightInset, bottomInset, leftInset);
 277         }
 278         String displayNodeText = displayNode.getText();
 279         double width = 0;
 280         for (String name : colorNameMap.values()) {
 281             displayNode.setText(name);
 282             width = Math.max(width, super.computePrefWidth(height, topInset, rightInset, bottomInset, leftInset));
 283         }
 284         displayNode.setText(Utils.formatHexString(Color.BLACK)); // #000000
 285         width = Math.max(width, super.computePrefWidth(height, topInset, rightInset, bottomInset, leftInset));
 286         displayNode.setText(displayNodeText);
 287         return width;
 288     }
 289 
 290     /** {@inheritDoc} */
 291     @Override protected Node getPopupContent() {
 292         if (popupContent == null) {
 293 //            popupContent = new ColorPalette(colorPicker.getValue(), colorPicker);
 294             popupContent = new ColorPalette((ColorPicker)getSkinnable());
 295             popupContent.setPopupControl(getPopup());
 296         }
 297         return popupContent;
 298     }
 299 
 300     /** {@inheritDoc} */
 301     @Override public void show() {
 302         super.show();
 303         final ColorPicker colorPicker = (ColorPicker)getSkinnable();
 304         popupContent.updateSelection(colorPicker.getValue());
 305     }
 306 
 307     /** {@inheritDoc} */
 308     @Override public Node getDisplayNode() {
 309         return displayNode;
 310     }
 311 
 312     /** {@inheritDoc} */
 313     @Override protected void layoutChildren(final double x, final double y,
 314                                             final double w, final double h) {
 315         updateComboBoxMode();
 316         super.layoutChildren(x, y, w, h);
 317     }
 318 
 319 
 320 
 321     /***************************************************************************
 322      *                                                                         *
 323      * Private implementation                                                  *
 324      *                                                                         *
 325      **************************************************************************/
 326 
 327     /** {@inheritDoc} */
 328     @Override void focusLost() {
 329         // do nothing
 330     }
 331 
 332     /** {@inheritDoc} */
 333     @Override ComboBoxBaseBehavior getBehavior() {
 334         return behavior;
 335     }
 336 
 337     private void updateComboBoxMode() {
 338         List<String> styleClass = getSkinnable().getStyleClass();
 339         if (styleClass.contains(ColorPicker.STYLE_CLASS_BUTTON)) {
 340             setMode(ComboBoxMode.BUTTON);
 341         } else if (styleClass.contains(ColorPicker.STYLE_CLASS_SPLIT_BUTTON)) {
 342             setMode(ComboBoxMode.SPLITBUTTON);
 343         }
 344     }
 345 
 346     private static final Map<Color, String> colorNameMap = new HashMap<>(24);
 347     private static final Map<Color, String> cssNameMap = new HashMap<>(139);
 348     static {
 349         // Translatable display names for the most common colors
 350         colorNameMap.put(TRANSPARENT, Properties.getColorPickerString("colorName.transparent"));
 351         colorNameMap.put(BLACK,       Properties.getColorPickerString("colorName.black"));
 352         colorNameMap.put(BLUE,        Properties.getColorPickerString("colorName.blue"));
 353         colorNameMap.put(CYAN,        Properties.getColorPickerString("colorName.cyan"));
 354         colorNameMap.put(DARKBLUE,    Properties.getColorPickerString("colorName.darkblue"));
 355         colorNameMap.put(DARKCYAN,    Properties.getColorPickerString("colorName.darkcyan"));
 356         colorNameMap.put(DARKGRAY,    Properties.getColorPickerString("colorName.darkgray"));
 357         colorNameMap.put(DARKGREEN,   Properties.getColorPickerString("colorName.darkgreen"));
 358         colorNameMap.put(DARKMAGENTA, Properties.getColorPickerString("colorName.darkmagenta"));
 359         colorNameMap.put(DARKRED,     Properties.getColorPickerString("colorName.darkred"));
 360         colorNameMap.put(GRAY,        Properties.getColorPickerString("colorName.gray"));
 361         colorNameMap.put(GREEN,       Properties.getColorPickerString("colorName.green"));
 362         colorNameMap.put(LIGHTBLUE,   Properties.getColorPickerString("colorName.lightblue"));
 363         colorNameMap.put(LIGHTCYAN,   Properties.getColorPickerString("colorName.lightcyan"));
 364         colorNameMap.put(LIGHTGRAY,   Properties.getColorPickerString("colorName.lightgray"));
 365         colorNameMap.put(LIGHTGREEN,  Properties.getColorPickerString("colorName.lightgreen"));
 366         colorNameMap.put(LIGHTYELLOW, Properties.getColorPickerString("colorName.lightyellow"));
 367         colorNameMap.put(MAGENTA,     Properties.getColorPickerString("colorName.magenta"));
 368         colorNameMap.put(MEDIUMBLUE,  Properties.getColorPickerString("colorName.mediumblue"));
 369         colorNameMap.put(ORANGE,      Properties.getColorPickerString("colorName.orange"));
 370         colorNameMap.put(PINK,        Properties.getColorPickerString("colorName.pink"));
 371         colorNameMap.put(RED,         Properties.getColorPickerString("colorName.red"));
 372         colorNameMap.put(WHITE,       Properties.getColorPickerString("colorName.white"));
 373         colorNameMap.put(YELLOW,      Properties.getColorPickerString("colorName.yellow"));
 374 
 375         // CSS names.
 376         // Note that synonyms (such as "grey") have been removed here,
 377         // since a color can be presented with only one name in this
 378         // skin. If a reverse map is created for parsing names in the
 379         // future, then the synonyms should be included there. For a
 380         // full list of CSS names, see Color.java.
 381         cssNameMap.put(ALICEBLUE,            "aliceblue");
 382         cssNameMap.put(ANTIQUEWHITE,         "antiquewhite");
 383         cssNameMap.put(AQUAMARINE,           "aquamarine");
 384         cssNameMap.put(AZURE,                "azure");
 385         cssNameMap.put(BEIGE,                "beige");
 386         cssNameMap.put(BISQUE,               "bisque");
 387         cssNameMap.put(BLACK,                "black");
 388         cssNameMap.put(BLANCHEDALMOND,       "blanchedalmond");
 389         cssNameMap.put(BLUE,                 "blue");
 390         cssNameMap.put(BLUEVIOLET,           "blueviolet");
 391         cssNameMap.put(BROWN,                "brown");
 392         cssNameMap.put(BURLYWOOD,            "burlywood");
 393         cssNameMap.put(CADETBLUE,            "cadetblue");


 506         cssNameMap.put(SPRINGGREEN,          "springgreen");
 507         cssNameMap.put(STEELBLUE,            "steelblue");
 508         cssNameMap.put(TAN,                  "tan");
 509         cssNameMap.put(TEAL,                 "teal");
 510         cssNameMap.put(THISTLE,              "thistle");
 511         cssNameMap.put(TOMATO,               "tomato");
 512         cssNameMap.put(TRANSPARENT,          "transparent");
 513         cssNameMap.put(TURQUOISE,            "turquoise");
 514         cssNameMap.put(VIOLET,               "violet");
 515         cssNameMap.put(WHEAT,                "wheat");
 516         cssNameMap.put(WHITE,                "white");
 517         cssNameMap.put(WHITESMOKE,           "whitesmoke");
 518         cssNameMap.put(YELLOW,               "yellow");
 519         cssNameMap.put(YELLOWGREEN,          "yellowgreen");
 520     }
 521 
 522     static String colorDisplayName(Color c) {
 523         if (c != null) {
 524             String displayName = colorNameMap.get(c);
 525             if (displayName == null) {
 526                 displayName = Utils.formatHexString(c);
 527             }
 528             return displayName;
 529         } else {
 530             return null;
 531         }
 532     }
 533 
 534     static String tooltipString(Color c) {
 535         if (c != null) {
 536             String tooltipStr = "";
 537             String displayName = colorNameMap.get(c);
 538             if (displayName != null) {
 539                 tooltipStr += displayName + " ";
 540             }
 541 
 542             tooltipStr += Utils.formatHexString(c);
 543 
 544             String cssName = cssNameMap.get(c);
 545             if (cssName != null) {
 546                 tooltipStr += " (css: " + cssName + ")";
 547             }
 548             return tooltipStr;
 549         } else {
 550             return null;
 551         }
 552     }
 553 



















































 554     private void updateColor() {
 555         final ColorPicker colorPicker = (ColorPicker)getSkinnable();
 556         colorRect.setFill(colorPicker.getValue());
 557         if (colorLabelVisible.get()) {
 558             displayNode.setText(colorDisplayName(colorPicker.getValue()));
 559         } else {
 560             displayNode.setText("");
 561         }
 562     }







 563 





 564 



 565 
 566     /***************************************************************************
 567     *                                                                         *
 568     *                         picker-color-cell                               *
 569     *                                                                         *
 570     **************************************************************************/
 571 
 572     private class PickerColorBox extends StackPane {
 573         @Override protected void layoutChildren() {
 574             final double top = snappedTopInset();
 575             final double left = snappedLeftInset();
 576             final double width = getWidth();
 577             final double height = getHeight();
 578             final double right = snappedRightInset();
 579             final double bottom = snappedBottomInset();
 580             colorRect.setX(snapPosition(colorRectX.get()));
 581             colorRect.setY(snapPosition(colorRectY.get()));
 582             colorRect.setWidth(snapSize(colorRectWidth.get()));
 583             colorRect.setHeight(snapSize(colorRectHeight.get()));
 584             if (getChildren().size() == 2) {


 676                 @Override public StyleableProperty<String> getStyleableProperty(ColorPicker n) {
 677                     final ColorPickerSkin skin = (ColorPickerSkin) n.getSkin();
 678                     return skin.imageUrl;
 679                 }
 680             };
 681         private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES;
 682         static {
 683             final List<CssMetaData<? extends Styleable, ?>> styleables =
 684                 new ArrayList<CssMetaData<? extends Styleable, ?>>(ComboBoxBaseSkin.getClassCssMetaData());
 685             styleables.add(COLOR_LABEL_VISIBLE);
 686             styleables.add(COLOR_RECT_WIDTH);
 687             styleables.add(COLOR_RECT_HEIGHT);
 688             styleables.add(COLOR_RECT_X);
 689             styleables.add(COLOR_RECT_Y);
 690             styleables.add(GRAPHIC);
 691             STYLEABLES = Collections.unmodifiableList(styleables);
 692         }
 693     }
 694 
 695     /**
 696      * Returns the CssMetaData associated with this class, which may include the
 697      * CssMetaData of its super classes.
 698      */
 699     public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() {
 700         return StyleableProperties.STYLEABLES;
 701     }
 702 
 703     /**
 704      * {@inheritDoc}
 705      */
 706     @Override
 707     public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() {
 708         return getClassCssMetaData();
 709     }
 710 
 711     /** {@inheritDoc} */
 712     @Override protected javafx.util.StringConverter<Color> getConverter() {
 713         return null;
 714     }
 715 
 716     /**
 717      * ColorPicker does not use a main text field, so this method has been
 718      * overridden to return null.
 719      */
 720     @Override protected TextField getEditor() {
 721         return null;
 722     }
 723 }