/* * Copyright (c) 2013 by Gerrit Grunwald * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package eu.hansolo.enzo.onoffswitch; import com.sun.javafx.css.converters.PaintConverter; import eu.hansolo.enzo.onoffswitch.skin.OnOffSwitchSkin; import javafx.beans.property.BooleanProperty; import javafx.beans.property.BooleanPropertyBase; import javafx.beans.property.ObjectProperty; import javafx.beans.property.ObjectPropertyBase; import javafx.css.CssMetaData; import javafx.css.PseudoClass; import javafx.css.Styleable; import javafx.css.StyleableObjectProperty; import javafx.css.StyleableProperty; import javafx.event.EventHandler; import javafx.event.EventType; import javafx.scene.control.Control; import javafx.scene.control.Skin; import javafx.scene.control.Toggle; import javafx.scene.control.ToggleGroup; import javafx.scene.paint.Color; import javafx.scene.paint.Paint; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * User: hansolo * Date: 08.10.13 * Time: 07:49 */ public class OnOffSwitch extends Control implements Toggle { public static final Color DEFAULT_SWITCH_COLOR = Color.WHITE; public static final Color DEFAULT_TEXT_COLOR_ON = Color.WHITE; public static final Color DEFAULT_TEXT_COLOR_OFF = Color.WHITE; public static final Color DEFAULT_THUMB_COLOR = Color.WHITE; private static final PseudoClass PSEUDO_CLASS_SELECTED = PseudoClass.getPseudoClass("selected"); // CSS styleable properties private ObjectProperty<Paint> switchColor; private ObjectProperty<Paint> textColorOn; private ObjectProperty<Paint> textColorOff; private ObjectProperty<Paint> thumbColor; private ObjectProperty<ToggleGroup> toggleGroup; // CSS pseudo classes private BooleanProperty selected; // ******************** Constructors ************************************** public OnOffSwitch() { getStyleClass().setAll("on-off-switch"); } // ******************** Methods ******************************************* public final boolean isSelected() { return null == selected ? false : selected.get(); } public final void setSelected(final boolean SELECTED) { selectedProperty().set(SELECTED); } public final BooleanProperty selectedProperty() { if (null == selected) { selected = new BooleanPropertyBase() { @Override protected void invalidated() { if (null != getToggleGroup()) { if (get()) { getToggleGroup().selectToggle(OnOffSwitch.this); } else if (getToggleGroup().getSelectedToggle() == OnOffSwitch.this) { getToggleGroup().selectToggle(null); } } if (selected.get()) { fireSelectionEvent(new SelectionEvent(this, null, SelectionEvent.SELECT)); } else { fireSelectionEvent(new SelectionEvent(this, null, SelectionEvent.DESELECT)); } pseudoClassStateChanged(PSEUDO_CLASS_SELECTED, get()); } @Override public Object getBean() { return this; } @Override public String getName() { return "on"; } }; } return selected; } public final ToggleGroup getToggleGroup() { return null == toggleGroup ? null : toggleGroup.get(); } public final void setToggleGroup(ToggleGroup value) { toggleGroupProperty().set(value); } public final ObjectProperty<ToggleGroup> toggleGroupProperty() { if (null == toggleGroup) { toggleGroup = new ObjectPropertyBase<ToggleGroup>() { private ToggleGroup oldToggleGroup; @Override protected void invalidated() { final ToggleGroup toggleGroup = get(); if (null != toggleGroup && !toggleGroup.getToggles().contains(OnOffSwitch.this)) { if (oldToggleGroup != null) { oldToggleGroup.getToggles().remove(OnOffSwitch.this); } toggleGroup.getToggles().add(OnOffSwitch.this); } else if (null == toggleGroup) { oldToggleGroup.getToggles().remove(OnOffSwitch.this); } oldToggleGroup = toggleGroup; } @Override public Object getBean() { return OnOffSwitch.this; } @Override public String getName() { return "toggleGroup"; } }; } return toggleGroup; } // ******************** CSS Stylable Properties *************************** public final Paint getSwitchColor() { return null == switchColor ? DEFAULT_SWITCH_COLOR : switchColor.get(); } public final void setSwitchColor(Paint value) { switchColorProperty().set(value); } public final ObjectProperty<Paint> switchColorProperty() { if (null == switchColor) { switchColor = new StyleableObjectProperty<Paint>(DEFAULT_SWITCH_COLOR) { @Override public CssMetaData getCssMetaData() { return StyleableProperties.SWITCH_COLOR; } @Override public Object getBean() { return OnOffSwitch.this; } @Override public String getName() { return "switchColor"; } }; } return switchColor; } public final Paint getTextColorOn() { return null == textColorOn ? DEFAULT_TEXT_COLOR_ON : textColorOn.get(); } public final void setTextColorOn(Paint value) { textColorOnProperty().set(value); } public final ObjectProperty<Paint> textColorOnProperty() { if (null == textColorOn) { textColorOn = new StyleableObjectProperty<Paint>(DEFAULT_TEXT_COLOR_ON) { @Override public CssMetaData getCssMetaData() { return StyleableProperties.TEXT_COLOR_ON; } @Override public Object getBean() { return OnOffSwitch.this; } @Override public String getName() { return "switchColor"; } }; } return textColorOn; } public final Paint getTextColorOff() { return null == textColorOff ? DEFAULT_TEXT_COLOR_OFF : textColorOff.get(); } public final void setTextColorOff(Paint value) { textColorOffProperty().set(value); } public final ObjectProperty<Paint> textColorOffProperty() { if (null == textColorOff) { textColorOff = new StyleableObjectProperty<Paint>(DEFAULT_TEXT_COLOR_OFF) { @Override public CssMetaData getCssMetaData() { return StyleableProperties.TEXT_COLOR_OFF; } @Override public Object getBean() { return OnOffSwitch.this; } @Override public String getName() { return "textColorOff"; } }; } return textColorOff; } public final Paint getThumbColor() { return null == thumbColor ? DEFAULT_THUMB_COLOR : thumbColor.get(); } public final void setThumbColor(Paint value) { thumbColorProperty().set(value); } public final ObjectProperty<Paint> thumbColorProperty() { if (null == thumbColor) { thumbColor = new StyleableObjectProperty<Paint>(DEFAULT_THUMB_COLOR) { @Override public CssMetaData getCssMetaData() { return StyleableProperties.THUMB_COLOR; } @Override public Object getBean() { return OnOffSwitch.this; } @Override public String getName() { return "thumbColor"; } }; } return thumbColor; } // ******************** Style related ************************************* @Override protected Skin createDefaultSkin() { return new OnOffSwitchSkin(this); } @Override protected String getUserAgentStylesheet() { return getClass().getResource("onoffswitch.css").toExternalForm(); } private static class StyleableProperties { private static final CssMetaData<OnOffSwitch, Paint> SWITCH_COLOR = new CssMetaData<OnOffSwitch, Paint>("-switch-color", PaintConverter.getInstance(), DEFAULT_SWITCH_COLOR) { @Override public boolean isSettable(OnOffSwitch onOffSwitch) { return null == onOffSwitch.switchColor || !onOffSwitch.switchColor.isBound(); } @Override public StyleableProperty<Paint> getStyleableProperty(OnOffSwitch onOffSwitch) { return (StyleableProperty) onOffSwitch.switchColorProperty(); } @Override public Color getInitialValue(OnOffSwitch onOffSwitch) { return (Color) onOffSwitch.getSwitchColor(); } }; private static final CssMetaData<OnOffSwitch, Paint> TEXT_COLOR_ON = new CssMetaData<OnOffSwitch, Paint>("-text-color-on", PaintConverter.getInstance(), DEFAULT_TEXT_COLOR_ON) { @Override public boolean isSettable(OnOffSwitch onOffSwitch) { return null == onOffSwitch.textColorOn || !onOffSwitch.textColorOn.isBound(); } @Override public StyleableProperty<Paint> getStyleableProperty(OnOffSwitch onOffSwitch) { return (StyleableProperty) onOffSwitch.textColorOnProperty(); } @Override public Color getInitialValue(OnOffSwitch onOffSwitch) { return (Color) onOffSwitch.getTextColorOn(); } }; private static final CssMetaData<OnOffSwitch, Paint> TEXT_COLOR_OFF = new CssMetaData<OnOffSwitch, Paint>("-text-color-off", PaintConverter.getInstance(), DEFAULT_TEXT_COLOR_OFF) { @Override public boolean isSettable(OnOffSwitch onOffSwitch) { return null == onOffSwitch.textColorOff || !onOffSwitch.textColorOff.isBound(); } @Override public StyleableProperty<Paint> getStyleableProperty(OnOffSwitch onOffSwitch) { return (StyleableProperty) onOffSwitch.textColorOffProperty(); } @Override public Color getInitialValue(OnOffSwitch onOffSwitch) { return (Color) onOffSwitch.getTextColorOff(); } }; private static final CssMetaData<OnOffSwitch, Paint> THUMB_COLOR = new CssMetaData<OnOffSwitch, Paint>("-thumb-color", PaintConverter.getInstance(), DEFAULT_THUMB_COLOR) { @Override public boolean isSettable(OnOffSwitch onOffSwitch) { return null == onOffSwitch.thumbColor || !onOffSwitch.thumbColor.isBound(); } @Override public StyleableProperty<Paint> getStyleableProperty(OnOffSwitch onOffSwitch) { return (StyleableProperty) onOffSwitch.thumbColorProperty(); } @Override public Color getInitialValue(OnOffSwitch onOffSwitch) { return (Color) onOffSwitch.getThumbColor(); } }; private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES; static { final List<CssMetaData<? extends Styleable, ?>> styleables = new ArrayList<>(Control.getClassCssMetaData()); Collections.addAll(styleables, SWITCH_COLOR, TEXT_COLOR_ON, TEXT_COLOR_OFF, THUMB_COLOR ); STYLEABLES = Collections.unmodifiableList(styleables); } } public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() { return StyleableProperties.STYLEABLES; } @Override public List<CssMetaData<? extends Styleable, ?>> getControlCssMetaData() { return getClassCssMetaData(); } // ******************** Event handling************************************* public final ObjectProperty<EventHandler<SelectionEvent>> onSelectProperty() { return onSelect; } public final void setOnSelect(EventHandler<SelectionEvent> value) { onSelectProperty().set(value); } public final EventHandler<SelectionEvent> getOnSelect() { return onSelectProperty().get(); } private ObjectProperty<EventHandler<SelectionEvent>> onSelect = new ObjectPropertyBase<EventHandler<SelectionEvent>>() { @Override public Object getBean() { return this; } @Override public String getName() { return "onSelect";} }; public final ObjectProperty<EventHandler<SelectionEvent>> onDeselectProperty() { return onDeselect; } public final void setOnDeselect(EventHandler<SelectionEvent> value) { onDeselectProperty().set(value); } public final EventHandler<SelectionEvent> getOnDeselect() { return onDeselectProperty().get(); } private ObjectProperty<EventHandler<SelectionEvent>> onDeselect = new ObjectPropertyBase<EventHandler<SelectionEvent>>() { @Override public Object getBean() { return this; } @Override public String getName() { return "onDeselect";} }; public void fireSelectionEvent(final SelectionEvent EVENT) { fireEvent(EVENT); final EventType TYPE = EVENT.getEventType(); final EventHandler<SelectionEvent> HANDLER; if (SelectionEvent.SELECT == TYPE) { HANDLER = getOnSelect(); } else if (SelectionEvent.DESELECT == TYPE) { HANDLER = getOnDeselect(); } else { HANDLER = null; } if (null == HANDLER) return; HANDLER.handle(EVENT); } }