Moved former ListCell#updateItem methods into separate Control objects

Additionally fixed bug showing wrong color of infoLabel after switching
scenes
This commit is contained in:
delvh 2020-07-01 19:35:15 +02:00
parent 2c00539f8a
commit 74734777cd
11 changed files with 242 additions and 160 deletions

View File

@ -164,4 +164,11 @@ public class ClearableTextField extends GridPane {
* @since Envoy Client v0.1-beta
*/
public final BooleanProperty editableProperty() { return textField.editableProperty(); }
/**
* @return whether this {@code ClearableTextField} is editable
* @see javafx.scene.control.TextInputControl#isEditable()
* @since Envoy Client v0.1-beta
*/
public final boolean isEditable() { return textField.isEditable(); }
}

View File

@ -16,7 +16,6 @@ import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import envoy.client.data.Chat;
import envoy.client.data.LocalDB;
@ -26,8 +25,9 @@ import envoy.client.net.Client;
import envoy.client.net.WriteProxy;
import envoy.client.ui.IconUtil;
import envoy.client.ui.SceneContext;
import envoy.client.ui.listcell.ContactListCell;
import envoy.client.ui.listcell.MessageListCell;
import envoy.client.ui.listcell.ContactListCellFactory;
import envoy.client.ui.listcell.MessageControl;
import envoy.client.ui.listcell.MessageListCellFactory;
import envoy.data.*;
import envoy.event.EventBus;
import envoy.event.MessageStatusChange;
@ -95,8 +95,8 @@ public final class ChatScene {
private void initialize() {
// Initialize message and user rendering
messageList.setCellFactory(MessageListCell::new);
userList.setCellFactory(ContactListCell::new);
messageList.setCellFactory(MessageListCellFactory::new);
userList.setCellFactory(ContactListCellFactory::new);
settingsButton.setGraphic(new ImageView(IconUtil.load("/icons/settings.png", 16)));
@ -169,8 +169,8 @@ public final class ChatScene {
userList.setItems(FXCollections.observableList(localDB.getChats().stream().map(Chat::getRecipient).collect(Collectors.toList())));
contactLabel.setText(localDB.getUser().getName());
MessageListCell.setUser(localDB.getUser());
if (!client.isOnline()) updateInfoLabel("You are offline", Color.YELLOW);
MessageControl.setUser(localDB.getUser());
if (!client.isOnline()) updateInfoLabel("You are offline", "infoLabel-info");
}
/**
@ -182,7 +182,6 @@ public final class ChatScene {
private void userListClicked() {
final Contact user = userList.getSelectionModel().getSelectedItem();
if (user != null && (currentChat == null || !user.equals(currentChat.getRecipient()))) {
logger.log(Level.FINEST, "Loading chat with " + user);
// LEON: JFC <===> JAVA FRIED CHICKEN <=/=> Java Foundation Classes
@ -190,6 +189,9 @@ public final class ChatScene {
currentChat = localDB.getChat(user.getID()).get();
messageList.setItems(FXCollections.observableList(currentChat.getMessages()));
final var scrollIndex = messageList.getItems().size() - 1;
messageList.scrollTo(scrollIndex);
logger.log(Level.FINEST, "Loading chat with " + user + " at index " + scrollIndex);
deleteContactMenuItem.setText("Delete " + user.getName());
// Read the current chat
@ -260,7 +262,7 @@ public final class ChatScene {
if (!infoLabel.getText().equals(noMoreMessaging))
// Informing the user that he is a f*cking moron and should use Envoy online
// because he ran out of messageIDs to use
updateInfoLabel(noMoreMessaging, Color.RED);
updateInfoLabel(noMoreMessaging, "infoLabel-error");
}
}
@ -305,7 +307,7 @@ public final class ChatScene {
postButton.setDisable(true);
messageTextArea.setDisable(true);
messageTextArea.clear();
updateInfoLabel("You need to go online to send more messages", Color.RED);
updateInfoLabel("You need to go online to send more messages", "infoLabel-error");
return;
}
final var text = messageTextArea.getText().strip();
@ -347,13 +349,14 @@ public final class ChatScene {
/**
* Updates the {@code infoLabel}.
*
* @param text the text to use
* @param textfill the color in which to display information
* @param text the text to use
* @param infoLabelID the id the the {@code infoLabel} should have so that it
* can be styled accordingly in CSS
* @since Envoy Client v0.1-beta
*/
private void updateInfoLabel(String text, Paint textfill) {
private void updateInfoLabel(String text, String infoLabelID) {
infoLabel.setText(text);
infoLabel.setTextFill(textfill);
infoLabel.setId(infoLabelID);
infoLabel.setVisible(true);
}

View File

@ -14,7 +14,7 @@ import envoy.client.data.LocalDB;
import envoy.client.event.SendEvent;
import envoy.client.ui.ClearableTextField;
import envoy.client.ui.SceneContext;
import envoy.client.ui.listcell.ContactListCell;
import envoy.client.ui.listcell.ContactListCellFactory;
import envoy.data.Contact;
import envoy.event.ElementOperation;
import envoy.event.EventBus;
@ -58,7 +58,7 @@ public class ContactSearchScene {
@FXML
private void initialize() {
contactList.setCellFactory(ContactListCell::new);
contactList.setCellFactory(ContactListCellFactory::new);
searchBar.setClearButtonListener(e -> { searchBar.getTextField().clear(); contactList.getItems().clear(); });
eventBus.register(ContactSearchResult.class,
response -> Platform.runLater(() -> { contactList.getItems().clear(); contactList.getItems().addAll(response.get()); }));

View File

@ -11,7 +11,7 @@ import envoy.client.data.LocalDB;
import envoy.client.event.SendEvent;
import envoy.client.ui.ClearableTextField;
import envoy.client.ui.SceneContext;
import envoy.client.ui.listcell.ContactListCell;
import envoy.client.ui.listcell.ContactListCellFactory;
import envoy.data.Contact;
import envoy.event.EventBus;
import envoy.event.GroupCreation;
@ -42,7 +42,7 @@ public class GroupCreationScene {
@FXML
private void initialize() {
contactList.setCellFactory(ContactListCell::new);
contactList.setCellFactory(ContactListCellFactory::new);
contactList.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
groupNameField.setClearButtonListener(e -> { groupNameField.getTextField().clear(); createButton.setDisable(true); });
}

View File

@ -0,0 +1,41 @@
package envoy.client.ui.listcell;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import envoy.data.Contact;
import envoy.data.Group;
import envoy.data.User;
/**
* This class formats a single {@link Contact} into a UI component.
* <p>
* Project: <strong>envoy-client</strong><br>
* File: <strong>ContactControl.java</strong><br>
* Created: <strong>01.07.2020</strong><br>
*
* @author Leon Hofmeister
* @since Envoy Client v0.1-beta
*/
public class ContactControl extends VBox {
/**
*
* @param contact the contact that should be formatted
* @since Envoy Client v0.1-beta
*/
public ContactControl(Contact contact) {
// Container with contact name
final var nameLabel = new Label(contact.getName());
nameLabel.setWrapText(true);
getChildren().add(nameLabel);
if (contact instanceof User) {
// Online status
final var user = (User) contact;
final var statusLabel = new Label(user.getStatus().toString());
statusLabel.getStyleClass().add(user.getStatus().toString().toLowerCase());
getChildren().add(statusLabel);
} else // Member count
getChildren().add(new Label(((Group) contact).getContacts().size() + " members"));
}
}

View File

@ -1,59 +0,0 @@
package envoy.client.ui.listcell;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.layout.VBox;
import envoy.data.Contact;
import envoy.data.Group;
import envoy.data.User;
/**
* Project: <strong>envoy-client</strong><br>
* File: <strong>UserListCell.java</strong><br>
* Created: <strong>28.03.2020</strong><br>
*
* @author Kai S. K. Engelbart
* @since Envoy Client v0.1-beta
*/
public class ContactListCell extends ListCell<Contact> {
private final ListView<Contact> listView;
/**
* @param listView the list view inside which this cell is contained
* @since Envoy Client v0.1-beta
*/
public ContactListCell(ListView<Contact> 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(Contact contact, boolean empty) {
super.updateItem(contact, empty);
if (empty || contact == null) {
setText(null);
setGraphic(null);
} else {
// Container with contact name
final var nameLabel = new Label(contact.getName());
nameLabel.setWrapText(true);
final var vbox = new VBox(nameLabel);
if (contact instanceof User) {
// Online status
final var user = (User) contact;
final var statusLabel = new Label(user.getStatus().toString());
statusLabel.getStyleClass().add(user.getStatus().toString().toLowerCase());
vbox.getChildren().add(statusLabel);
} else // Member count
vbox.getChildren().add(new Label(((Group) contact).getContacts().size() + " members"));
if (listView != null) prefWidthProperty().bind(listView.widthProperty().subtract(40));
setGraphic(vbox);
}
}
}

View File

@ -0,0 +1,44 @@
package envoy.client.ui.listcell;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import envoy.data.Contact;
/**
* Project: <strong>envoy-client</strong><br>
* File: <strong>UserListCell.java</strong><br>
* Created: <strong>28.03.2020</strong><br>
*
* @author Kai S. K. Engelbart
* @since Envoy Client v0.1-beta
*/
public class ContactListCellFactory extends ListCell<Contact> {
private final ListView<Contact> listView;
/**
* @param listView the list view inside which this cell is contained
* @since Envoy Client v0.1-beta
*/
public ContactListCellFactory(ListView<Contact> 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(Contact 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);
}
}
}

View File

@ -0,0 +1,60 @@
package envoy.client.ui.listcell;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import javafx.geometry.Insets;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.VBox;
import envoy.client.ui.IconUtil;
import envoy.data.Message;
import envoy.data.Message.MessageStatus;
import envoy.data.User;
/**
* This class formats a single {@link Message} into a UI component.
* <p>
* Project: <strong>envoy-client</strong><br>
* File: <strong>MessageControl.java</strong><br>
* Created: <strong>01.07.2020</strong><br>
*
* @author Leon Hofmeister
* @since Envoy Client v0.1-beta
*/
public class MessageControl extends VBox {
private static User client;
private static final DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm");
private static final Map<MessageStatus, Image> statusImages = IconUtil.loadByEnum(MessageStatus.class, 16);
/**
*
* @param message the message that should be formatted
* @since Envoy Client v0.1-beta
*/
public MessageControl(Message message) {
// Creating the underlying VBox, the dateLabel and the textLabel
super(new Label(dateFormat.format(message.getCreationDate())));
final var textLabel = new Label(message.getText());
textLabel.setWrapText(true);
getChildren().add(textLabel);
// Setting the message status icon and background color
if (message.getRecipientID() != client.getID()) {
final var statusIcon = new ImageView(statusImages.get(message.getStatus()));
statusIcon.setPreserveRatio(true);
getChildren().add(statusIcon);
getStyleClass().add("own-message");
} else getStyleClass().add("received-message");
// Adjusting height and weight of the cell to the corresponding ListView
paddingProperty().setValue(new Insets(5, 20, 5, 20));
}
/**
* @param client the user who has logged in
* @since Envoy Client v0.1-beta
*/
public static void setUser(User client) { MessageControl.client = client; }
}

View File

@ -1,82 +0,0 @@
package envoy.client.ui.listcell;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import javafx.geometry.Insets;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.VBox;
import javafx.stage.PopupWindow.AnchorLocation;
import envoy.client.ui.IconUtil;
import envoy.data.Message;
import envoy.data.Message.MessageStatus;
import envoy.data.User;
/**
* Displays a single message inside the message list.
* <p>
* Project: <strong>envoy-client</strong><br>
* File: <strong>MessageListCell.java</strong><br>
* Created: <strong>28.03.2020</strong><br>
*
* @author Kai S. K. Engelbart
* @since Envoy Client v0.1-beta
*/
public class MessageListCell extends ListCell<Message> {
private final ListView<Message> listView;
private static User client;
private static final DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm");
private static final Map<MessageStatus, Image> statusImages = IconUtil.loadByEnum(MessageStatus.class, 16);
/**
* @param listView the list view inside which this cell is contained
* @since Envoy Client v0.1-beta
*/
public MessageListCell(ListView<Message> listView) { this.listView = listView; }
/**
* Displays the text, the data of creation and the status of a message.
*
* @since Envoy v0.1-beta
*/
@Override
protected void updateItem(Message message, boolean empty) {
super.updateItem(message, empty);
if (empty || message == null) {
setText(null);
setGraphic(null);
} else {
// Creating the underlying VBox, the dateLabel and the textLabel
final var cell = new VBox(new Label(dateFormat.format(message.getCreationDate())));
final var textLabel = new Label(message.getText());
textLabel.setWrapText(true);
cell.getChildren().add(textLabel);
// Setting the message status icon and background color
if (message.getRecipientID() != client.getID()) {
final var statusIcon = new ImageView(statusImages.get(message.getStatus()));
cell.getChildren().add(statusIcon);
cell.getStyleClass().add("own-message");
} else cell.getStyleClass().add("received-message");
// Adjusting height and weight of the cell to the corresponding ListView
cell.paddingProperty().setValue(new Insets(5, 20, 5, 20));
if (listView != null) cell.prefWidthProperty().bind(listView.widthProperty().subtract(40));
// Creating the Tooltip to deselect a message
final var tooltip = new Tooltip("You can select a message by clicking on it \nand deselect it by pressing \"ctrl\" and clicking on it");
tooltip.setWrapText(true);
tooltip.setAnchorLocation(AnchorLocation.WINDOW_TOP_LEFT);
setTooltip(tooltip);
setGraphic(cell);
}
}
/**
* @param client the user who chats with another person
* @since Envoy Client v0.1-beta
*/
public static void setUser(User client) { MessageListCell.client = client; }
}

View File

@ -0,0 +1,52 @@
package envoy.client.ui.listcell;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.Tooltip;
import javafx.stage.PopupWindow.AnchorLocation;
import envoy.data.Message;
/**
* Displays a single message inside the message list.
* <p>
* Project: <strong>envoy-client</strong><br>
* File: <strong>MessageListCellFactory.java</strong><br>
* Created: <strong>28.03.2020</strong><br>
*
* @author Kai S. K. Engelbart
* @since Envoy Client v0.1-beta
*/
public class MessageListCellFactory extends ListCell<Message> {
private final ListView<Message> listView;
/**
* @param listView the list view inside which this cell is contained
* @since Envoy Client v0.1-beta
*/
public MessageListCellFactory(ListView<Message> listView) { this.listView = listView; }
/**
* Displays the text, the data of creation and the status of a message.
*
* @since Envoy v0.1-beta
*/
@Override
protected void updateItem(Message message, boolean empty) {
super.updateItem(message, empty);
if (empty || message == null) {
setText(null);
setGraphic(null);
} else {
final var control = new MessageControl(message);
control.prefWidthProperty().bind(listView.widthProperty().subtract(40));
// Creating the Tooltip to deselect a message
final var tooltip = new Tooltip("You can select a message by clicking on it \nand deselect it by pressing \"ctrl\" and clicking on it");
tooltip.setWrapText(true);
tooltip.setAnchorLocation(AnchorLocation.WINDOW_TOP_LEFT);
setTooltip(tooltip);
setGraphic(control);
}
}
}

View File

@ -3,7 +3,7 @@
}
.context-menu, .context-menu > * {
-fx-background-radius: 15px;
-fx-background-radius: 15.0px;
/*TODO: solution below does not work */
-fx-background-color: transparent;
}
@ -58,3 +58,19 @@
-fx-text-fill: #00FF00;
-fx-background-color: transparent;
}
#infoLabel-success {
-fx-text-fill: #00FF00;
}
#infoLabel-info {
-fx-text-fill: yellow;
}
#infoLabel-warning {
-fx-text-fill: orange;
}
#infoLabel-error {
-fx-text-fill: red;
}