ButtonBindings.java
- /*
- * *************************************************************************************************************************************************************
- *
- * SteelBlue: DCI User Interfaces
- * http://tidalwave.it/projects/steelblue
- *
- * Copyright (C) 2015 - 2025 by Tidalwave s.a.s. (http://tidalwave.it)
- *
- * *************************************************************************************************************************************************************
- *
- * 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.
- *
- * *************************************************************************************************************************************************************
- *
- * git clone https://bitbucket.org/tidalwave/steelblue-src
- * git clone https://github.com/tidalwave-it/steelblue-src
- *
- * *************************************************************************************************************************************************************
- */
- package it.tidalwave.ui.javafx.impl.button;
- import jakarta.annotation.Nonnull;
- import java.util.Collection;
- import java.util.List;
- import java.util.concurrent.Executor;
- import java.util.concurrent.atomic.AtomicInteger;
- import javafx.beans.property.BooleanProperty;
- import javafx.geometry.HPos;
- import javafx.geometry.VPos;
- import javafx.scene.control.Button;
- import javafx.scene.control.ButtonBase;
- import javafx.scene.control.MenuItem;
- import javafx.scene.control.ToggleButton;
- import javafx.scene.control.ToggleGroup;
- import javafx.scene.layout.ColumnConstraints;
- import javafx.scene.layout.GridPane;
- import javafx.scene.layout.Pane;
- import javafx.scene.layout.Priority;
- import javafx.application.Platform;
- import it.tidalwave.ui.core.BoundProperty;
- import it.tidalwave.ui.core.role.Displayable;
- import it.tidalwave.ui.core.role.PresentationModel;
- import it.tidalwave.ui.core.role.Styleable;
- import it.tidalwave.ui.core.role.UserAction;
- import it.tidalwave.ui.core.role.UserActionProvider;
- import it.tidalwave.ui.javafx.impl.common.DelegateSupport;
- import it.tidalwave.util.As;
- import it.tidalwave.role.SimpleComposite;
- import static it.tidalwave.ui.core.role.Displayable._Displayable_;
- import static it.tidalwave.ui.core.role.Styleable._Styleable_;
- import static it.tidalwave.ui.core.role.UserActionProvider._UserActionProvider_;
- import static it.tidalwave.ui.javafx.impl.DefaultJavaFXBinder.enforceFxApplicationThread;
- import static java.util.Collections.emptyList;
- import static java.util.stream.Collectors.*;
- /***************************************************************************************************************************************************************
- *
- * @author Fabrizio Giudici
- *
- **************************************************************************************************************************************************************/
- public class ButtonBindings extends DelegateSupport
- {
- private static final As.Type<SimpleComposite<PresentationModel>> _SimpleCompositePresentationModel_ = new As.Type<>(SimpleComposite.class);
- /***********************************************************************************************************************************************************
- *
- **********************************************************************************************************************************************************/
- public ButtonBindings (@Nonnull final Executor executor)
- {
- super(executor);
- }
- /***********************************************************************************************************************************************************
- *
- **********************************************************************************************************************************************************/
- public void bind (@Nonnull final ButtonBase button, @Nonnull final UserAction action)
- {
- enforceFxApplicationThread();
- action.maybeAs(_Displayable_).ifPresent(d -> button.setText(d.getDisplayName()));
- button.setOnAction(ignored -> executor.execute(action::actionPerformed));
- bindEnableProperty(button.disableProperty(), action.enabled());
- }
- /***********************************************************************************************************************************************************
- *
- **********************************************************************************************************************************************************/
- public void bind (@Nonnull final MenuItem menuItem, @Nonnull final UserAction action)
- {
- enforceFxApplicationThread();
- menuItem.setText(action.maybeAs(_Displayable_).map(Displayable::getDisplayName).orElse(""));
- menuItem.setOnAction(ignored -> executor.execute(action::actionPerformed));
- bindEnableProperty(menuItem.disableProperty(), action.enabled());
- }
- /***********************************************************************************************************************************************************
- * {@inheritDoc}
- **********************************************************************************************************************************************************/
- public void bindToggleButtons (@Nonnull final Pane pane, @Nonnull final PresentationModel pm)
- {
- enforceFxApplicationThread();
- final var group = new ToggleGroup();
- final var children = pane.getChildren();
- final var prototypeStyleClass = children.get(0).getStyleClass();
- final var pmc = pm.as(_SimpleCompositePresentationModel_);
- children.setAll(pmc.findChildren().stream().map(cpm -> createToggleButton(cpm, prototypeStyleClass, group)).collect(toList()));
- }
- /***********************************************************************************************************************************************************
- *
- **********************************************************************************************************************************************************/
- public void bindButtonsInPane (@Nonnull final GridPane gridPane, @Nonnull final Collection<UserAction> actions)
- {
- enforceFxApplicationThread();
- final var columnConstraints = gridPane.getColumnConstraints();
- final var children = gridPane.getChildren();
- columnConstraints.clear();
- children.clear();
- final var columnIndex = new AtomicInteger(0);
- actions.forEach(menuAction ->
- {
- final var column = new ColumnConstraints();
- column.setPercentWidth(100.0 / actions.size());
- columnConstraints.add(column);
- final var button = createButton();
- GridPane.setConstraints(button, columnIndex.getAndIncrement(), 0);
- bind(button, menuAction);
- children.add(button);
- });
- }
- /***********************************************************************************************************************************************************
- * {@return a new {@code Button}} for the menu bar.
- **********************************************************************************************************************************************************/
- @Nonnull
- private Button createButton()
- {
- final var button = new Button();
- GridPane.setHgrow(button, Priority.ALWAYS);
- GridPane.setVgrow(button, Priority.ALWAYS);
- GridPane.setHalignment(button, HPos.CENTER);
- GridPane.setValignment(button, VPos.CENTER);
- button.setPrefSize(999, 999); // fill
- button.getStyleClass().add("mainMenuButton");
- return button;
- }
- /***********************************************************************************************************************************************************
- *
- **********************************************************************************************************************************************************/
- @Nonnull
- private ToggleButton createToggleButton (@Nonnull final PresentationModel pm, @Nonnull final List<String> baseStyleClass, @Nonnull final ToggleGroup group)
- {
- final var button = new ToggleButton();
- button.setToggleGroup(group);
- button.setText(pm.maybeAs(_Displayable_).map(Displayable::getDisplayName).orElse(""));
- button.getStyleClass().addAll(baseStyleClass);
- button.getStyleClass().addAll(pm.maybeAs(_Styleable_).map(Styleable::getStyles).orElse(emptyList()));
- pm.maybeAs(_UserActionProvider_).flatMap(UserActionProvider::getOptionalDefaultAction)
- .ifPresent(action -> bind(button, action));
- if (group.getSelectedToggle() == null)
- {
- group.selectToggle(button);
- }
- return button;
- }
- /***********************************************************************************************************************************************************
- *
- **********************************************************************************************************************************************************/
- private void bindEnableProperty (@Nonnull final BooleanProperty property1, @Nonnull final BoundProperty<Boolean> property2)
- {
- property1.setValue(!property2.get());
- property1.addListener((_1, _2, newValue) -> executor.execute(() -> property2.set(!newValue)));
- property2.addPropertyChangeListener(evt -> Platform.runLater(() -> property1.setValue(!(boolean)evt.getNewValue())));
- }
- }