Merge pull request 'Quick Select Support for the GroupCreationTab' (#77) from f/quick-group-select into develop

Reviewed-on: https://git.kske.dev/zdm/envoy/pulls/77
Reviewed-by: kske <kai@kske.dev>
Reviewed-by: delvh <leon@kske.dev> (With a little discussion topic :))
This commit is contained in:
Maximilian P. Käfer 2020-10-04 21:28:55 +02:00
commit 99867eb23a
Signed by: Käfer & Engelbart Git
GPG Key ID: 70F2F9206EDC1FCE
5 changed files with 155 additions and 8 deletions

View File

@ -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&auml;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<QuickSelectControl> 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; }
}

View File

@ -7,11 +7,12 @@ import java.util.stream.Collectors;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.control.*; import javafx.scene.control.*;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox; import javafx.scene.layout.HBox;
import envoy.client.data.*; import envoy.client.data.*;
import envoy.client.event.BackEvent; import envoy.client.event.BackEvent;
import envoy.client.ui.control.ContactControl; import envoy.client.ui.control.*;
import envoy.client.ui.listcell.ListCellFactory; import envoy.client.ui.listcell.ListCellFactory;
import envoy.data.*; import envoy.data.*;
import envoy.event.GroupCreation; import envoy.event.GroupCreation;
@ -58,6 +59,9 @@ public class GroupCreationTab implements EventListener {
@FXML @FXML
private HBox errorProceedBox; private HBox errorProceedBox;
@FXML
private ListView<QuickSelectControl> quickSelectList;
private String name; private String name;
private final LocalDB localDB = Context.getInstance().getLocalDB(); private final LocalDB localDB = Context.getInstance().getLocalDB();
@ -67,7 +71,6 @@ public class GroupCreationTab implements EventListener {
@FXML @FXML
private void initialize() { private void initialize() {
userList.setCellFactory(new ListCellFactory<>(ContactControl::new)); userList.setCellFactory(new ListCellFactory<>(ContactControl::new));
userList.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
createButton.setDisable(true); createButton.setDisable(true);
eventBus.registerListener(this); eventBus.registerListener(this);
userList.getItems() userList.getItems()
@ -78,6 +81,8 @@ public class GroupCreationTab implements EventListener {
.filter(not(localDB.getUser()::equals)) .filter(not(localDB.getUser()::equals))
.map(User.class::cast) .map(User.class::cast)
.collect(Collectors.toList())); .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 * @since Envoy Client v0.1-beta
*/ */
@FXML @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 * 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 * @since Envoy Client v0.1-beta
*/ */
@FXML @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. * 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 // Restoring the original design as tabs will always be reused
setErrorMessageLabelSize(0); setErrorMessageLabelSize(0);
groupNameField.clear(); 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) { private void createGroup(String name) {
Context.getInstance() Context.getInstance()
.getClient() .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); 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 @FXML
private void backButtonClicked() { private void backButtonClicked() {
eventBus.dispatch(new BackEvent()); eventBus.dispatch(new BackEvent());

View File

@ -41,7 +41,7 @@
-fx-scale-y: 1.05; -fx-scale-y: 1.05;
} }
.label { .label, .quick-select {
-fx-background-color: transparent; -fx-background-color: transparent;
} }
@ -144,3 +144,15 @@
visibility: hidden ; visibility: hidden ;
-fx-padding: -20.0 0.0 0.0 0.0; -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;
}

View File

@ -18,7 +18,7 @@
-fx-background-color: lightgray; -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; -fx-background-color: #222222;
} }
@ -69,7 +69,7 @@
-fx-background-color: transparent; -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; -fx-background-color: transparent;
} }
@ -83,3 +83,8 @@
-fx-text-fill: white; -fx-text-fill: white;
-fx-background-color: transparent; -fx-background-color: transparent;
} }
#remove-button {
-fx-background-color: red;
-fx-background-radius: 1em;
}

View File

@ -64,6 +64,7 @@
<Insets bottom="5.0" top="5" /> <Insets bottom="5.0" top="5" />
</VBox.margin> </VBox.margin>
</Label> </Label>
<ListView fx:id="quickSelectList" id="quick-select-list" orientation="HORIZONTAL" prefHeight="60.0" />
<ListView id="chat-list" fx:id="userList" focusTraversable="false" onMouseClicked="#userListClicked" prefWidth="316.0" VBox.vgrow="ALWAYS"> <ListView id="chat-list" fx:id="userList" focusTraversable="false" onMouseClicked="#userListClicked" prefWidth="316.0" VBox.vgrow="ALWAYS">
<contextMenu> <contextMenu>
<ContextMenu anchorLocation="CONTENT_TOP_LEFT" /> <ContextMenu anchorLocation="CONTENT_TOP_LEFT" />