/* * Copyright [2014] [Christian Loehnert, krampenschiesser@gmail.com] * 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 de.ks.selection; import de.ks.activity.ActivityController; import de.ks.executor.group.LastTextChange; import de.ks.i18n.Localized; import de.ks.javafx.FxCss; import de.ks.persistence.PersistentWork; import de.ks.persistence.QueryConsumer; import de.ks.persistence.entity.NamedPersistentObject; import de.ks.validation.ValidationRegistry; import de.ks.validation.validators.NamedEntityValidator; import javafx.application.Platform; import javafx.beans.property.BooleanProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.TextField; import javafx.scene.input.KeyCode; import javafx.scene.input.KeyEvent; import javafx.scene.layout.GridPane; import javafx.scene.layout.StackPane; import javafx.stage.Modality; import javafx.stage.Stage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.enterprise.inject.Instance; import javax.enterprise.inject.spi.CDI; import java.net.URL; import java.util.ResourceBundle; public abstract class BaseNamedPersistentObjectSelection<T extends NamedPersistentObject<T>> implements Initializable { private static final Logger log = LoggerFactory.getLogger(BaseNamedPersistentObjectSelection.class); @FXML protected TextField input; @FXML protected GridPane root; @FXML protected Button browse; protected Class<T> entityClass; protected SimpleObjectProperty<T> selectedValue = new SimpleObjectProperty<>(); protected ActivityController controller = CDI.current().select(ActivityController.class).get(); protected QueryConsumer<T, T> filter; protected Stage dialog; private CustomAutoCompletionBinding autoCompletion; private EventHandler<ActionEvent> onAction; private NamedPersistentObjectAutoCompletion<T> namedPersistentObjectAutoCompletion; private LastTextChange lastInputTextChange; @Override public void initialize(URL location, ResourceBundle resources) { browse.disableProperty().bind(input.disabledProperty()); selectedValue.addListener((p, o, n) -> { if (n != null) { input.setText(n.getName()); if (onAction != null) { onAction.handle(new ActionEvent()); } } }); } protected void findAndSetLastValue(String name) { T namedObject = PersistentWork.forName(entityClass, name); controller.getJavaFXExecutor().submit(() -> { setSelectedValue(namedObject); }); } public BaseNamedPersistentObjectSelection<T> from(Class<T> namedEntity) { from(namedEntity, null); return this; } public BaseNamedPersistentObjectSelection<T> from(Class<T> namedEntity, QueryConsumer<T, T> filter) { this.entityClass = namedEntity; this.filter = filter; Platform.runLater(() -> { namedPersistentObjectAutoCompletion = new NamedPersistentObjectAutoCompletion<>(entityClass, filter); autoCompletion = new CustomAutoCompletionBinding(input, namedPersistentObjectAutoCompletion); }); lastInputTextChange = new LastTextChange(input, controller.getExecutorService()); lastInputTextChange.registerHandler(cf -> { cf.thenAccept(this::findAndSetLastValue); }); return this; } public BaseNamedPersistentObjectSelection<T> enableValidation() { ValidationRegistry validationRegistry = CDI.current().select(ValidationRegistry.class).get(); Platform.runLater(() -> { validationRegistry.registerValidator(input, new NamedEntityValidator(entityClass)); }); return this; } @FXML protected void showBrowser() { String title = Localized.get("select.namedEntity." + entityClass.getSimpleName()); dialog = new Stage(); dialog.setTitle(title); Scene scene = new Scene(new StackPane(getBrowseNode())); dialog.setScene(scene); dialog.initModality(Modality.APPLICATION_MODAL); dialog.setAlwaysOnTop(true); dialog.show(); Instance<String> styleSheets = CDI.current().select(String.class, FxCss.LITERAL); styleSheets.forEach((sheet) -> { scene.getStylesheets().add(sheet); }); } public BooleanProperty disableProperty() { return input.disableProperty(); } public TextField getInput() { return input; } public void hidePopup() { if (dialog != null) { dialog.hide(); } if (autoCompletion != null) { autoCompletion.hidePopup(); } } @FXML void onKeyPressed(KeyEvent event) { KeyCode code = event.getCode(); if (code == KeyCode.ENTER) { if (onAction != null) { event.consume(); onAction.handle(new ActionEvent()); input.clear(); } } } public void setOnAction(EventHandler<ActionEvent> handler) { this.onAction = handler; } public EventHandler<ActionEvent> getOnAction() { return onAction; } public boolean isSelectingProject() { return dialog != null && dialog.isShowing(); } public void hideBrowserBtn() { if (root.getChildren().contains(browse)) { root.getChildren().remove(browse); } root.setHgap(0.0D); } public T getSelectedValue() { return selectedValue.get(); } public SimpleObjectProperty<T> selectedValueProperty() { return selectedValue; } public void setSelectedValue(T selectedValue) { this.selectedValue.set(selectedValue); } protected abstract Node getBrowseNode(); }