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 }
|