package org.geotoolkit.gui.javafx.util; import javafx.beans.binding.Bindings; import javafx.beans.property.BooleanProperty; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.value.ObservableValue; import javafx.geometry.Pos; import javafx.scene.control.ToggleButton; import javafx.scene.control.TreeTableCell; import javafx.scene.control.TreeTableColumn; import javafx.util.Callback; import javafx.util.StringConverter; /** * Copy version of JavaFX CheckBoxTreeTableCell for a ToggleButton. * */ public class ToggleButtonTreeTableCell<S,T> extends TreeTableCell<S,T> { private final static StringConverter defaultStringConverter = new StringConverter<Object>() { @Override public String toString(Object t) { return t == null ? null : t.toString(); } @Override public Object fromString(String string) { return (Object) string; } }; public static <S> Callback<TreeTableColumn<S,Boolean>, TreeTableCell<S,Boolean>> forTreeTableColumn( final TreeTableColumn<S, Boolean> column) { return forTreeTableColumn(null, null); } public static <S,T> Callback<TreeTableColumn<S,T>, TreeTableCell<S,T>> forTreeTableColumn( final Callback<Integer, ObservableValue<Boolean>> getSelectedProperty) { return forTreeTableColumn(getSelectedProperty, null); } public static <S,T> Callback<TreeTableColumn<S,T>, TreeTableCell<S,T>> forTreeTableColumn( final Callback<Integer, ObservableValue<Boolean>> getSelectedProperty, final boolean showLabel) { StringConverter<T> converter = ! showLabel ? null : defaultStringConverter; return forTreeTableColumn(getSelectedProperty, converter); } public static <S,T> Callback<TreeTableColumn<S,T>, TreeTableCell<S,T>> forTreeTableColumn( final Callback<Integer, ObservableValue<Boolean>> getSelectedProperty, final StringConverter<T> converter) { return list -> new ToggleButtonTreeTableCell<S,T>(getSelectedProperty, converter); } private final ToggleButton toggleButton; private boolean showLabel; private ObservableValue<Boolean> booleanProperty; public ToggleButtonTreeTableCell() { this(null, null); } public ToggleButtonTreeTableCell( final Callback<Integer, ObservableValue<Boolean>> getSelectedProperty) { this(getSelectedProperty, null); } public ToggleButtonTreeTableCell( final Callback<Integer, ObservableValue<Boolean>> getSelectedProperty, final StringConverter<T> converter) { this.toggleButton = new ToggleButton(); setGraphic(null); setSelectedStateCallback(getSelectedProperty); setConverter(converter); } public ToggleButton getToggleButton() { return toggleButton; } private ObjectProperty<StringConverter<T>> converter = new SimpleObjectProperty<StringConverter<T>>(this, "converter") { protected void invalidated() { updateShowLabel(); } }; public final ObjectProperty<StringConverter<T>> converterProperty() { return converter; } public final void setConverter(StringConverter<T> value) { converterProperty().set(value); } public final StringConverter<T> getConverter() { return converterProperty().get(); } private ObjectProperty<Callback<Integer, ObservableValue<Boolean>>> selectedStateCallback = new SimpleObjectProperty<Callback<Integer, ObservableValue<Boolean>>>( this, "selectedStateCallback"); public final ObjectProperty<Callback<Integer, ObservableValue<Boolean>>> selectedStateCallbackProperty() { return selectedStateCallback; } public final void setSelectedStateCallback(Callback<Integer, ObservableValue<Boolean>> value) { selectedStateCallbackProperty().set(value); } public final Callback<Integer, ObservableValue<Boolean>> getSelectedStateCallback() { return selectedStateCallbackProperty().get(); } @SuppressWarnings("unchecked") @Override public void updateItem(T item, boolean empty) { super.updateItem(item, empty); if (empty) { setText(null); setGraphic(null); } else { StringConverter<T> c = getConverter(); if (showLabel) { setText(c.toString(item)); } setGraphic(toggleButton); if (booleanProperty instanceof BooleanProperty) { toggleButton.selectedProperty().unbindBidirectional((BooleanProperty)booleanProperty); } ObservableValue<?> obsValue = getSelectedProperty(); if (obsValue instanceof BooleanProperty) { booleanProperty = (ObservableValue<Boolean>) obsValue; toggleButton.selectedProperty().bindBidirectional((BooleanProperty)booleanProperty); } toggleButton.disableProperty().bind(Bindings.not( getTreeTableView().editableProperty().and( getTableColumn().editableProperty()).and( editableProperty()) )); } } private void updateShowLabel() { this.showLabel = converter != null; this.toggleButton.setAlignment(showLabel ? Pos.CENTER_LEFT : Pos.CENTER); } private ObservableValue<?> getSelectedProperty() { return getSelectedStateCallback() != null ? getSelectedStateCallback().call(getIndex()) : getTableColumn().getCellObservableValue(getIndex()); } }