       1 /*
       2  * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
       3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       4  *
       5  * This code is free software; you can redistribute it and/or modify it
       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 import javafx.beans.property.StringProperty;
      30 import javafx.css.StyleOrigin;
      31 import javafx.css.StyleableBooleanProperty;
      32 import javafx.css.CssMetaData;
      33 import com.sun.javafx.css.converters.BooleanConverter;
      34 import java.util.ArrayList;
      35 import java.util.Collections;
      36 import java.util.List;
      37 import java.util.Locale;
      38 import javafx.css.StyleableDoubleProperty;
      39 import javafx.css.StyleableStringProperty;
      40 import javafx.geometry.Pos;
      41 import javafx.scene.Node;
      42 import javafx.event.EventHandler;
      43 import javafx.scene.image.ImageView;
      44 import javafx.scene.input.MouseEvent;
      45 import javafx.scene.layout.StackPane;
      46 import javafx.scene.shape.Rectangle;
      47 import com.sun.javafx.css.converters.SizeConverter;
      48 import com.sun.javafx.css.converters.StringConverter;
      49 import com.sun.javafx.scene.control.behavior.ColorPickerBehavior;
      50 import java.util.HashMap;
      51 import java.util.Map;
      52 import javafx.scene.control.ColorPicker;
      53 import javafx.beans.property.BooleanProperty;
      54 import javafx.css.Styleable;
      55 import javafx.css.StyleableProperty;
      56 import javafx.event.ActionEvent;
      57 import javafx.scene.control.Label;
      58 import javafx.scene.paint.Color;
      59
      60 /**
      61  *
      62  */
      63 public class ColorPickerSkin extends ComboBoxPopupControl<Color> {
      64
      65     private Label displayNode;
      66     private StackPane pickerColorBox;
      67     private Rectangle colorRect;
      68     private ColorPalette popupContent;
      69     BooleanProperty colorLabelVisible = new StyleableBooleanProperty(true) {
      70         @Override public void invalidated() {
      71             if (displayNode != null) {
      72                 if (colorLabelVisible.get()) {
      73                     displayNode.setText(colorValueToWeb(((ColorPicker)getSkinnable()).getValue()));
      74                 } else {
      75                     displayNode.setText("");
      76                 }
      77             }
      78         }
      79         @Override public Object getBean() {
      80             return ColorPickerSkin.this;
      81         }
      82         @Override public String getName() {
      83             return "colorLabelVisible";
      84         }
      85         @Override public CssMetaData<ColorPicker,Boolean> getCssMetaData() {
      86             return StyleableProperties.COLOR_LABEL_VISIBLE;
      87         }
      88     };
      89     public StringProperty imageUrlProperty() { return imageUrl; }
      90     private final StyleableStringProperty imageUrl = new StyleableStringProperty() {
      91         @Override public void applyStyle(StyleOrigin origin, String v) {
      92             super.applyStyle(origin, v);
      93             if (v == null) {
      94                 // remove old image view
      95                 if (pickerColorBox.getChildren().size() == 2) pickerColorBox.getChildren().remove(1);
      96             } else {
      97                 if (pickerColorBox.getChildren().size() == 2) {
      98                     ImageView imageView = (ImageView)pickerColorBox.getChildren().get(1);
      99                     imageView.setImage(StyleManager.getInstance().getCachedImage(v));
     100                 } else {
     101                     pickerColorBox.getChildren().add(new ImageView(StyleManager.getInstance().getCachedImage(v)));
     102                 }
     103             }
     104         }
     105         @Override public Object getBean() {
     106             return ColorPickerSkin.this;
     107         }
     108         @Override public String getName() {
     109             return "imageUrl";
     110         }
     111         @Override public CssMetaData<ColorPicker,String> getCssMetaData() {
     112             return StyleableProperties.GRAPHIC;
     113         }
     114     };
     115     private final StyleableDoubleProperty colorRectWidth =  new StyleableDoubleProperty(12) {
     116         @Override protected void invalidated() {
     117             if(pickerColorBox!=null) pickerColorBox.requestLayout();
     118         }
     119         @Override public CssMetaData<ColorPicker,Number> getCssMetaData() {
     120             return StyleableProperties.COLOR_RECT_WIDTH;
     121         }
     122         @Override public Object getBean() {
     123             return ColorPickerSkin.this;
     124         }
     125         @Override public String getName() {
     126             return "colorRectWidth";
     127         }
     128     };
     129     private final StyleableDoubleProperty colorRectHeight =  new StyleableDoubleProperty(12) {
     130         @Override protected void invalidated() {
     131             if(pickerColorBox!=null) pickerColorBox.requestLayout();
     132         }
     133         @Override public CssMetaData<ColorPicker,Number> getCssMetaData() {
     134             return StyleableProperties.COLOR_RECT_HEIGHT;
     135         }
     136         @Override public Object getBean() {
     137             return ColorPickerSkin.this;
     138         }
     139         @Override public String getName() {
     140             return "colorRectHeight";
     141         }
     142     };
     143     private final StyleableDoubleProperty colorRectX =  new StyleableDoubleProperty(0) {
     144         @Override protected void invalidated() {
     145             if(pickerColorBox!=null) pickerColorBox.requestLayout();
     146         }
     147         @Override public CssMetaData<ColorPicker,Number> getCssMetaData() {
     148             return StyleableProperties.COLOR_RECT_X;
     149         }
     150         @Override public Object getBean() {
     151             return ColorPickerSkin.this;
     152         }
     153         @Override public String getName() {
     154             return "colorRectX";
     155         }
     156     };
     157     private final StyleableDoubleProperty colorRectY =  new StyleableDoubleProperty(0) {
     158         @Override protected void invalidated() {
     159             if(pickerColorBox!=null) pickerColorBox.requestLayout();
     160         }
     161         @Override public CssMetaData<ColorPicker,Number> getCssMetaData() {
     162             return StyleableProperties.COLOR_RECT_Y;
     163         }
     164         @Override public Object getBean() {
     165             return ColorPickerSkin.this;
     166         }
     167         @Override public String getName() {
     168             return "colorRectY";
     169         }
     170     };
     171
     172     public ColorPickerSkin(final ColorPicker colorPicker) {
     173         super(colorPicker, new ColorPickerBehavior(colorPicker));
     174         updateComboBoxMode();
     175         if (getMode() == ComboBoxMode.BUTTON || getMode() == ComboBoxMode.COMBOBOX) {
     176              if (arrowButton.getOnMouseReleased() == null) {
     177                 arrowButton.setOnMouseReleased(new EventHandler<MouseEvent>() {
     178                     @Override public void handle(MouseEvent e) {
     179                         ((ColorPickerBehavior)getBehavior()).mouseReleased(e, true);
     180                         e.consume();
     181                     }
     182                 });
     183             }
     184         } else if (getMode() == ComboBoxMode.SPLITBUTTON) {
     185             if (arrowButton.getOnMouseReleased() == null) {
     186                 arrowButton.setOnMouseReleased(new EventHandler<MouseEvent>() {
     187                     @Override public void handle(MouseEvent e) {
     188                         ((ColorPickerBehavior)getBehavior()).mouseReleased(e, true);
     189                         e.consume();
     190                     }
     191                 });
     192             }
     193         }
     194         registerChangeListener(colorPicker.valueProperty(), "VALUE");
     195
     196         // create displayNode
     197         displayNode = new Label();
     198         displayNode.getStyleClass().add("color-picker-label");
     199         if (getMode() == ComboBoxMode.BUTTON || getMode() == ComboBoxMode.COMBOBOX) {
     200             if (displayNode.getOnMouseReleased() == null) {
     201                 displayNode.setOnMouseReleased(new EventHandler<MouseEvent>() {
     202                     @Override public void handle(MouseEvent e) {
     203                         ((ColorPickerBehavior)getBehavior()).mouseReleased(e, true);
     204                     }
     205                 });
     206             }
     207         } else {
     208             if (displayNode.getOnMouseReleased() == null) {
     209                 displayNode.setOnMouseReleased(new EventHandler<MouseEvent>() {
     210                     @Override public void handle(MouseEvent e) {
     211                         ((ColorPickerBehavior)getBehavior()).mouseReleased(e, false);
     212                         e.consume();
     213                     }
     214                 });
     215             }
     216         }
     217         // label graphic
     218         pickerColorBox = new PickerColorBox();
     219         pickerColorBox.getStyleClass().add("picker-color");
     220         colorRect = new Rectangle(12, 12);
     221         colorRect.getStyleClass().add("picker-color-rect");
     222
     223         updateColor();
     224         colorPicker.addEventHandler(ActionEvent.ACTION, new EventHandler<ActionEvent>() {
     225             @Override
     226             public void handle(ActionEvent t) {
     227                 updateColor();
     228             }
     229         });
     230
     231         pickerColorBox.getChildren().add(colorRect);
     232         displayNode.setGraphic(pickerColorBox);
     233         if (displayNode.getOnMouseReleased() == null) {
     234             displayNode.setOnMouseReleased(new EventHandler<MouseEvent>() {
     235                 @Override
     236                 public void handle(MouseEvent e) {
     237                     ((ColorPickerBehavior)getBehavior()).mouseReleased(e, false);
     238                     e.consume();
     239                 }
     240             });
     241         }
     242     }
     243
     244
     245
     246     private void updateComboBoxMode() {
     247         if (getSkinnable().getStyleClass().contains(ColorPicker.STYLE_CLASS_BUTTON)) {
     248             setMode(ComboBoxMode.BUTTON);
     249         }
     250         else if (getSkinnable().getStyleClass().contains(ColorPicker.STYLE_CLASS_SPLIT_BUTTON)) {
     251             setMode(ComboBoxMode.SPLITBUTTON);
     252         }
     253     }
     254
     255     private static final Map<Color, String> colorNameMap = new HashMap<Color, String>(147);
     256     static {
     257         // The following code is used to generate the hard-coded colorNameMap
     258         // below, but it is then hand tweaked to proper represent the colour
     259         // names.
     260
     261 //        // Initializes the namedColors map
     262 //        Color.web("white", 1.0);
     263 //        for (Field f : Color.class.getDeclaredFields()) {
     264 //            int modifier = f.getModifiers();
     265 //            if (Modifier.isStatic(modifier) && Modifier.isPublic(modifier) && f.getType().equals(Color.class)) {
     266 //                colorNames.add(f.getName());
     267 //
     268 //                String name = f.toString();
     269 //                name = name.substring(name.lastIndexOf("Color."));
     270 //
     271 //                String displayName = f.getName();
     272 //                displayName = displayName.substring(0, 1) + displayName.substring(1).toLowerCase(Locale.ROOT);
     273 //
     274 //                System.out.println("colorNameMap.put(" + name + ", \"" + displayName + "\");");
     275 //            }
     276 //        }
     277
     278         colorNameMap.put(Color.TRANSPARENT, "Transparent");
     279         colorNameMap.put(Color.ALICEBLUE, "Alice Blue");
     280         colorNameMap.put(Color.ANTIQUEWHITE, "Antique White");
     281         colorNameMap.put(Color.AQUA, "Aqua");
     282         colorNameMap.put(Color.AQUAMARINE, "Aquamarine");
     283         colorNameMap.put(Color.AZURE, "Azure");
     284         colorNameMap.put(Color.BEIGE, "Beige");
     285         colorNameMap.put(Color.BISQUE, "Bisque");
     286         colorNameMap.put(Color.BLACK, "Black");
     287         colorNameMap.put(Color.BLANCHEDALMOND, "Blanched Almond");
     288         colorNameMap.put(Color.BLUE, "Blue");
     289         colorNameMap.put(Color.BLUEVIOLET, "Blue Violet");
     290         colorNameMap.put(Color.BROWN, "Brown");
     291         colorNameMap.put(Color.BURLYWOOD, "Burlywood");
     292         colorNameMap.put(Color.CADETBLUE, "Cadet Blue");
     293         colorNameMap.put(Color.CHARTREUSE, "Chartreuse");
     294         colorNameMap.put(Color.CHOCOLATE, "Chocolate");
     295         colorNameMap.put(Color.CORAL, "Coral");
     296         colorNameMap.put(Color.CORNFLOWERBLUE, "Cornflower Blue");
     297         colorNameMap.put(Color.CORNSILK, "Cornsilk");
     298         colorNameMap.put(Color.CRIMSON, "Crimson");
     299         colorNameMap.put(Color.CYAN, "Cyan");
     300         colorNameMap.put(Color.DARKBLUE, "Dark Blue");
     301         colorNameMap.put(Color.DARKCYAN, "Dark Cyan");
     302         colorNameMap.put(Color.DARKGOLDENROD, "Dark Goldenrod");
     303         colorNameMap.put(Color.DARKGRAY, "Dark Gray");
     304         colorNameMap.put(Color.DARKGREEN, "Dark Green");
     305         colorNameMap.put(Color.DARKGREY, "Dark Grey");
     306         colorNameMap.put(Color.DARKKHAKI, "Dark Khaki");
     307         colorNameMap.put(Color.DARKMAGENTA, "Dark Magenta");
     308         colorNameMap.put(Color.DARKOLIVEGREEN, "Dark Olive Green");
     309         colorNameMap.put(Color.DARKORANGE, "Dark Orange");
     310         colorNameMap.put(Color.DARKORCHID, "Dark Orchid");
     311         colorNameMap.put(Color.DARKRED, "Dark Red");
     312         colorNameMap.put(Color.DARKSALMON, "Dark Salmon");
     313         colorNameMap.put(Color.DARKSEAGREEN, "Dark Sea Green");
     314         colorNameMap.put(Color.DARKSLATEBLUE, "Dark Slate Blue");
     315         colorNameMap.put(Color.DARKSLATEGRAY, "Dark Slate Gray");
     316         colorNameMap.put(Color.DARKSLATEGREY, "Dark Slate Grey");
     317         colorNameMap.put(Color.DARKTURQUOISE, "Dark Turquoise");
     318         colorNameMap.put(Color.DARKVIOLET, "Dark Violet");
     319         colorNameMap.put(Color.DEEPPINK, "Deep Pink");
     320         colorNameMap.put(Color.DEEPSKYBLUE, "Deep Sky Blue");
     321         colorNameMap.put(Color.DIMGRAY, "Dim Gray");
     322         colorNameMap.put(Color.DIMGREY, "Dim Grey");
     323         colorNameMap.put(Color.DODGERBLUE, "Dodger Blue");
     324         colorNameMap.put(Color.FIREBRICK, "Firebrick");
     325         colorNameMap.put(Color.FLORALWHITE, "Floral White");
     326         colorNameMap.put(Color.FORESTGREEN, "Forest Green");
     327         colorNameMap.put(Color.FUCHSIA, "Fuchsia");
     328         colorNameMap.put(Color.GAINSBORO, "Gainsboro");
     329         colorNameMap.put(Color.GHOSTWHITE, "Ghost White");
     330         colorNameMap.put(Color.GOLD, "Gold");
     331         colorNameMap.put(Color.GOLDENROD, "Goldenrod");
     332         colorNameMap.put(Color.GRAY, "Gray");
     333         colorNameMap.put(Color.GREEN, "Green");
     334         colorNameMap.put(Color.GREENYELLOW, "Green Yellow");
     335         colorNameMap.put(Color.GREY, "Grey");
     336         colorNameMap.put(Color.HONEYDEW, "Honeydew");
     337         colorNameMap.put(Color.HOTPINK, "Hot Pink");
     338         colorNameMap.put(Color.INDIANRED, "Indian Red");
     339         colorNameMap.put(Color.INDIGO, "Indigo");
     340         colorNameMap.put(Color.IVORY, "Ivory");
     341         colorNameMap.put(Color.KHAKI, "Khaki");
     342         colorNameMap.put(Color.LAVENDER, "Lavender");
     343         colorNameMap.put(Color.LAVENDERBLUSH, "Lavender Blush");
     344         colorNameMap.put(Color.LAWNGREEN, "Lawn Green");
     345         colorNameMap.put(Color.LEMONCHIFFON, "Lemon Chiffon");
     346         colorNameMap.put(Color.LIGHTBLUE, "Light Blue");
     347         colorNameMap.put(Color.LIGHTCORAL, "Light Coral");
     348         colorNameMap.put(Color.LIGHTCYAN, "Light Cyan");
     349         colorNameMap.put(Color.LIGHTGOLDENRODYELLOW, "Light Goldenrod Yellow");
     350         colorNameMap.put(Color.LIGHTGRAY, "Light Gray");
     351         colorNameMap.put(Color.LIGHTGREEN, "Light Green");
     352         colorNameMap.put(Color.LIGHTGREY, "Light Grey");
     353         colorNameMap.put(Color.LIGHTPINK, "Light Pink");
     354         colorNameMap.put(Color.LIGHTSALMON, "Light Salmon");
     355         colorNameMap.put(Color.LIGHTSEAGREEN, "Light Sea Green");
     356         colorNameMap.put(Color.LIGHTSKYBLUE, "Light Sky Blue");
     357         colorNameMap.put(Color.LIGHTSLATEGRAY, "Light Slate Gray");
     358         colorNameMap.put(Color.LIGHTSLATEGREY, "Light Slate Grey");
     359         colorNameMap.put(Color.LIGHTSTEELBLUE, "Light Steel Blue");
     360         colorNameMap.put(Color.LIGHTYELLOW, "Light Yellow");
     361         colorNameMap.put(Color.LIME, "Lime");
     362         colorNameMap.put(Color.LIMEGREEN, "Lime Green");
     363         colorNameMap.put(Color.LINEN, "Linen");
     364         colorNameMap.put(Color.MAGENTA, "Magenta");
     365         colorNameMap.put(Color.MAROON, "Maroon");
     366         colorNameMap.put(Color.MEDIUMAQUAMARINE, "Medium Aquamarine");
     367         colorNameMap.put(Color.MEDIUMBLUE, "Medium Blue");
     368         colorNameMap.put(Color.MEDIUMORCHID, "Medium Orchid");
     369         colorNameMap.put(Color.MEDIUMPURPLE, "Medium Purple");
     370         colorNameMap.put(Color.MEDIUMSEAGREEN, "Medium Sea Green");
     371         colorNameMap.put(Color.MEDIUMSLATEBLUE, "Medium Slate Blue");
     372         colorNameMap.put(Color.MEDIUMSPRINGGREEN, "Medium Spring Green");
     373         colorNameMap.put(Color.MEDIUMTURQUOISE, "Medium Turquoise");
     374         colorNameMap.put(Color.MEDIUMVIOLETRED, "Medium Violet Red");
     375         colorNameMap.put(Color.MIDNIGHTBLUE, "Midnight Blue");
     376         colorNameMap.put(Color.MINTCREAM, "Mint Cream");
     377         colorNameMap.put(Color.MISTYROSE, "Misty Rose");
     378         colorNameMap.put(Color.MOCCASIN, "Moccasin");
     379         colorNameMap.put(Color.NAVAJOWHITE, "Navajo White");
     380         colorNameMap.put(Color.NAVY, "Navy");
     381         colorNameMap.put(Color.OLDLACE, "Old Lace");
     382         colorNameMap.put(Color.OLIVE, "Olive");
     383         colorNameMap.put(Color.OLIVEDRAB, "Olive Drab");
     384         colorNameMap.put(Color.ORANGE, "Orange");
     385         colorNameMap.put(Color.ORANGERED, "Orange Red");
     386         colorNameMap.put(Color.ORCHID, "Orchid");
     387         colorNameMap.put(Color.PALEGOLDENROD, "Pale Goldenrod");
     388         colorNameMap.put(Color.PALEGREEN, "Pale Green");
     389         colorNameMap.put(Color.PALETURQUOISE, "Pale Turquoise");
     390         colorNameMap.put(Color.PALEVIOLETRED, "Pale Violet Red");
     391         colorNameMap.put(Color.PAPAYAWHIP, "Papaya Whip");
     392         colorNameMap.put(Color.PEACHPUFF, "Peach Puff");
     393         colorNameMap.put(Color.PERU, "Peru");
     394         colorNameMap.put(Color.PINK, "Pink");
     395         colorNameMap.put(Color.PLUM, "Plum");
     396         colorNameMap.put(Color.POWDERBLUE, "Powder Blue");
     397         colorNameMap.put(Color.PURPLE, "Purple");
     398         colorNameMap.put(Color.RED, "Red");
     399         colorNameMap.put(Color.ROSYBROWN, "Rosy Brown");
     400         colorNameMap.put(Color.ROYALBLUE, "Royal Blue");
     401         colorNameMap.put(Color.SADDLEBROWN, "Saddle Brown");
     402         colorNameMap.put(Color.SALMON, "Salmon");
     403         colorNameMap.put(Color.SANDYBROWN, "Sandy Brown");
     404         colorNameMap.put(Color.SEAGREEN, "Sea Green");
     405         colorNameMap.put(Color.SEASHELL, "Seashell");
     406         colorNameMap.put(Color.SIENNA, "Sienna");
     407         colorNameMap.put(Color.SILVER, "Silver");
     408         colorNameMap.put(Color.SKYBLUE, "Sky Blue");
     409         colorNameMap.put(Color.SLATEBLUE, "Slate Blue");
     410         colorNameMap.put(Color.SLATEGRAY, "Slate Gray");
     411         colorNameMap.put(Color.SLATEGREY, "Slate Grey");
     412         colorNameMap.put(Color.SNOW, "Snow");
     413         colorNameMap.put(Color.SPRINGGREEN, "Spring Green");
     414         colorNameMap.put(Color.STEELBLUE, "Steel Blue");
     415         colorNameMap.put(Color.TAN, "Tan");
     416         colorNameMap.put(Color.TEAL, "Teal");
     417         colorNameMap.put(Color.THISTLE, "Thistle");
     418         colorNameMap.put(Color.TOMATO, "Tomato");
     419         colorNameMap.put(Color.TURQUOISE, "Turquoise");
     420         colorNameMap.put(Color.VIOLET, "Violet");
     421         colorNameMap.put(Color.WHEAT, "Wheat");
     422         colorNameMap.put(Color.WHITE, "White");
     423         colorNameMap.put(Color.WHITESMOKE, "White Smoke");
     424         colorNameMap.put(Color.YELLOW, "Yellow");
     425         colorNameMap.put(Color.YELLOWGREEN, "Yellow Green");
     426     }
     427
     428     static String colorValueToWeb(Color c) {
     429         if (c == null) return null;
     430         String web = colorNameMap.get(c);
     431         if (web == null) {
     432             web = String.format((Locale) null, "%02x%02x%02x", Math.round(c.getRed() * 255), Math.round(c.getGreen() * 255), Math.round(c.getBlue() * 255));
     433         }
     434         return web;
     435     }
     436
     437     @Override protected Node getPopupContent() {
     438         if (popupContent == null) {
     439 //            popupContent = new ColorPalette(colorPicker.getValue(), colorPicker);
     440             popupContent = new ColorPalette(getSkinnable().getValue(), (ColorPicker)getSkinnable());
     441             popupContent.setPopupControl(getPopup());
     442         }
     443        return popupContent;
     444     }
     445
     446     @Override protected void focusLost() {
     447         // do nothing
     448     }
     449
     450     @Override public void show() {
     451         super.show();
     452         final ColorPicker colorPicker = (ColorPicker)getSkinnable();
     453         popupContent.updateSelection(colorPicker.getValue());
     454         popupContent.clearFocus();
     455     }
     456
     457     @Override protected void handleControlPropertyChanged(String p) {
     458         super.handleControlPropertyChanged(p);
     459
     460         if ("SHOWING".equals(p)) {
     461             if (getSkinnable().isShowing()) {
     462                 show();
     463             } else {
     464                 if (!popupContent.isCustomColorDialogShowing()) hide();
     465             }
     466         } else if ("VALUE".equals(p)) {
     467             updateColor();
     468            // Change the current selected color in the grid if ColorPicker value changes
     469             if (popupContent != null) {
     470 //                popupContent.updateSelection(getSkinnable().getValue());
     471             }
     472         }
     473     }
     474     @Override public Node getDisplayNode() {
     475         return displayNode;
     476     }
     477
     478     private void updateColor() {
     479         final ColorPicker colorPicker = (ColorPicker)getSkinnable();
     480         colorRect.setFill(colorPicker.getValue());
     481         if (colorLabelVisible.get()) {
     482             displayNode.setText(colorValueToWeb(colorPicker.getValue()));
     483         } else {
     484             displayNode.setText("");
     485         }
     486     }
     487     public void syncWithAutoUpdate() {
     488         if (!getPopup().isShowing() && getSkinnable().isShowing()) {
     489             // Popup was dismissed. Maybe user clicked outside or typed ESCAPE.
     490             // Make sure ColorPicker button is in sync.
     491             getSkinnable().hide();
     492         }
     493     }
     494
     495     @Override protected void layoutChildren(final double x, final double y,
     496             final double w, final double h) {
     497         updateComboBoxMode();
     498         super.layoutChildren(x,y,w,h);
     499     }
     500
     501     /***************************************************************************
     502     *                                                                         *
     503     *                         picker-color-cell                               *
     504     *                                                                         *
     505     **************************************************************************/
     506
     507     private class PickerColorBox extends StackPane {
     508         @Override protected void layoutChildren() {
     509             final double top = snappedTopInset();
     510             final double left = snappedLeftInset();
     511             final double width = getWidth();
     512             final double height = getHeight();
     513             final double right = snappedRightInset();
     514             final double bottom = snappedBottomInset();
     515             colorRect.setX(snapPosition(colorRectX.get()));
     516             colorRect.setY(snapPosition(colorRectY.get()));
     517             colorRect.setWidth(snapSize(colorRectWidth.get()));
     518             colorRect.setHeight(snapSize(colorRectHeight.get()));
     519             if (getChildren().size() == 2) {
     520                 final ImageView icon = (ImageView) getChildren().get(1);
     521                 Pos childAlignment = StackPane.getAlignment(icon);
     522                 layoutInArea(icon, left, top,
     523                              width - left - right, height - top - bottom,
     524                              0, getMargin(icon),
     525                              childAlignment != null? childAlignment.getHpos() : getAlignment().getHpos(),
     526                              childAlignment != null? childAlignment.getVpos() : getAlignment().getVpos());
     527                 colorRect.setLayoutX(icon.getLayoutX());
     528                 colorRect.setLayoutY(icon.getLayoutY());
     529             } else {
     530                 Pos childAlignment = StackPane.getAlignment(colorRect);
     531                 layoutInArea(colorRect, left, top,
     532                              width - left - right, height - top - bottom,
     533                              0, getMargin(colorRect),
     534                              childAlignment != null? childAlignment.getHpos() : getAlignment().getHpos(),
     535                              childAlignment != null? childAlignment.getVpos() : getAlignment().getVpos());
     536             }
     537         }
     538     }
     539
     540     /***************************************************************************
     541     *                                                                         *
     542     *                         Stylesheet Handling                             *
     543     *                                                                         *
     544     **************************************************************************/
     545
     546      private static class StyleableProperties {
     547         private static final CssMetaData<ColorPicker,Boolean> COLOR_LABEL_VISIBLE =
     548                 new CssMetaData<ColorPicker,Boolean>("-fx-color-label-visible",
     549                 BooleanConverter.getInstance(), Boolean.TRUE) {
     550
     551             @Override public boolean isSettable(ColorPicker n) {
     552                 final ColorPickerSkin skin = (ColorPickerSkin) n.getSkin();
     553                 return skin.colorLabelVisible == null || !skin.colorLabelVisible.isBound();
     554             }
     555
     556             @Override public StyleableProperty<Boolean> getStyleableProperty(ColorPicker n) {
     557                 final ColorPickerSkin skin = (ColorPickerSkin) n.getSkin();
     558                 return (StyleableProperty<Boolean>)skin.colorLabelVisible;
     559             }
     560         };
     561         private static final CssMetaData<ColorPicker,Number> COLOR_RECT_WIDTH =
     562                 new CssMetaData<ColorPicker,Number>("-fx-color-rect-width", SizeConverter.getInstance(), 12d) {
     563                     @Override public boolean isSettable(ColorPicker n) {
     564                         final ColorPickerSkin skin = (ColorPickerSkin) n.getSkin();
     565                         return !skin.colorRectWidth.isBound();
     566                     }
     567                     @Override public StyleableProperty<Number> getStyleableProperty(ColorPicker n) {
     568                         final ColorPickerSkin skin = (ColorPickerSkin) n.getSkin();
     569                         return skin.colorRectWidth;
     570                     }
     571                 };
     572         private static final CssMetaData<ColorPicker,Number> COLOR_RECT_HEIGHT =
     573                 new CssMetaData<ColorPicker,Number>("-fx-color-rect-height", SizeConverter.getInstance(), 12d) {
     574                     @Override public boolean isSettable(ColorPicker n) {
     575                         final ColorPickerSkin skin = (ColorPickerSkin) n.getSkin();
     576                         return !skin.colorRectHeight.isBound();
     577                     }
     578                     @Override public StyleableProperty<Number> getStyleableProperty(ColorPicker n) {
     579                         final ColorPickerSkin skin = (ColorPickerSkin) n.getSkin();
     580                         return skin.colorRectHeight;
     581                     }
     582                 };
     583         private static final CssMetaData<ColorPicker,Number> COLOR_RECT_X =
     584                 new CssMetaData<ColorPicker,Number>("-fx-color-rect-x", SizeConverter.getInstance(), 0) {
     585                     @Override public boolean isSettable(ColorPicker n) {
     586                         final ColorPickerSkin skin = (ColorPickerSkin) n.getSkin();
     587                         return !skin.colorRectX.isBound();
     588                     }
     589                     @Override public StyleableProperty<Number> getStyleableProperty(ColorPicker n) {
     590                         final ColorPickerSkin skin = (ColorPickerSkin) n.getSkin();
     591                         return skin.colorRectX;
     592                     }
     593                 };
     594         private static final CssMetaData<ColorPicker,Number> COLOR_RECT_Y =
     595                 new CssMetaData<ColorPicker,Number>("-fx-color-rect-y", SizeConverter.getInstance(), 0) {
     596                     @Override public boolean isSettable(ColorPicker n) {
     597                         final ColorPickerSkin skin = (ColorPickerSkin) n.getSkin();
     598                         return !skin.colorRectY.isBound();
     599                     }
     600                     @Override public StyleableProperty<Number> getStyleableProperty(ColorPicker n) {
     601                         final ColorPickerSkin skin = (ColorPickerSkin) n.getSkin();
     602                         return skin.colorRectY;
     603                     }
     604                 };
     605         private static final CssMetaData<ColorPicker,String> GRAPHIC =
     606             new CssMetaData<ColorPicker,String>("-fx-graphic", StringConverter.getInstance()) {
     607                 @Override public boolean isSettable(ColorPicker n) {
     608                     final ColorPickerSkin skin = (ColorPickerSkin) n.getSkin();
     609                     return !skin.imageUrl.isBound();
     610                 }
     611                 @Override public StyleableProperty<String> getStyleableProperty(ColorPicker n) {
     612                     final ColorPickerSkin skin = (ColorPickerSkin) n.getSkin();
     613                     return skin.imageUrl;
     614                 }
     615             };
     616         private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES;
     617         static {
     618             final List<CssMetaData<? extends Styleable, ?>> styleables =
     619                 new ArrayList<CssMetaData<? extends Styleable, ?>>(ComboBoxBaseSkin.getClassCssMetaData());
     620             styleables.add(COLOR_LABEL_VISIBLE);
     621             styleables.add(COLOR_RECT_WIDTH);
     622             styleables.add(COLOR_RECT_HEIGHT);
     623             styleables.add(COLOR_RECT_X);
     624             styleables.add(COLOR_RECT_Y);
     625             styleables.add(GRAPHIC);
     626             STYLEABLES = Collections.unmodifiableList(styleables);
     627         }
     628     }
     629
     630     /**
     631      * @return The CssMetaData associated with this class, which may include the
     632      * CssMetaData of its super classes.
     633      */
     634     public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() {
     635         return StyleableProperties.STYLEABLES;
     636     }
     637
     638     /**
     639      * {@inheritDoc}
     640      */
     641     @Override
     642     public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() {
     643         return getClassCssMetaData();
     644     }
     645
     646 }