package envoy.client.ui.controller; import static java.util.function.Predicate.not; import java.util.stream.Collectors; import javafx.application.Platform; import javafx.fxml.FXML; import javafx.scene.control.*; import javafx.scene.control.Alert.AlertType; import envoy.client.data.Chat; import envoy.client.data.LocalDB; import envoy.client.event.BackEvent; import envoy.client.event.LoadGroupCreationEvent; import envoy.client.event.SendEvent; import envoy.client.ui.SceneContext; import envoy.client.ui.listcell.ContactControl; import envoy.client.ui.listcell.ListCellFactory; import envoy.data.Contact; import envoy.data.Group; import envoy.data.User; import envoy.event.EventBus; import envoy.event.GroupCreation; import envoy.util.Bounds; /** * Provides a group creation interface. A group name can be entered in the text * field at the top. Available users (local chat recipients) are displayed * inside a list and can be selected (multiple selection available). *

* When the group creation button is pressed, a {@link GroupCreation} is sent to * the server. This controller enforces a valid group name and a non-empty * member list (excluding the client user). *

* Project: envoy-client
* File: GroupCreationScene.java
* Created: 07.06.2020
* * @author Maximilian Käfer * @since Envoy Client v0.1-beta */ public class GroupCreationTab { @FXML private Button createButton; @FXML private TextArea groupNameField; @FXML private ListView userList; private LocalDB localDB; private static final EventBus eventBus = EventBus.getInstance(); @FXML private void initialize() { userList.setCellFactory(new ListCellFactory<>(ContactControl::new)); userList.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); eventBus.register(LoadGroupCreationEvent.class, e -> { createButton.setDisable(true); this.localDB = e.get(); userList.getItems().clear(); Platform.runLater(() -> userList.getItems() .addAll(localDB.getChats() .stream() .map(Chat::getRecipient) .filter(User.class::isInstance) .filter(not(localDB.getUser()::equals)) .map(User.class::cast) .collect(Collectors.toList()))); }); } /** * Enables the {@code createButton} if at least one contact is selected. * * @since Envoy Client v0.1-beta */ @FXML private void userListClicked() { createButton.setDisable(userList.getSelectionModel().isEmpty() || groupNameField.getText().isBlank()); } /** * Checks, whether the {@code createButton} can be enabled because text is * present in the text field. * * @since Envoy Client v0.1-beta */ @FXML private void textUpdated() { createButton.setDisable(userList.getSelectionModel().isEmpty() || groupNameField.getText().isBlank()); } /** * Sends a {@link GroupCreation} to the server and closes this scene. *

* If the given group name is not valid, an error is displayed instead. * * @since Envoy Client v0.1-beta */ @FXML private void createButtonClicked() { final var name = groupNameField.getText(); if (!Bounds.isValidContactName(name)) { new Alert(AlertType.ERROR, "The entered group name is not valid (" + Bounds.CONTACT_NAME_PATTERN + ")").showAndWait(); groupNameField.clear(); } else if (groupNameAlreadyPresent(name)) { final var alert = new Alert(AlertType.WARNING, "You already have a group with that name.", ButtonType.OK, ButtonType.CANCEL); alert.setTitle("Create Group?"); alert.setHeaderText("Proceed?"); alert.showAndWait().filter(btn -> btn == ButtonType.OK).ifPresent(btn -> createGroup(name)); } else { new Alert(AlertType.INFORMATION, String.format("Group '%s' successfully created.", name)).showAndWait(); createGroup(name); } eventBus.dispatch(new BackEvent()); } /** * Creates a new group with the given name and all selected members.
* Additionally pops the scene automatically. * * @param name the chosen group name * @since Envoy Client v0.1-beta */ private void createGroup(String name) { eventBus.dispatch(new SendEvent( new GroupCreation(name, userList.getSelectionModel().getSelectedItems().stream().map(User::getID).collect(Collectors.toSet())))); } /** * Returns true if the proposed group name is already present in the users * {@code LocalDB}. * * @param newName the chosen group name * @return true if this name is already present * @since Envoy Client v0.1-beta */ public boolean groupNameAlreadyPresent(String newName) { return localDB.getChats() .stream() .map(Chat::getRecipient) .filter(Group.class::isInstance) .map(Contact::getName) .anyMatch(newName::equals); } @FXML private void backButtonClicked() { eventBus.dispatch(new BackEvent()); } }