UIForAnyToggleButton.java
package swingtree;
import sprouts.From;
import sprouts.Var;
import javax.swing.JToggleButton;
/**
* An abstract precursor for swing tree builder nodes for {@link JToggleButton} instances.
* Extend this class to create a builder node for a custom {@link JToggleButton} subtype.
*
* @param <I> The type of this builder node.
* @param <B> The type of the {@link JToggleButton} subtype which will be managed by this builder.
*/
public abstract class UIForAnyToggleButton<I, B extends JToggleButton> extends UIForAnyButton<I, B>
{
/**
* Use this to dynamically bind the selection flag of the button to a {@link Var}
* property which will determine the selection state of the button based on the
* equality of the property value and the provided reference value.
* So if the first {@code state} argument is equal to the value of the {@code selection} property,
* the button will be selected, otherwise it will be deselected.<br>
* A typical use case is to bind a button to an enum property, like so: <br>
* <pre>{@code
* // In your view model:
* enum Step { ONE, TWO, THREE }
* Var<Step> step = Var.of(Step.ONE);
*
* // In your view:
* UI.radioButton("Two").isSelectedIf(Step.TWO, vm.getStep());
* }</pre>
* As you can see, the radio button will be selected if the enum property is equal to the supplied enum value
* and deselected otherwise. <br>
* <br>
* <i>Hint: Use {@code myProperty.fire(From.VIEW_MODEL)} in your view model to send the property value to this view component.</i>
*
* @param state The reference value which this {@link JToggleButton} should represent.
* @param selection The {@link sprouts.Var} instance which will be used
* to dynamically model the selection state of the wrapped {@link JToggleButton} type
* based on the equality of the {@code state} argument and the value of the property.
* @param <E> The type of the property value.
* @return The current builder type, to allow for further method chaining.
* @throws IllegalArgumentException if {@code selected} is {@code null}.
*/
public final <E> I isSelectedIf( E state, Var<E> selection ) {
NullUtil.nullArgCheck(state, "state", Enum.class);
NullUtil.nullArgCheck(selection, "selection", Var.class);
NullUtil.nullPropertyCheck(selection, "selection", "Null is not a valid selection state.");
return _withOnShow( selection, (button,s) -> {
_setSelectedSilently(button, state.equals(s));
})
._with( button -> {
_setSelectedSilently(button, state.equals(selection.get()));
// When the user clicks the button, we update the selection property!
// But only if the button is selected, otherwise we'll ignore the click.
// And we also trigger "set" events for the button, so that other buttons
// can be updated to reflect the new selection state.
_onChange(button, event -> {
if ( button.isSelected() )
selection.set(From.VIEW, state ).fireChange(From.VIEW_MODEL);
});
})
._this();
}
}