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

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

*** 21,56 **** * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ ! package com.sun.javafx.scene.control.skin; import com.sun.javafx.css.StyleManager; import javafx.beans.property.StringProperty; import javafx.css.StyleOrigin; import javafx.css.StyleableBooleanProperty; import javafx.css.CssMetaData; ! import com.sun.javafx.css.converters.BooleanConverter; import java.util.ArrayList; import java.util.Collections; import java.util.List; - import java.util.Locale; import javafx.css.StyleableDoubleProperty; import javafx.css.StyleableStringProperty; import javafx.geometry.Pos; import javafx.scene.Node; import javafx.scene.image.ImageView; import javafx.scene.layout.StackPane; import javafx.scene.shape.Rectangle; ! import com.sun.javafx.css.converters.SizeConverter; ! import com.sun.javafx.css.converters.StringConverter; import com.sun.javafx.scene.control.behavior.ColorPickerBehavior; import java.util.HashMap; import java.util.Map; --- 21,59 ---- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ ! package javafx.scene.control.skin; import com.sun.javafx.css.StyleManager; + import com.sun.javafx.scene.control.Properties; + import com.sun.javafx.scene.control.behavior.ComboBoxBaseBehavior; + import com.sun.javafx.scene.control.skin.Utils; import javafx.beans.property.StringProperty; import javafx.css.StyleOrigin; import javafx.css.StyleableBooleanProperty; import javafx.css.CssMetaData; ! import javafx.css.converter.BooleanConverter; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javafx.css.StyleableDoubleProperty; import javafx.css.StyleableStringProperty; import javafx.geometry.Pos; import javafx.scene.Node; + import javafx.scene.control.Control; import javafx.scene.image.ImageView; import javafx.scene.layout.StackPane; import javafx.scene.shape.Rectangle; ! import javafx.css.converter.SizeConverter; ! import javafx.css.converter.StringConverter; import com.sun.javafx.scene.control.behavior.ColorPickerBehavior; import java.util.HashMap; import java.util.Map;
*** 58,84 **** import javafx.scene.control.TextField; import javafx.beans.property.BooleanProperty; import javafx.beans.value.WritableValue; import javafx.css.Styleable; import javafx.css.StyleableProperty; - import javafx.event.ActionEvent; import javafx.scene.control.Label; import javafx.scene.paint.Color; - import com.sun.javafx.scene.control.skin.resources.ControlResources; - import static javafx.scene.paint.Color.*; /** * */ public class ColorPickerSkin extends ComboBoxPopupControl<Color> { private Label displayNode; private StackPane pickerColorBox; private Rectangle colorRect; private ColorPalette popupContent; BooleanProperty colorLabelVisible = new StyleableBooleanProperty(true) { @Override public void invalidated() { if (displayNode != null) { if (colorLabelVisible.get()) { displayNode.setText(colorDisplayName(((ColorPicker)getSkinnable()).getValue())); --- 61,147 ---- import javafx.scene.control.TextField; import javafx.beans.property.BooleanProperty; import javafx.beans.value.WritableValue; import javafx.css.Styleable; import javafx.css.StyleableProperty; import javafx.scene.control.Label; import javafx.scene.paint.Color; import static javafx.scene.paint.Color.*; /** + * Default skin implementation for the {@link ColorPicker} control. * + * @see ColorPicker + * @since 9 */ public class ColorPickerSkin extends ComboBoxPopupControl<Color> { + /*************************************************************************** + * * + * Private fields * + * * + **************************************************************************/ + private Label displayNode; private StackPane pickerColorBox; private Rectangle colorRect; private ColorPalette popupContent; + + private final ColorPickerBehavior behavior; + + + + /*************************************************************************** + * * + * Constructors * + * * + **************************************************************************/ + + /** + * Creates a new ColorPickerSkin instance, installing the necessary child + * nodes into the Control {@link Control#getChildren() children} list, as + * well as the necessary input mappings for handling key, mouse, etc events. + * + * @param control The control that this skin should be installed onto. + */ + public ColorPickerSkin(final ColorPicker control) { + super(control); + + // install default input map for the control + this.behavior = new ColorPickerBehavior(control); + // control.setInputMap(behavior.getInputMap()); + + updateComboBoxMode(); + registerChangeListener(control.valueProperty(), e -> updateColor()); + + // create displayNode + displayNode = new Label(); + displayNode.getStyleClass().add("color-picker-label"); + displayNode.setManaged(false); + + // label graphic + pickerColorBox = new PickerColorBox(); + pickerColorBox.getStyleClass().add("picker-color"); + colorRect = new Rectangle(12, 12); + colorRect.getStyleClass().add("picker-color-rect"); + + updateColor(); + + pickerColorBox.getChildren().add(colorRect); + displayNode.setGraphic(pickerColorBox); + } + + + + /*************************************************************************** + * * + * Properties * + * * + **************************************************************************/ + + // --- color label visible BooleanProperty colorLabelVisible = new StyleableBooleanProperty(true) { @Override public void invalidated() { if (displayNode != null) { if (colorLabelVisible.get()) { displayNode.setText(colorDisplayName(((ColorPicker)getSkinnable()).getValue()));
*** 95,105 **** } @Override public CssMetaData<ColorPicker,Boolean> getCssMetaData() { return StyleableProperties.COLOR_LABEL_VISIBLE; } }; ! public StringProperty imageUrlProperty() { return imageUrl; } private final StyleableStringProperty imageUrl = new StyleableStringProperty() { @Override public void applyStyle(StyleOrigin origin, String v) { super.applyStyle(origin, v); if (v == null) { // remove old image view --- 158,170 ---- } @Override public CssMetaData<ColorPicker,Boolean> getCssMetaData() { return StyleableProperties.COLOR_LABEL_VISIBLE; } }; ! ! // --- image url ! private final StringProperty imageUrlProperty() { return imageUrl; } private final StyleableStringProperty imageUrl = new StyleableStringProperty() { @Override public void applyStyle(StyleOrigin origin, String v) { super.applyStyle(origin, v); if (v == null) { // remove old image view
*** 121,130 **** --- 186,197 ---- } @Override public CssMetaData<ColorPicker,String> getCssMetaData() { return StyleableProperties.GRAPHIC; } }; + + // --- color rect width private final StyleableDoubleProperty colorRectWidth = new StyleableDoubleProperty(12) { @Override protected void invalidated() { if(pickerColorBox!=null) pickerColorBox.requestLayout(); } @Override public CssMetaData<ColorPicker,Number> getCssMetaData() {
*** 135,144 **** --- 202,213 ---- } @Override public String getName() { return "colorRectWidth"; } }; + + // --- color rect height private final StyleableDoubleProperty colorRectHeight = new StyleableDoubleProperty(12) { @Override protected void invalidated() { if(pickerColorBox!=null) pickerColorBox.requestLayout(); } @Override public CssMetaData<ColorPicker,Number> getCssMetaData() {
*** 149,158 **** --- 218,229 ---- } @Override public String getName() { return "colorRectHeight"; } }; + + // --- color rect X private final StyleableDoubleProperty colorRectX = new StyleableDoubleProperty(0) { @Override protected void invalidated() { if(pickerColorBox!=null) pickerColorBox.requestLayout(); } @Override public CssMetaData<ColorPicker,Number> getCssMetaData() {
*** 163,172 **** --- 234,245 ---- } @Override public String getName() { return "colorRectX"; } }; + + // --- color rect Y private final StyleableDoubleProperty colorRectY = new StyleableDoubleProperty(0) { @Override protected void invalidated() { if(pickerColorBox!=null) pickerColorBox.requestLayout(); } @Override public CssMetaData<ColorPicker,Number> getCssMetaData() {
*** 178,263 **** @Override public String getName() { return "colorRectY"; } }; - public ColorPickerSkin(final ColorPicker colorPicker) { - super(colorPicker, new ColorPickerBehavior(colorPicker)); - updateComboBoxMode(); - registerChangeListener(colorPicker.valueProperty(), "VALUE"); - // create displayNode - displayNode = new Label(); - displayNode.getStyleClass().add("color-picker-label"); - displayNode.setManaged(false); ! // label graphic ! pickerColorBox = new PickerColorBox(); ! pickerColorBox.getStyleClass().add("picker-color"); ! colorRect = new Rectangle(12, 12); ! colorRect.getStyleClass().add("picker-color-rect"); ! updateColor(); ! pickerColorBox.getChildren().add(colorRect); ! displayNode.setGraphic(pickerColorBox); } ! @Override protected double computePrefWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) { if (!colorLabelVisible.get()) { return super.computePrefWidth(height, topInset, rightInset, bottomInset, leftInset); } String displayNodeText = displayNode.getText(); double width = 0; for (String name : colorNameMap.values()) { displayNode.setText(name); width = Math.max(width, super.computePrefWidth(height, topInset, rightInset, bottomInset, leftInset)); } ! displayNode.setText(formatHexString(Color.BLACK)); // #000000 width = Math.max(width, super.computePrefWidth(height, topInset, rightInset, bottomInset, leftInset)); displayNode.setText(displayNodeText); return width; } private void updateComboBoxMode() { List<String> styleClass = getSkinnable().getStyleClass(); if (styleClass.contains(ColorPicker.STYLE_CLASS_BUTTON)) { setMode(ComboBoxMode.BUTTON); } else if (styleClass.contains(ColorPicker.STYLE_CLASS_SPLIT_BUTTON)) { setMode(ComboBoxMode.SPLITBUTTON); } } ! private static final Map<Color, String> colorNameMap = new HashMap<Color, String>(24); ! private static final Map<Color, String> cssNameMap = new HashMap<Color, String>(139); static { // Translatable display names for the most common colors ! colorNameMap.put(TRANSPARENT, getString("colorName.transparent")); ! colorNameMap.put(BLACK, getString("colorName.black")); ! colorNameMap.put(BLUE, getString("colorName.blue")); ! colorNameMap.put(CYAN, getString("colorName.cyan")); ! colorNameMap.put(DARKBLUE, getString("colorName.darkblue")); ! colorNameMap.put(DARKCYAN, getString("colorName.darkcyan")); ! colorNameMap.put(DARKGRAY, getString("colorName.darkgray")); ! colorNameMap.put(DARKGREEN, getString("colorName.darkgreen")); ! colorNameMap.put(DARKMAGENTA, getString("colorName.darkmagenta")); ! colorNameMap.put(DARKRED, getString("colorName.darkred")); ! colorNameMap.put(GRAY, getString("colorName.gray")); ! colorNameMap.put(GREEN, getString("colorName.green")); ! colorNameMap.put(LIGHTBLUE, getString("colorName.lightblue")); ! colorNameMap.put(LIGHTCYAN, getString("colorName.lightcyan")); ! colorNameMap.put(LIGHTGRAY, getString("colorName.lightgray")); ! colorNameMap.put(LIGHTGREEN, getString("colorName.lightgreen")); ! colorNameMap.put(LIGHTYELLOW, getString("colorName.lightyellow")); ! colorNameMap.put(MAGENTA, getString("colorName.magenta")); ! colorNameMap.put(MEDIUMBLUE, getString("colorName.mediumblue")); ! colorNameMap.put(ORANGE, getString("colorName.orange")); ! colorNameMap.put(PINK, getString("colorName.pink")); ! colorNameMap.put(RED, getString("colorName.red")); ! colorNameMap.put(WHITE, getString("colorName.white")); ! colorNameMap.put(YELLOW, getString("colorName.yellow")); // CSS names. // Note that synonyms (such as "grey") have been removed here, // since a color can be presented with only one name in this // skin. If a reverse map is created for parsing names in the --- 251,378 ---- @Override public String getName() { return "colorRectY"; } }; ! /*************************************************************************** ! * * ! * Public API * ! * * ! **************************************************************************/ ! /** {@inheritDoc} */ ! @Override public void dispose() { ! super.dispose(); ! if (behavior != null) { ! behavior.dispose(); ! } } ! /** {@inheritDoc} */ @Override protected double computePrefWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) { if (!colorLabelVisible.get()) { return super.computePrefWidth(height, topInset, rightInset, bottomInset, leftInset); } String displayNodeText = displayNode.getText(); double width = 0; for (String name : colorNameMap.values()) { displayNode.setText(name); width = Math.max(width, super.computePrefWidth(height, topInset, rightInset, bottomInset, leftInset)); } ! displayNode.setText(Utils.formatHexString(Color.BLACK)); // #000000 width = Math.max(width, super.computePrefWidth(height, topInset, rightInset, bottomInset, leftInset)); displayNode.setText(displayNodeText); return width; } + /** {@inheritDoc} */ + @Override protected Node getPopupContent() { + if (popupContent == null) { + // popupContent = new ColorPalette(colorPicker.getValue(), colorPicker); + popupContent = new ColorPalette((ColorPicker)getSkinnable()); + popupContent.setPopupControl(getPopup()); + } + return popupContent; + } + + /** {@inheritDoc} */ + @Override public void show() { + super.show(); + final ColorPicker colorPicker = (ColorPicker)getSkinnable(); + popupContent.updateSelection(colorPicker.getValue()); + } + + /** {@inheritDoc} */ + @Override public Node getDisplayNode() { + return displayNode; + } + + /** {@inheritDoc} */ + @Override protected void layoutChildren(final double x, final double y, + final double w, final double h) { + updateComboBoxMode(); + super.layoutChildren(x, y, w, h); + } + + + + /*************************************************************************** + * * + * Private implementation * + * * + **************************************************************************/ + + /** {@inheritDoc} */ + @Override void focusLost() { + // do nothing + } + + /** {@inheritDoc} */ + @Override ComboBoxBaseBehavior getBehavior() { + return behavior; + } + private void updateComboBoxMode() { List<String> styleClass = getSkinnable().getStyleClass(); if (styleClass.contains(ColorPicker.STYLE_CLASS_BUTTON)) { setMode(ComboBoxMode.BUTTON); } else if (styleClass.contains(ColorPicker.STYLE_CLASS_SPLIT_BUTTON)) { setMode(ComboBoxMode.SPLITBUTTON); } } ! private static final Map<Color, String> colorNameMap = new HashMap<>(24); ! private static final Map<Color, String> cssNameMap = new HashMap<>(139); static { // Translatable display names for the most common colors ! colorNameMap.put(TRANSPARENT, Properties.getColorPickerString("colorName.transparent")); ! colorNameMap.put(BLACK, Properties.getColorPickerString("colorName.black")); ! colorNameMap.put(BLUE, Properties.getColorPickerString("colorName.blue")); ! colorNameMap.put(CYAN, Properties.getColorPickerString("colorName.cyan")); ! colorNameMap.put(DARKBLUE, Properties.getColorPickerString("colorName.darkblue")); ! colorNameMap.put(DARKCYAN, Properties.getColorPickerString("colorName.darkcyan")); ! colorNameMap.put(DARKGRAY, Properties.getColorPickerString("colorName.darkgray")); ! colorNameMap.put(DARKGREEN, Properties.getColorPickerString("colorName.darkgreen")); ! colorNameMap.put(DARKMAGENTA, Properties.getColorPickerString("colorName.darkmagenta")); ! colorNameMap.put(DARKRED, Properties.getColorPickerString("colorName.darkred")); ! colorNameMap.put(GRAY, Properties.getColorPickerString("colorName.gray")); ! colorNameMap.put(GREEN, Properties.getColorPickerString("colorName.green")); ! colorNameMap.put(LIGHTBLUE, Properties.getColorPickerString("colorName.lightblue")); ! colorNameMap.put(LIGHTCYAN, Properties.getColorPickerString("colorName.lightcyan")); ! colorNameMap.put(LIGHTGRAY, Properties.getColorPickerString("colorName.lightgray")); ! colorNameMap.put(LIGHTGREEN, Properties.getColorPickerString("colorName.lightgreen")); ! colorNameMap.put(LIGHTYELLOW, Properties.getColorPickerString("colorName.lightyellow")); ! colorNameMap.put(MAGENTA, Properties.getColorPickerString("colorName.magenta")); ! colorNameMap.put(MEDIUMBLUE, Properties.getColorPickerString("colorName.mediumblue")); ! colorNameMap.put(ORANGE, Properties.getColorPickerString("colorName.orange")); ! colorNameMap.put(PINK, Properties.getColorPickerString("colorName.pink")); ! colorNameMap.put(RED, Properties.getColorPickerString("colorName.red")); ! colorNameMap.put(WHITE, Properties.getColorPickerString("colorName.white")); ! colorNameMap.put(YELLOW, Properties.getColorPickerString("colorName.yellow")); // CSS names. // Note that synonyms (such as "grey") have been removed here, // since a color can be presented with only one name in this // skin. If a reverse map is created for parsing names in the
*** 406,416 **** static String colorDisplayName(Color c) { if (c != null) { String displayName = colorNameMap.get(c); if (displayName == null) { ! displayName = formatHexString(c); } return displayName; } else { return null; } --- 521,531 ---- static String colorDisplayName(Color c) { if (c != null) { String displayName = colorNameMap.get(c); if (displayName == null) { ! displayName = Utils.formatHexString(c); } return displayName; } else { return null; }
*** 422,432 **** String displayName = colorNameMap.get(c); if (displayName != null) { tooltipStr += displayName + " "; } ! tooltipStr += formatHexString(c); String cssName = cssNameMap.get(c); if (cssName != null) { tooltipStr += " (css: " + cssName + ")"; } --- 537,547 ---- String displayName = colorNameMap.get(c); if (displayName != null) { tooltipStr += displayName + " "; } ! tooltipStr += Utils.formatHexString(c); String cssName = cssNameMap.get(c); if (cssName != null) { tooltipStr += " (css: " + cssName + ")"; }
*** 434,520 **** } else { return null; } } - static String formatHexString(Color c) { - if (c != null) { - return String.format((Locale) null, "#%02x%02x%02x", - Math.round(c.getRed() * 255), - Math.round(c.getGreen() * 255), - Math.round(c.getBlue() * 255)); - } else { - return null; - } - } - - @Override protected Node getPopupContent() { - if (popupContent == null) { - // popupContent = new ColorPalette(colorPicker.getValue(), colorPicker); - popupContent = new ColorPalette((ColorPicker)getSkinnable()); - popupContent.setPopupControl(getPopup()); - } - return popupContent; - } - - @Override protected void focusLost() { - // do nothing - } - - @Override public void show() { - super.show(); - final ColorPicker colorPicker = (ColorPicker)getSkinnable(); - popupContent.updateSelection(colorPicker.getValue()); - } - - @Override protected void handleControlPropertyChanged(String p) { - super.handleControlPropertyChanged(p); - - if ("SHOWING".equals(p)) { - if (getSkinnable().isShowing()) { - show(); - } else { - if (!popupContent.isCustomColorDialogShowing()) hide(); - } - } else if ("VALUE".equals(p)) { - updateColor(); - // Change the current selected color in the grid if ColorPicker value changes - if (popupContent != null) { - // popupContent.updateSelection(getSkinnable().getValue()); - } - } - } - @Override public Node getDisplayNode() { - return displayNode; - } - private void updateColor() { final ColorPicker colorPicker = (ColorPicker)getSkinnable(); colorRect.setFill(colorPicker.getValue()); if (colorLabelVisible.get()) { displayNode.setText(colorDisplayName(colorPicker.getValue())); } else { displayNode.setText(""); } } - public void syncWithAutoUpdate() { - if (!getPopup().isShowing() && getSkinnable().isShowing()) { - // Popup was dismissed. Maybe user clicked outside or typed ESCAPE. - // Make sure ColorPicker button is in sync. - getSkinnable().hide(); - } - } - @Override protected void layoutChildren(final double x, final double y, - final double w, final double h) { - updateComboBoxMode(); - super.layoutChildren(x,y,w,h); - } - static String getString(String key) { - return ControlResources.getString("ColorPicker."+key); - } /*************************************************************************** * * * picker-color-cell * * * --- 549,569 ----
*** 642,652 **** STYLEABLES = Collections.unmodifiableList(styleables); } } /** ! * @return The CssMetaData associated with this class, which may include the * CssMetaData of its super classes. */ public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() { return StyleableProperties.STYLEABLES; } --- 691,701 ---- STYLEABLES = Collections.unmodifiableList(styleables); } } /** ! * Returns the CssMetaData associated with this class, which may include the * CssMetaData of its super classes. */ public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() { return StyleableProperties.STYLEABLES; }
*** 657,672 **** @Override public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() { return getClassCssMetaData(); } @Override protected javafx.util.StringConverter<Color> getConverter() { return null; } /** ! * ColorPicker does not use a main text field. */ @Override protected TextField getEditor() { return null; } } --- 706,723 ---- @Override public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() { return getClassCssMetaData(); } + /** {@inheritDoc} */ @Override protected javafx.util.StringConverter<Color> getConverter() { return null; } /** ! * ColorPicker does not use a main text field, so this method has been ! * overridden to return null. */ @Override protected TextField getEditor() { return null; } }