diff --git a/client/src/main/java/envoy/client/ui/control/QuickSelectControl.java b/client/src/main/java/envoy/client/ui/control/QuickSelectControl.java new file mode 100644 index 0000000..0e1b2e5 --- /dev/null +++ b/client/src/main/java/envoy/client/ui/control/QuickSelectControl.java @@ -0,0 +1,92 @@ +package envoy.client.ui.control; + +import java.util.function.Consumer; + +import javafx.geometry.*; +import javafx.scene.control.*; +import javafx.scene.image.ImageView; +import javafx.scene.layout.*; +import javafx.scene.shape.Rectangle; + +import envoy.client.util.IconUtil; +import envoy.data.*; + +/** + * Displays an {@link User} as a quick select control which is used in the + * quick select list. + * + * @author Maximilian Käfer + * @since Envoy Client v0.3-beta + */ +public class QuickSelectControl extends VBox { + + private User user; + + /** + * Creates an instance of the {@code QuickSelectControl}. + * + * @param user the contact whose data is used to create this instance. + * @param action the action to perform when a contact is removed with this control as a parameter + * @since Envoy Client v0.3-beta + */ + public QuickSelectControl(User user, Consumer action) { + this.user = user; + setPadding(new Insets(1, 0, 0, 0)); + setPrefWidth(37); + setMaxWidth(37); + setMinWidth(37); + var stackPane = new StackPane(); + stackPane.setAlignment(Pos.TOP_CENTER); + + // Profile picture + var picHold = new VBox(); + picHold.setPadding(new Insets(2, 0, 0, 0)); + picHold.setPrefHeight(35); + picHold.setMaxHeight(35); + picHold.setMinHeight(35); + var contactProfilePic = new ImageView(IconUtil.loadIconThemeSensitive("user_icon", 32)); + final var clip = new Rectangle(); + clip.setWidth(32); + clip.setHeight(32); + clip.setArcHeight(32); + clip.setArcWidth(32); + contactProfilePic.setClip(clip); + picHold.getChildren().add(contactProfilePic); + stackPane.getChildren().add(picHold); + + var hBox = new HBox(); + hBox.setPrefHeight(12); + hBox.setMaxHeight(12); + hBox.setMinHeight(12); + var region = new Region(); + hBox.getChildren().add(region); + HBox.setHgrow(region, Priority.ALWAYS); + + var removeBtn = new Button(); + removeBtn.setPrefSize(12, 12); + removeBtn.setMaxSize(12, 12); + removeBtn.setMinSize(12, 12); + removeBtn.setOnMouseClicked(evt -> action.accept(this)); + removeBtn.setId("remove-button"); + hBox.getChildren().add(removeBtn); + stackPane.getChildren().add(hBox); + getChildren().add(stackPane); + + var nameLabel = new Label(); + nameLabel.setPrefSize(35, 20); + nameLabel.setMaxSize(35, 20); + nameLabel.setMinSize(35, 20); + nameLabel.setText(user.getName()); + nameLabel.setAlignment(Pos.TOP_CENTER); + nameLabel.setPadding(new Insets(0, 5, 0, 0)); + getChildren().add(nameLabel); + + getStyleClass().add("quick-select"); + } + + /** + * @return the user whose data is used in this instance + * @since Envoy Client v0.3-beta + */ + public User getUser() { return user; } +} diff --git a/client/src/main/java/envoy/client/ui/controller/GroupCreationTab.java b/client/src/main/java/envoy/client/ui/controller/GroupCreationTab.java index 4243ce4..23ec485 100644 --- a/client/src/main/java/envoy/client/ui/controller/GroupCreationTab.java +++ b/client/src/main/java/envoy/client/ui/controller/GroupCreationTab.java @@ -7,11 +7,12 @@ import java.util.stream.Collectors; import javafx.application.Platform; import javafx.fxml.FXML; import javafx.scene.control.*; +import javafx.scene.input.MouseEvent; import javafx.scene.layout.HBox; import envoy.client.data.*; import envoy.client.event.BackEvent; -import envoy.client.ui.control.ContactControl; +import envoy.client.ui.control.*; import envoy.client.ui.listcell.ListCellFactory; import envoy.data.*; import envoy.event.GroupCreation; @@ -58,6 +59,9 @@ public class GroupCreationTab implements EventListener { @FXML private HBox errorProceedBox; + @FXML + private ListView quickSelectList; + private String name; private final LocalDB localDB = Context.getInstance().getLocalDB(); @@ -67,7 +71,6 @@ public class GroupCreationTab implements EventListener { @FXML private void initialize() { userList.setCellFactory(new ListCellFactory<>(ContactControl::new)); - userList.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); createButton.setDisable(true); eventBus.registerListener(this); userList.getItems() @@ -78,6 +81,8 @@ public class GroupCreationTab implements EventListener { .filter(not(localDB.getUser()::equals)) .map(User.class::cast) .collect(Collectors.toList())); + resizeQuickSelectSpace(0); + quickSelectList.addEventFilter(MouseEvent.MOUSE_PRESSED, evt -> evt.consume()); } /** @@ -86,7 +91,15 @@ public class GroupCreationTab implements EventListener { * @since Envoy Client v0.1-beta */ @FXML - private void userListClicked() { createButton.setDisable(userList.getSelectionModel().isEmpty() || groupNameField.getText().isBlank()); } + private void userListClicked() { + if (userList.getSelectionModel().getSelectedItem() != null) { + quickSelectList.getItems().add(new QuickSelectControl(userList.getSelectionModel().getSelectedItem(), this::removeFromQuickSelection)); + createButton.setDisable(quickSelectList.getItems().isEmpty() || groupNameField.getText().isBlank()); + resizeQuickSelectSpace(60); + userList.getItems().remove(userList.getSelectionModel().getSelectedItem()); + userList.getSelectionModel().clearSelection(); + } + } /** * Checks, whether the {@code createButton} can be enabled because text is @@ -95,7 +108,7 @@ public class GroupCreationTab implements EventListener { * @since Envoy Client v0.1-beta */ @FXML - private void textUpdated() { createButton.setDisable(userList.getSelectionModel().isEmpty() || groupNameField.getText().isBlank()); } + private void textUpdated() { createButton.setDisable(quickSelectList.getItems().isEmpty() || groupNameField.getText().isBlank()); } /** * Sends a {@link GroupCreation} to the server and closes this scene. @@ -123,6 +136,9 @@ public class GroupCreationTab implements EventListener { // Restoring the original design as tabs will always be reused setErrorMessageLabelSize(0); groupNameField.clear(); + quickSelectList.getItems().forEach(q -> userList.getItems().add(q.getUser())); + quickSelectList.getItems().clear(); + resizeQuickSelectSpace(0); } } @@ -136,7 +152,7 @@ public class GroupCreationTab implements EventListener { private void createGroup(String name) { Context.getInstance() .getClient() - .send(new GroupCreation(name, userList.getSelectionModel().getSelectedItems().stream().map(User::getID).collect(Collectors.toSet()))); + .send(new GroupCreation(name, quickSelectList.getItems().stream().map(q -> q.getUser().getID()).collect(Collectors.toSet()))); } /** @@ -151,6 +167,27 @@ public class GroupCreationTab implements EventListener { return localDB.getChats().stream().map(Chat::getRecipient).filter(Group.class::isInstance).map(Contact::getName).anyMatch(newName::equals); } + /** + * Removes an element from the quickSelectList. + * + * @param element the element to be removed. + * @since Envoy Client v0.3-beta + */ + public void removeFromQuickSelection(QuickSelectControl element) { + quickSelectList.getItems().remove(element); + userList.getItems().add(element.getUser()); + if (quickSelectList.getItems().isEmpty()) { + resizeQuickSelectSpace(0); + createButton.setDisable(true); + } + } + + private void resizeQuickSelectSpace(int value) { + quickSelectList.setPrefHeight(value); + quickSelectList.setMaxHeight(value); + quickSelectList.setMinHeight(value); + } + @FXML private void backButtonClicked() { eventBus.dispatch(new BackEvent()); diff --git a/client/src/main/resources/css/base.css b/client/src/main/resources/css/base.css index 79099d7..be559b7 100644 --- a/client/src/main/resources/css/base.css +++ b/client/src/main/resources/css/base.css @@ -41,7 +41,7 @@ -fx-scale-y: 1.05; } -.label { +.label, .quick-select { -fx-background-color: transparent; } @@ -144,3 +144,15 @@ visibility: hidden ; -fx-padding: -20.0 0.0 0.0 0.0; } + +#quick-select-list .scroll-bar:horizontal{ + -fx-pref-height: 0; + -fx-max-height: 0; + -fx-min-height: 0; +} + +#quick-select-list .scroll-bar:vertical{ + -fx-pref-width: 0; + -fx-max-width: 0; + -fx-min-width: 0; +} diff --git a/client/src/main/resources/css/dark.css b/client/src/main/resources/css/dark.css index 7ab6a59..0ed2997 100644 --- a/client/src/main/resources/css/dark.css +++ b/client/src/main/resources/css/dark.css @@ -18,7 +18,7 @@ -fx-background-color: lightgray; } -#message-list, .text-field, .password-field, .tooltip, .pane, .pane .content, .vbox, .titled-pane > .title, .titled-pane > *.content, .context-menu, .menu-item { +#message-list, .text-field, .password-field, .tooltip, .pane, .pane .content, .vbox, .titled-pane > .title, .titled-pane > *.content, .context-menu, .menu-item, #quick-select-list { -fx-background-color: #222222; } @@ -69,7 +69,7 @@ -fx-background-color: transparent; } -.scroll-bar:vertical .increment-arrow, .scroll-bar:vertical .decrement-arrow { +.scroll-bar:vertical .increment-arrow, .scroll-bar:vertical .decrement-arrow, .list-cell { -fx-background-color: transparent; } @@ -83,3 +83,8 @@ -fx-text-fill: white; -fx-background-color: transparent; } + +#remove-button { + -fx-background-color: red; + -fx-background-radius: 1em; +} diff --git a/client/src/main/resources/fxml/GroupCreationTab.fxml b/client/src/main/resources/fxml/GroupCreationTab.fxml index cb4dbad..688ae0d 100644 --- a/client/src/main/resources/fxml/GroupCreationTab.fxml +++ b/client/src/main/resources/fxml/GroupCreationTab.fxml @@ -64,6 +64,7 @@ +