Add ContactListCellFactory

- Refactor chatList to userList in ContactSearchScene and
  GroupCreationScene
- Narrow contact searches down to users on a datamodel basis
- Refactor ContactSearchRequest and ContactSearchResult to
  UserSearchRequest and UserSearchResult
This commit is contained in:
Kai S. K. Engelbart 2020-07-13 19:02:40 +02:00
parent bcb978ce59
commit 563499e9cf
No known key found for this signature in database
GPG Key ID: 0A48559CA32CB48F
13 changed files with 188 additions and 152 deletions

View File

@ -12,7 +12,7 @@ import envoy.client.event.SendEvent;
import envoy.data.*; import envoy.data.*;
import envoy.event.*; import envoy.event.*;
import envoy.event.contact.ContactOperation; import envoy.event.contact.ContactOperation;
import envoy.event.contact.ContactSearchResult; import envoy.event.contact.UserSearchResult;
import envoy.util.EnvoyLog; import envoy.util.EnvoyLog;
import envoy.util.SerializationUtils; import envoy.util.SerializationUtils;
@ -147,7 +147,7 @@ public class Client implements Closeable {
receiver.registerProcessor(NameChange.class, evt -> { localDB.replaceContactName(evt); eventBus.dispatch(evt); }); receiver.registerProcessor(NameChange.class, evt -> { localDB.replaceContactName(evt); eventBus.dispatch(evt); });
// Process contact searches // Process contact searches
receiver.registerProcessor(ContactSearchResult.class, eventBus::dispatch); receiver.registerProcessor(UserSearchResult.class, eventBus::dispatch);
// Process contact operations // Process contact operations
receiver.registerProcessor(ContactOperation.class, eventBus::dispatch); receiver.registerProcessor(ContactOperation.class, eventBus::dispatch);

View File

@ -34,7 +34,7 @@ import envoy.client.net.WriteProxy;
import envoy.client.ui.IconUtil; import envoy.client.ui.IconUtil;
import envoy.client.ui.Restorable; import envoy.client.ui.Restorable;
import envoy.client.ui.SceneContext; import envoy.client.ui.SceneContext;
import envoy.client.ui.listcell.ContactListCellFactory; import envoy.client.ui.listcell.ChatListCellFactory;
import envoy.client.ui.listcell.MessageControl; import envoy.client.ui.listcell.MessageControl;
import envoy.client.ui.listcell.MessageListCellFactory; import envoy.client.ui.listcell.MessageListCellFactory;
import envoy.data.*; import envoy.data.*;
@ -125,7 +125,7 @@ public final class ChatScene implements Restorable {
// Initialize message and user rendering // Initialize message and user rendering
messageList.setCellFactory(MessageListCellFactory::new); messageList.setCellFactory(MessageListCellFactory::new);
chatList.setCellFactory(ContactListCellFactory::new); chatList.setCellFactory(ChatListCellFactory::new);
settingsButton.setGraphic(new ImageView(IconUtil.loadIconThemeSensitive("settings", DEFAULT_ICON_SIZE))); settingsButton.setGraphic(new ImageView(IconUtil.loadIconThemeSensitive("settings", DEFAULT_ICON_SIZE)));
voiceButton.setGraphic(new ImageView(IconUtil.loadIconThemeSensitive("microphone", DEFAULT_ICON_SIZE))); voiceButton.setGraphic(new ImageView(IconUtil.loadIconThemeSensitive("microphone", DEFAULT_ICON_SIZE)));
@ -151,8 +151,6 @@ public final class ChatScene implements Restorable {
chatList.getItems().remove(chat); chatList.getItems().remove(chat);
chatList.getItems().add(0, chat); chatList.getItems().add(0, chat);
if (chat.equals(currentChat)) chatList.getSelectionModel().select(0); if (chat.equals(currentChat)) chatList.getSelectionModel().select(0);
localDB.getChats().remove(chat);
localDB.getChats().add(0, chat);
}); });
}); });
}); });
@ -187,13 +185,11 @@ public final class ChatScene implements Restorable {
case ADD: case ADD:
localDB.getUsers().put(contact.getName(), contact); localDB.getUsers().put(contact.getName(), contact);
Chat chat = contact instanceof User ? new Chat(contact) : new GroupChat(client.getSender(), contact); Chat chat = contact instanceof User ? new Chat(contact) : new GroupChat(client.getSender(), contact);
localDB.getChats().add(chat);
Platform.runLater(() -> chatList.getItems().add(chat)); Platform.runLater(() -> chatList.getItems().add(chat));
break; break;
case REMOVE: case REMOVE:
localDB.getUsers().remove(contact.getName()); localDB.getUsers().remove(contact.getName());
localDB.getChats().removeIf(c -> c.getRecipient().getID() == contact.getID()); Platform.runLater(() -> chatList.getItems().removeIf(c -> c.getRecipient().equals(contact)));
Platform.runLater(() -> chatList.getItems().removeIf(c -> c.getRecipient().getID() == contact.getID()));
break; break;
} }
}); });
@ -233,6 +229,8 @@ public final class ChatScene implements Restorable {
*/ */
@FXML @FXML
private void chatListClicked() { private void chatListClicked() {
if (chatList.getSelectionModel().isEmpty()) return;
final Contact user = chatList.getSelectionModel().getSelectedItem().getRecipient(); final Contact user = chatList.getSelectionModel().getSelectedItem().getRecipient();
if (user != null && (currentChat == null || !user.equals(currentChat.getRecipient()))) { if (user != null && (currentChat == null || !user.equals(currentChat.getRecipient()))) {

View File

@ -2,7 +2,6 @@ package envoy.client.ui.controller;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.stream.Collectors;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.fxml.FXML; import javafx.fxml.FXML;
@ -11,22 +10,31 @@ import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.ButtonType; import javafx.scene.control.ButtonType;
import javafx.scene.control.ListView; import javafx.scene.control.ListView;
import envoy.client.data.Chat;
import envoy.client.data.LocalDB; import envoy.client.data.LocalDB;
import envoy.client.event.SendEvent; import envoy.client.event.SendEvent;
import envoy.client.ui.ClearableTextField; import envoy.client.ui.ClearableTextField;
import envoy.client.ui.SceneContext; import envoy.client.ui.SceneContext;
import envoy.client.ui.listcell.ContactListCellFactory; import envoy.client.ui.listcell.ContactListCellFactory;
import envoy.data.User;
import envoy.event.ElementOperation; import envoy.event.ElementOperation;
import envoy.event.EventBus; import envoy.event.EventBus;
import envoy.event.contact.ContactOperation; import envoy.event.contact.ContactOperation;
import envoy.event.contact.ContactSearchRequest; import envoy.event.contact.UserSearchRequest;
import envoy.event.contact.ContactSearchResult; import envoy.event.contact.UserSearchResult;
import envoy.util.EnvoyLog; import envoy.util.EnvoyLog;
/** /**
* Provides a search bar in which a user name (substring) can be entered. The
* users with a matching name are then displayed inside a list view. A
* {@link UserSearchRequest} is sent on every keystroke.
* <p>
* <i>The actual search algorithm is implemented on the server.
* <p>
* To create a group, a button is available that loads the
* {@link GroupCreationScene}.
* <p>
* Project: <strong>envoy-client</strong><br> * Project: <strong>envoy-client</strong><br>
* File: <strong>ContactSearchSceneController.java</strong><br> * File: <strong>ContactSearchScene.java</strong><br>
* Created: <strong>07.06.2020</strong><br> * Created: <strong>07.06.2020</strong><br>
* *
* @author Leon Hofmeister * @author Leon Hofmeister
@ -38,7 +46,7 @@ public class ContactSearchScene {
private ClearableTextField searchBar; private ClearableTextField searchBar;
@FXML @FXML
private ListView<Chat> chatList; private ListView<User> userList;
private SceneContext sceneContext; private SceneContext sceneContext;
@ -59,12 +67,12 @@ public class ContactSearchScene {
@FXML @FXML
private void initialize() { private void initialize() {
chatList.setCellFactory(ContactListCellFactory::new); userList.setCellFactory(new ContactListCellFactory<>());
searchBar.setClearButtonListener(e -> { searchBar.getTextField().clear(); chatList.getItems().clear(); }); searchBar.setClearButtonListener(e -> { searchBar.getTextField().clear(); userList.getItems().clear(); });
eventBus.register(ContactSearchResult.class, eventBus.register(UserSearchResult.class,
response -> Platform.runLater(() -> { response -> Platform.runLater(() -> {
chatList.getItems().clear(); userList.getItems().clear();
chatList.getItems().addAll(response.get().stream().map(Chat::new).collect(Collectors.toList())); userList.getItems().addAll(response.get());
})); }));
} }
@ -76,8 +84,8 @@ public class ContactSearchScene {
@FXML @FXML
private void sendRequest() { private void sendRequest() {
final var text = searchBar.getTextField().getText().strip(); final var text = searchBar.getTextField().getText().strip();
if (!text.isBlank()) eventBus.dispatch(new SendEvent(new ContactSearchRequest(text))); if (!text.isBlank()) eventBus.dispatch(new SendEvent(new UserSearchRequest(text)));
else chatList.getItems().clear(); else userList.getItems().clear();
} }
/** /**
@ -89,7 +97,7 @@ public class ContactSearchScene {
@FXML @FXML
private void clear() { private void clear() {
searchBar.getTextField().setText(null); searchBar.getTextField().setText(null);
chatList.getItems().clear(); userList.getItems().clear();
} }
/** /**
@ -100,21 +108,21 @@ public class ContactSearchScene {
*/ */
@FXML @FXML
private void chatListClicked() { private void chatListClicked() {
final var chat = chatList.getSelectionModel().getSelectedItem(); final var user = userList.getSelectionModel().getSelectedItem();
if (chat != null) { if (user != null) {
final var alert = new Alert(AlertType.CONFIRMATION); final var alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle("Add Contact to Contact List"); alert.setTitle("Add Contact to Contact List");
alert.setHeaderText("Add the user " + chat.getRecipient().getName() + " to your contact list?"); alert.setHeaderText("Add the user " + user.getName() + " to your contact list?");
// Normally, this would be total BS (we are already on the FX Thread), however // Normally, this would be total BS (we are already on the FX Thread), however
// it could be proven that the creation of this dialog wrapped in // it could be proven that the creation of this dialog wrapped in
// Platform.runLater is less error-prone than without it // Platform.runLater is less error-prone than without it
Platform.runLater(() -> alert.showAndWait().filter(btn -> btn == ButtonType.OK).ifPresent(btn -> { Platform.runLater(() -> alert.showAndWait().filter(btn -> btn == ButtonType.OK).ifPresent(btn -> {
final var event = new ContactOperation(chat.getRecipient(), ElementOperation.ADD); final var event = new ContactOperation(user, ElementOperation.ADD);
// Sends the event to the server // Sends the event to the server
eventBus.dispatch(new SendEvent(event)); eventBus.dispatch(new SendEvent(event));
// Updates the UI // Updates the UI
eventBus.dispatch(event); eventBus.dispatch(event);
logger.log(Level.INFO, "Added contact " + chat.getRecipient()); logger.log(Level.INFO, "Added user " + user);
})); }));
} }
} }

View File

@ -1,5 +1,7 @@
package envoy.client.ui.controller; package envoy.client.ui.controller;
import static java.util.function.Predicate.not;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javafx.application.Platform; import javafx.application.Platform;
@ -13,14 +15,22 @@ import envoy.client.event.SendEvent;
import envoy.client.ui.ClearableTextField; import envoy.client.ui.ClearableTextField;
import envoy.client.ui.SceneContext; import envoy.client.ui.SceneContext;
import envoy.client.ui.listcell.ContactListCellFactory; import envoy.client.ui.listcell.ContactListCellFactory;
import envoy.data.Group; import envoy.data.User;
import envoy.event.EventBus; import envoy.event.EventBus;
import envoy.event.GroupCreation; import envoy.event.GroupCreation;
import envoy.util.Bounds; 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).
* <p>
* 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).
* <p>
* Project: <strong>envoy-client</strong><br> * Project: <strong>envoy-client</strong><br>
* File: <strong>ContactSearchSceneController.java</strong><br> * File: <strong>GroupCreationScene.java</strong><br>
* Created: <strong>07.06.2020</strong><br> * Created: <strong>07.06.2020</strong><br>
* *
* @author Maximilian K&auml;fer * @author Maximilian K&auml;fer
@ -35,7 +45,7 @@ public class GroupCreationScene {
private ClearableTextField groupNameField; private ClearableTextField groupNameField;
@FXML @FXML
private ListView<Chat> chatList; private ListView<User> userList;
private SceneContext sceneContext; private SceneContext sceneContext;
@ -43,8 +53,8 @@ public class GroupCreationScene {
@FXML @FXML
private void initialize() { private void initialize() {
chatList.setCellFactory(ContactListCellFactory::new); userList.setCellFactory(new ContactListCellFactory<>());
chatList.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); userList.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
groupNameField.setClearButtonListener(e -> { groupNameField.getTextField().clear(); createButton.setDisable(true); }); groupNameField.setClearButtonListener(e -> { groupNameField.getTextField().clear(); createButton.setDisable(true); });
} }
@ -56,11 +66,13 @@ public class GroupCreationScene {
*/ */
public void initializeData(SceneContext sceneContext, LocalDB localDB) { public void initializeData(SceneContext sceneContext, LocalDB localDB) {
this.sceneContext = sceneContext; this.sceneContext = sceneContext;
Platform.runLater(() -> chatList.getItems() Platform.runLater(() -> userList.getItems()
.addAll(localDB.getChats() .addAll(localDB.getChats()
.stream() .stream()
.filter(c -> !(c.getRecipient() instanceof Group)) .map(Chat::getRecipient)
.filter(c -> c.getRecipient().getID() != localDB.getUser().getID()) .filter(User.class::isInstance)
.filter(not(localDB.getUser()::equals))
.map(User.class::cast)
.collect(Collectors.toList()))); .collect(Collectors.toList())));
} }
@ -71,12 +83,12 @@ public class GroupCreationScene {
*/ */
@FXML @FXML
private void chatListClicked() { private void chatListClicked() {
createButton.setDisable(chatList.getSelectionModel().isEmpty() || groupNameField.getTextField().getText().isBlank()); createButton.setDisable(userList.getSelectionModel().isEmpty() || groupNameField.getTextField().getText().isBlank());
} }
/** /**
* Checks, whether the {@code createButton} can be enabled because text is * Checks, whether the {@code createButton} can be enabled because text is
* present in the textfield. * present in the text field.
* *
* @since Envoy Client v0.1-beta * @since Envoy Client v0.1-beta
*/ */
@ -97,8 +109,8 @@ public class GroupCreationScene {
new Alert(AlertType.ERROR, "The entered group name is not valid (" + Bounds.CONTACT_NAME_PATTERN + ")").showAndWait(); new Alert(AlertType.ERROR, "The entered group name is not valid (" + Bounds.CONTACT_NAME_PATTERN + ")").showAndWait();
groupNameField.getTextField().clear(); groupNameField.getTextField().clear();
} else { } else {
eventBus.dispatch(new SendEvent(new GroupCreation(name, eventBus.dispatch(new SendEvent(
chatList.getSelectionModel().getSelectedItems().stream().map(c -> c.getRecipient().getID()).collect(Collectors.toSet())))); new GroupCreation(name, userList.getSelectionModel().getSelectedItems().stream().map(User::getID).collect(Collectors.toSet()))));
new Alert(AlertType.INFORMATION, String.format("Group '%s' successfully created.", name)).showAndWait(); new Alert(AlertType.INFORMATION, String.format("Group '%s' successfully created.", name)).showAndWait();
sceneContext.pop(); sceneContext.pop();
} }

View File

@ -0,0 +1,44 @@
package envoy.client.ui.listcell;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import envoy.client.data.Chat;
/**
* Project: <strong>envoy-client</strong><br>
* File: <strong>ChatListCellFactory.java</strong><br>
* Created: <strong>28.03.2020</strong><br>
*
* @author Kai S. K. Engelbart
* @since Envoy Client v0.1-beta
*/
public class ChatListCellFactory extends ListCell<Chat> {
private final ListView<Chat> listView;
/**
* @param listView the list view inside which this cell is contained
* @since Envoy Client v0.1-beta
*/
public ChatListCellFactory(ListView<Chat> listView) { this.listView = listView; }
/**
* Displays the name of a contact. If the contact is a user, their online status
* is displayed as well.
*
* @since Envoy Client v0.1-beta
*/
@Override
protected void updateItem(Chat chat, boolean empty) {
super.updateItem(chat, empty);
if (empty || chat.getRecipient() == null) {
setText(null);
setGraphic(null);
} else {
final var control = new ChatControl(chat);
prefWidthProperty().bind(listView.widthProperty().subtract(40));
setGraphic(control);
}
}
}

View File

@ -28,7 +28,6 @@ public class ContactControl extends VBox {
// Name label // Name label
final var nameLabel = new Label(contact.getName()); final var nameLabel = new Label(contact.getName());
nameLabel.setWrapText(true);
getChildren().add(nameLabel); getChildren().add(nameLabel);
// Online status (user) or member count (group) // Online status (user) or member count (group)

View File

@ -2,43 +2,51 @@ package envoy.client.ui.listcell;
import javafx.scene.control.ListCell; import javafx.scene.control.ListCell;
import javafx.scene.control.ListView; import javafx.scene.control.ListView;
import javafx.util.Callback;
import envoy.client.data.Chat; import envoy.data.Contact;
/** /**
* Project: <strong>envoy-client</strong><br> * Project: <strong>envoy-client</strong><br>
* File: <strong>UserListCell.java</strong><br> * File: <strong>ContactListCellFactory.java</strong><br>
* Created: <strong>28.03.2020</strong><br> * Created: <strong>13.07.2020</strong><br>
* *
* @author Kai S. K. Engelbart * @author Kai S. K. Engelbart
* @param <T> the type of contact to display
* @since Envoy Client v0.1-beta * @since Envoy Client v0.1-beta
*/ */
public class ContactListCellFactory extends ListCell<Chat> { public class ContactListCellFactory<T extends Contact> implements Callback<ListView<T>, ListCell<T>> {
private final ListView<Chat> listView;
/** /**
* @param listView the list view inside which this cell is contained * Wraps a the {@link ContactControl} inside a list cell.
* @since Envoy Client v0.1-beta
*/
public ContactListCellFactory(ListView<Chat> listView) { this.listView = listView; }
/**
* Displays the name of a contact. If the contact is a user, their online status
* is displayed as well.
* *
* @param <T> the type of contact to display
* @since Envoy Client v0.1-beta * @since Envoy Client v0.1-beta
*/ */
@Override public static final class ContactListCell<T extends Contact> extends ListCell<T> {
protected void updateItem(Chat chat, boolean empty) {
super.updateItem(chat, empty); private final ListView<T> listView;
if (empty || chat.getRecipient() == null) {
setText(null); /**
setGraphic(null); * @param listView the list view containing this list cell
} else { * @since Envoy Client v0.1-beta
final var control = new ChatControl(chat); */
prefWidthProperty().bind(listView.widthProperty().subtract(40)); public ContactListCell(ListView<T> listView) { this.listView = listView; }
setGraphic(control);
@Override
protected void updateItem(T contact, boolean empty) {
super.updateItem(contact, empty);
if (empty || contact == null) {
setText(null);
setGraphic(null);
} else {
final var control = new ContactControl(contact);
prefWidthProperty().bind(listView.widthProperty().subtract(40));
setGraphic(control);
}
} }
} }
@Override
public ListCell<T> call(ListView<T> listView) { return new ContactListCell<>(listView); }
} }

View File

@ -8,19 +8,12 @@
<?import javafx.scene.layout.HBox?> <?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" <VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="envoy.client.ui.controller.ContactSearchScene">
minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0"
prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="envoy.client.ui.controller.ContactSearchScene">
<children> <children>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0"> <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0">
<children> <children>
<ClearableTextField fx:id="searchBar" <ClearableTextField fx:id="searchBar" prefWidth="310.0">
prefWidth="310.0"> <textField onInputMethodTextChanged="#sendRequest" onKeyTyped="#sendRequest" prefColumnCount="22" promptText="Enter username to search for">
<textField onInputMethodTextChanged="#sendRequest"
onKeyTyped="#sendRequest" prefColumnCount="22"
promptText="Enter username to search for">
</textField> </textField>
<HBox.margin> <HBox.margin>
<Insets bottom="5.0" left="5.0" right="5.0" top="15.0" /> <Insets bottom="5.0" left="5.0" right="5.0" top="15.0" />
@ -29,14 +22,10 @@
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" /> <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding> </padding>
<tooltip> <tooltip>
<Tooltip <Tooltip text="Enter a name. If an account by that name exists, it will be displayed below." wrapText="true" />
text="Enter a name. If an account by that name exists, it will be displayed below."
wrapText="true" />
</tooltip> </tooltip>
</ClearableTextField> </ClearableTextField>
<Button mnemonicParsing="false" <Button mnemonicParsing="false" onAction="#newGroupButtonClicked" prefHeight="26.0" prefWidth="139.0" text="New Group">
onAction="#newGroupButtonClicked" prefHeight="26.0"
prefWidth="139.0" text="New Group">
<HBox.margin> <HBox.margin>
<Insets bottom="5.0" left="30.0" right="5.0" top="5.0" /> <Insets bottom="5.0" left="30.0" right="5.0" top="5.0" />
</HBox.margin> </HBox.margin>
@ -46,9 +35,7 @@
</Button> </Button>
</children> </children>
</HBox> </HBox>
<ListView fx:id="chatList" <ListView fx:id="userList" onMouseClicked="#chatListClicked" prefHeight="314.0" prefWidth="600.0">
onMouseClicked="#chatListClicked" prefHeight="314.0"
prefWidth="600.0">
<padding> <padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" /> <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding> </padding>
@ -56,8 +43,7 @@
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</VBox.margin> </VBox.margin>
</ListView> </ListView>
<Button cancelButton="true" mnemonicParsing="true" <Button cancelButton="true" mnemonicParsing="true" onAction="#backButtonClicked" text="_Back">
onAction="#backButtonClicked" text="_Back">
<VBox.margin> <VBox.margin>
<Insets bottom="10.0" left="10.0" /> <Insets bottom="10.0" left="10.0" />
</VBox.margin> </VBox.margin>
@ -65,9 +51,7 @@
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" /> <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding> </padding>
<tooltip> <tooltip>
<Tooltip autoHide="true" <Tooltip autoHide="true" text="Takes you back to the screen where you can chat with others" wrapText="true" />
text="Takes you back to the screen where you can chat with others"
wrapText="true" />
</tooltip> </tooltip>
</Button> </Button>
</children> </children>

View File

@ -11,18 +11,12 @@
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?> <?import javafx.scene.text.Font?>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" <VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="envoy.client.ui.controller.GroupCreationScene">
minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0"
prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="envoy.client.ui.controller.GroupCreationScene">
<children> <children>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0"> <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0">
<children> <children>
<ClearableTextField fx:id="groupNameField"> <ClearableTextField fx:id="groupNameField">
<textField prefColumnCount="22" <textField onInputMethodTextChanged="#textUpdated" onKeyTyped="#textUpdated" prefColumnCount="22" promptText="Enter Group Name" />
promptText="Enter Group Name"
onInputMethodTextChanged="#textUpdated" onKeyTyped="#textUpdated" />
<HBox.margin> <HBox.margin>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" /> <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</HBox.margin> </HBox.margin>
@ -30,9 +24,7 @@
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" /> <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding> </padding>
<tooltip> <tooltip>
<Tooltip <Tooltip text="Enter something. A group with this name will be created." wrapText="true" />
text="Enter something. A group with this name will be created."
wrapText="true" />
</tooltip> </tooltip>
</ClearableTextField> </ClearableTextField>
</children> </children>
@ -45,9 +37,7 @@
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" /> <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding> </padding>
</Label> </Label>
<ListView fx:id="chatList" <ListView fx:id="userList" onMouseClicked="#chatListClicked" prefHeight="314.0" prefWidth="600.0">
onMouseClicked="#chatListClicked" prefHeight="314.0"
prefWidth="600.0">
<VBox.margin> <VBox.margin>
<Insets bottom="5.0" left="10.0" right="10.0" top="5.0" /> <Insets bottom="5.0" left="10.0" right="10.0" top="5.0" />
</VBox.margin> </VBox.margin>
@ -57,16 +47,12 @@
</ListView> </ListView>
<BorderPane prefHeight="50.0"> <BorderPane prefHeight="50.0">
<left> <left>
<Button cancelButton="true" mnemonicParsing="true" <Button cancelButton="true" mnemonicParsing="true" onAction="#backButtonClicked" text="_Back" BorderPane.alignment="CENTER">
onAction="#backButtonClicked" text="_Back"
BorderPane.alignment="CENTER">
<padding> <padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" /> <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding> </padding>
<tooltip> <tooltip>
<Tooltip autoHide="true" <Tooltip autoHide="true" text="Takes you back to the screen where you can chat with others" wrapText="true" />
text="Takes you back to the screen where you can chat with others"
wrapText="true" />
</tooltip> </tooltip>
<BorderPane.margin> <BorderPane.margin>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
@ -74,10 +60,7 @@
</Button> </Button>
</left> </left>
<right> <right>
<Button fx:id="createButton" alignment="CENTER_RIGHT" <Button fx:id="createButton" alignment="CENTER_RIGHT" defaultButton="true" disable="true" mnemonicParsing="false" onAction="#createButtonClicked" text="Create" BorderPane.alignment="CENTER">
defaultButton="true" disable="true" mnemonicParsing="false"
onAction="#createButtonClicked" text="Create"
BorderPane.alignment="CENTER">
<padding> <padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" /> <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding> </padding>

View File

@ -1,26 +0,0 @@
package envoy.event.contact;
import envoy.event.Event;
/**
* Requests a contact search from the server.<br>
* <br>
* Project: <strong>envoy-common</strong><br>
* File: <strong>ContactSearchRequest.java</strong><br>
* Created: <strong>05.02.2020</strong><br>
*
* @author Maximilian K&auml;fer
* @since Envoy Common v0.2-alpha
*/
public class ContactSearchRequest extends Event<String> {
private static final long serialVersionUID = 0L;
/**
* Initializes a {@link ContactSearchRequest}.
*
* @param searchPhrase the search phrase to use in the contact search
* @since Envoy Common v0.2-alpha
*/
public ContactSearchRequest(String searchPhrase) { super(searchPhrase); }
}

View File

@ -0,0 +1,26 @@
package envoy.event.contact;
import envoy.event.Event;
/**
* Requests a user search from the server.
* <p>
* Project: <strong>envoy-common</strong><br>
* File: <strong>UserSearchRequest.java</strong><br>
* Created: <strong>05.02.2020</strong><br>
*
* @author Maximilian K&auml;fer
* @since Envoy Common v0.2-alpha
*/
public class UserSearchRequest extends Event<String> {
private static final long serialVersionUID = 0L;
/**
* Initializes a {@link UserSearchRequest}.
*
* @param searchPhrase the search phrase to use in the user search
* @since Envoy Common v0.2-alpha
*/
public UserSearchRequest(String searchPhrase) { super(searchPhrase); }
}

View File

@ -2,28 +2,28 @@ package envoy.event.contact;
import java.util.List; import java.util.List;
import envoy.data.Contact; import envoy.data.User;
import envoy.event.Event; import envoy.event.Event;
/** /**
* Contains a list of {@link Contact}s for which a search was performed.<br> * Contains a list of users for which a search has been requested.
* <br> * <p>
* Project: <strong>envoy-common</strong><br> * Project: <strong>envoy-common</strong><br>
* File: <strong>ContactSearchResult.java</strong><br> * File: <strong>UserSearchResult.java</strong><br>
* Created: <strong>11 Feb 2020</strong><br> * Created: <strong>11 Feb 2020</strong><br>
* *
* @author Kai S. K. Engelbart * @author Kai S. K. Engelbart
* @since Envoy Common v0.2-alpha * @since Envoy Common v0.2-alpha
*/ */
public class ContactSearchResult extends Event<List<Contact>> { public class UserSearchResult extends Event<List<User>> {
private static final long serialVersionUID = 0L; private static final long serialVersionUID = 0L;
/** /**
* Creates an instance of {@link ContactSearchResult}. * Creates an instance of {@link UserSearchResult}.
* *
* @param users the users found during the search * @param users the users found during the search
* @since Envoy Common v0.2-alpha * @since Envoy Common v0.2-alpha
*/ */
public ContactSearchResult(List<Contact> users) { super(users); } public UserSearchResult(List<User> users) { super(users); }
} }

View File

@ -4,8 +4,8 @@ import java.io.IOException;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import envoy.data.Contact; import envoy.data.Contact;
import envoy.event.contact.ContactSearchRequest; import envoy.event.contact.UserSearchRequest;
import envoy.event.contact.ContactSearchResult; import envoy.event.contact.UserSearchResult;
import envoy.server.data.PersistenceManager; import envoy.server.data.PersistenceManager;
import envoy.server.data.User; import envoy.server.data.User;
import envoy.server.net.ConnectionManager; import envoy.server.net.ConnectionManager;
@ -20,7 +20,7 @@ import envoy.server.net.ObjectWriteProxy;
* @author Maximilian K&auml;fer * @author Maximilian K&auml;fer
* @since Envoy Server Standalone v0.1-alpha * @since Envoy Server Standalone v0.1-alpha
*/ */
public class ContactSearchProcessor implements ObjectProcessor<ContactSearchRequest> { public class ContactSearchProcessor implements ObjectProcessor<UserSearchRequest> {
/** /**
* Writes a list of contacts to the client containing all {@link Contact}s * Writes a list of contacts to the client containing all {@link Contact}s
@ -30,9 +30,9 @@ public class ContactSearchProcessor implements ObjectProcessor<ContactSearchRequ
* @since Envoy Server Standalone v0.1-alpha * @since Envoy Server Standalone v0.1-alpha
*/ */
@Override @Override
public void process(ContactSearchRequest request, long socketID, ObjectWriteProxy writeProxy) throws IOException { public void process(UserSearchRequest request, long socketID, ObjectWriteProxy writeProxy) throws IOException {
writeProxy.write(socketID, writeProxy.write(socketID,
new ContactSearchResult(PersistenceManager.getInstance() new UserSearchResult(PersistenceManager.getInstance()
.searchUsers(request.get(), ConnectionManager.getInstance().getUserIDBySocketID(socketID)) .searchUsers(request.get(), ConnectionManager.getInstance().getUserIDBySocketID(socketID))
.stream() .stream()
.map(User::toCommon) .map(User::toCommon)
@ -40,5 +40,5 @@ public class ContactSearchProcessor implements ObjectProcessor<ContactSearchRequ
} }
@Override @Override
public Class<ContactSearchRequest> getInputClass() { return ContactSearchRequest.class; } public Class<UserSearchRequest> getInputClass() { return UserSearchRequest.class; }
} }