From 63aa7859d3ccb55a75cc8c0442d8944d0d456388 Mon Sep 17 00:00:00 2001 From: delvh Date: Sat, 27 Jun 2020 15:35:35 +0200 Subject: [PATCH 01/19] Added working ClearableTextField additionally designed the clear button icon both in black and white --- .../envoy/client/ui/ClearableTextField.java | 252 ++++++++++++++++++ .../resources/icons/clear_button_black.png | Bin 0 -> 4258 bytes .../resources/icons/clear_button_white.png | Bin 0 -> 3919 bytes 3 files changed, 252 insertions(+) create mode 100644 src/main/java/envoy/client/ui/ClearableTextField.java create mode 100644 src/main/resources/icons/clear_button_black.png create mode 100644 src/main/resources/icons/clear_button_white.png diff --git a/src/main/java/envoy/client/ui/ClearableTextField.java b/src/main/java/envoy/client/ui/ClearableTextField.java new file mode 100644 index 0000000..adc5f94 --- /dev/null +++ b/src/main/java/envoy/client/ui/ClearableTextField.java @@ -0,0 +1,252 @@ +package envoy.client.ui; + +import javafx.beans.property.IntegerProperty; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.StringProperty; +import javafx.geometry.Insets; +import javafx.geometry.Pos; +import javafx.scene.control.*; +import javafx.scene.image.ImageView; +import javafx.scene.layout.Background; +import javafx.scene.layout.ColumnConstraints; +import javafx.scene.layout.GridPane; +import javafx.scene.text.Font; + +import envoy.client.data.Settings; + +/** + * This class offers a text field that is automatically equipped with a clear + * button. + *

+ * Project: envoy-client
+ * File: ClearableTextField.java
+ * Created: 25.06.2020
+ * + * @author Leon Hofmeister + * @since Envoy Client v0.1-beta + */ +@SuppressWarnings("javadoc") +public class ClearableTextField extends GridPane { + + private final TextField textField; + + private final Button clearButton; + + /** + * Constructs a new {@code ClearableTextField} with no initial text and icon + * size 16. + * + * @since Envoy Client v0.1-beta + */ + public ClearableTextField() { this("", 16); } + + /** + * Constructs a new {@code ClearableTextField} with initial text and a + * predetermined icon size. + * + * @param text the text that should be displayed by default + * @param size the size of the icon + * @since Envoy Client v0.1-beta + */ + public ClearableTextField(String text, int size) { + // initializing the textField and the button + textField = new TextField(text); + clearButton = new Button("", + new ImageView(IconUtil.load( + Settings.getInstance().getCurrentTheme().equals("dark") ? "/icons/clear_button_white.png" : "/icons/clear_button_black.png", + size))); + clearButton.setOnAction(e -> textField.clear()); + clearButton.getStyleClass().clear(); + clearButton.setBackground(Background.EMPTY); + // Adding the two elements to the GridPane + add(textField, 0, 0, 2, 1); + add(clearButton, 1, 0, 1, 1); + // Setting the percent - widths of the two columns. + // Used to locate the button on the right. + final var columnConstraints = new ColumnConstraints(); + columnConstraints.setPercentWidth(85); + getColumnConstraints().add(columnConstraints); + final var columnConstraints2 = new ColumnConstraints(); + columnConstraints2.setPercentWidth(15); + columnConstraints2.setPrefWidth(size); + getColumnConstraints().add(columnConstraints2); + setAlignment(Pos.CENTER); + setHgap(10); + setVgap(10); + setPadding(new Insets(5, 5, 5, 5)); + setMargin(clearButton, new Insets(5)); + } + + /** + * @return the underlying {@code textField} + * @since Envoy Client v0.1-beta + */ + public TextField getTextField() { return textField; } + + /** + * @return + * @see javafx.scene.control.TextInputControl#fontProperty() + * @since Envoy Client v0.1-beta + */ + public final ObjectProperty fontProperty() { return textField.fontProperty(); } + + /** + * @return + * @see javafx.scene.control.TextField#prefColumnCountProperty() + * @since Envoy Client v0.1-beta + */ + public final IntegerProperty prefColumnCountProperty() { return textField.prefColumnCountProperty(); } + + /** + * @return + * @see javafx.scene.control.TextField#getPrefColumnCount() + * @since Envoy Client v0.1-beta + */ + public final int getPrefColumnCount() { return textField.getPrefColumnCount(); } + + /** + * @param value + * @see javafx.scene.control.TextField#setPrefColumnCount(int) + * @since Envoy Client v0.1-beta + */ + public final void setPrefColumnCount(int value) { textField.setPrefColumnCount(value); } + + /** + * @return + * @see javafx.scene.control.Control#skinProperty() + * @since Envoy Client v0.1-beta + */ + public final ObjectProperty> skinProperty() { return textField.skinProperty(); } + + /** + * @param value + * @see javafx.scene.control.TextInputControl#setFont(javafx.scene.text.Font) + * @since Envoy Client v0.1-beta + */ + public final void setFont(Font value) { textField.setFont(value); } + + /** + * @return + * @see javafx.scene.control.TextInputControl#getFont() + * @since Envoy Client v0.1-beta + */ + public final Font getFont() { return textField.getFont(); } + + /** + * @return + * @see javafx.scene.control.TextInputControl#promptTextProperty() + * @since Envoy Client v0.1-beta + */ + public final StringProperty promptTextProperty() { return textField.promptTextProperty(); } + + /** + * @return + * @see javafx.scene.control.TextInputControl#getPromptText() + * @since Envoy Client v0.1-beta + */ + public final String getPromptText() { return textField.getPromptText(); } + + /** + * @param value + * @see javafx.scene.control.TextInputControl#setPromptText(java.lang.String) + * @since Envoy Client v0.1-beta + */ + public final void setPromptText(String value) { textField.setPromptText(value); } + + /** + * @return + * @see javafx.scene.control.TextInputControl#getText() + * @since Envoy Client v0.1-beta + */ + public final String getText() { return textField.getText(); } + + /** + * @param value + * @see javafx.scene.control.TextInputControl#setText(java.lang.String) + * @since Envoy Client v0.1-beta + */ + public final void setText(String value) { textField.setText(value); } + + /** + * @return + * @see javafx.scene.control.TextInputControl#textProperty() + * @since Envoy Client v0.1-beta + */ + public final StringProperty textProperty() { return textField.textProperty(); } + + /** + * @param value + * @see javafx.scene.control.TextInputControl#setEditable(boolean) + * @since Envoy Client v0.1-beta + */ + public final void setEditable(boolean value) { textField.setEditable(value); } + + /** + * @return + * @see javafx.scene.control.Control#tooltipProperty() + * @since Envoy Client v0.1-beta + */ + public final ObjectProperty tooltipProperty() { return textField.tooltipProperty(); } + + /** + * @param value + * @see javafx.scene.control.Control#setTooltip(javafx.scene.control.Tooltip) + * @since Envoy Client v0.1-beta + */ + public final void setTooltip(Tooltip value) { textField.setTooltip(value); } + + /** + * @return + * @see javafx.scene.control.Control#getTooltip() + * @since Envoy Client v0.1-beta + */ + public final Tooltip getTooltip() { return textField.getTooltip(); } + + /** + * @return + * @see javafx.scene.control.Control#contextMenuProperty() + * @since Envoy Client v0.1-beta + */ + public final ObjectProperty contextMenuProperty() { return textField.contextMenuProperty(); } + + /** + * @param value + * @see javafx.scene.control.Control#setContextMenu(javafx.scene.control.ContextMenu) + * @since Envoy Client v0.1-beta + */ + public final void setContextMenu(ContextMenu value) { textField.setContextMenu(value); } + + /** + * @return + * @see javafx.scene.control.Control#getContextMenu() + * @since Envoy Client v0.1-beta + */ + public final ContextMenu getContextMenu() { return textField.getContextMenu(); } + + /** + * @param minWidth + * @param minHeight + * @see javafx.scene.layout.Region#setMinSize(double, double) + * @since Envoy Client v0.1-beta + */ + @Override + public void setMinSize(double minWidth, double minHeight) { textField.setMinSize(minWidth, minHeight); } + + /** + * @param prefWidth + * @param prefHeight + * @see javafx.scene.layout.Region#setPrefSize(double, double) + * @since Envoy Client v0.1-beta + */ + @Override + public void setPrefSize(double prefWidth, double prefHeight) { textField.setPrefSize(prefWidth, prefHeight); } + + /** + * @param maxWidth + * @param maxHeight + * @see javafx.scene.layout.Region#setMaxSize(double, double) + * @since Envoy Client v0.1-beta + */ + @Override + public void setMaxSize(double maxWidth, double maxHeight) { textField.setMaxSize(maxWidth, maxHeight); } +} diff --git a/src/main/resources/icons/clear_button_black.png b/src/main/resources/icons/clear_button_black.png new file mode 100644 index 0000000000000000000000000000000000000000..56b8516a2808d37b1c3dcf7e3502e09ad1de7158 GIT binary patch literal 4258 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/icons/clear_button_white.png b/src/main/resources/icons/clear_button_white.png new file mode 100644 index 0000000000000000000000000000000000000000..e93bd4c6bfb44abc132a6a22825a843c7bf53227 GIT binary patch literal 3919 zcmXw64O~p=8h_7p;;pE2W>89*bNZN&gf`vnYdR*0QTf`2Mbj2;E2N@OoW_aCrsn#n zDC8@!riI%%|``_`23NmDshO8g#e<#J6NE_PgI>%t^K;M=Onw4+6 zZ%F0jjNr^?`#!$f|LD)1M}zx@+2nR#DqsJKGM?VwxXQ1d&=yzRv3Y)@V%7VzuLtlK zHpAi?EY|4z7IwL#%tHA^N?8@fHZ76hAEuG_RVcr-P=3r#e*1GeWhg)Xq4}#GK9cF zMXrrQ`DrSHo>IycG(`A874SELoFHqs3g%dHhg6AZbqpdN(hVsjWwD{vDnz`LHh94z zoK`Cl;o+m(D^v0}RK{cp?hdA{5ORS+=Pp(9YgNXH5*)A}uK}l0x*-a~l(6guh1!0voh-E+mIXSFIfaUE`7-yifik$t?li#a20n1;2k z5vr@F$8GNTJ|gURY$>KE|Vj+l?3c-`+9|aw6fjvJFig*n= z0ef2@7RAwR|3K9<{h(0wAq`U0Z;2-Z?dm0gfa!z*ony88Nk^b zPfn5o;vgck7a~QNh=`oQA~JJ1a0=qd1d$`^R3zj9M?@%7Xrq2<;-D+pN3xsWtQ)bv zO_l3RUmjgw5VfdoTVHhnihWqrIq4je_Unu;;skA4uv!0c!^Gma>95Lvzmb&lCiCh& zx+kw|Y;$kj8Fb0x+V`9F5xX9q9H?lpB?C^Bol}_0j%;cE?duX+uC7R)Mof2K( z@VsegjF--dQZA8lPo<`5g%$;AC=d+GNaI&*A5ElqGf$+%@k;zqstl5H;okgUs)16j z@f6ggk?!*J<*jN=n>HUVu0k0U(>xuy?FiCIni_Lpyp80IJ1lOXX=^YG#t2Dk{t$YIax^1+piHq@BY`o2YYiu?Q}2nex9~!0 z`YFo|;0&(SgRsVz0qn{MFMz$;8Q}4pCW5eP5=7WrcmwR!GJsccnvsOM>KjO8FJ)eb zwbGl>@u;haDpl}>f$qSV&1s5}PfHpk@{?W1Uu3`mA1KR<5uVYe!+XA|LfeZdk2oY- zHd-f{I*ZF0L8xnYgWPqyj(*Y*1Z7b)cV0nwv99_mWOnDy??rzsx(j*a7^qqW-!^kO zX-j!{3pecKZ|4k;B!qcFdN}bU@@`Z-N}`#%Sajjr8W23r3T1Zkk{TbK1XtjWJW12s zxhkMIbA9<}!t@@XSf^oIgYDKS@u-8^J=vG{o8<@OE&p=ih?J8ogba?VrtIa%Dm@^~ z?8W#1I`!*!0Q(+%25?2?Fn|xP8wBwEQ2>9-#W6#aYgXkzf;D$0gLeA}SD=hOGs1j} zG=#Z}{F?e4x1Jfviv$DZ45g+}jKetBycBr$_F+hA?Tnr&5x z+aaV!OIl0YVQ+2+GHvB@HgffNuiSTHy4-wXD2SwOR7)hHhHH+}qoQtIO&^)L_zI{tPdYAPXB$Dg3 z7~2{XOJI}o2OhRRfO=ni1=;4Pwo>-mj~+!;NHQ_Yog2 zGS|YhM+QA-1xfiWis4QEdmIm-r-4{*JmdpgzP7zhRW~Y3^1LykQNMAg$H{*`(CAF?VYiXk~m}yH5F1%do1^=?U;bcWg^ef`Lgm$oFAR#4yN8$KkuI< zK;P=TOmGoi8dZk7*WW}PTl)3lBC&N)PonX=)RDUu|K?#(3&GJtM1(|Nc zq_z0dMHKhLs{EreinzZf0B;RCcJN6w^Oxk-=v zkn7SPJmr1AKHKJE&d>8vVoB$Yd!2oUUl(84Fn&R?HjL_ca*y?=8vIDBmV(%NxbI_}=06Qi%bJ#wzwIJtIm#M7^b z)ZA$s`g}S1D5Wp|Gw*dqQBLoV0d;=C%jkqdZ$1yz(H!3OoDqkh^HG(Uo^hWzaDqa{ zil&0sF0k3Bu74-i7d-D4{142ry&hssJ5n(8{dq^Giq$%njuItKe)WkrwNad6QCp{g zUeeOtu=CuKF`u0FV#`3T$#1S0Dan(li^CUc_K2H$+>0->V@hg9i%}iyEUUSusJl@j z%ZI3p!)xPriOT0WR3_tIeitONoUvsc*W^A|+|&-4qDh!4c}V&oBrWy}0QX{xIv$AeMVTo?K6GSi=SN!(2__pVY@ z>M2|gbccEmhe$O0D4#pIP_AJG)`kfIh5n*yU>y40Q?SdDiKKZF%{a!oAVExHk0<{| zW-easEEt}9uFQOQxk|Amt_-4Uz! zTM>HdEo_Sst4PU~=&2yDJdxjykf1=JsQM9LWExE^M&&?Z&( zvI5NB-9kVZk+PE05cC2iZjmaBS)riN!g1xrC?k;ZdtUvT|0Oqk(8dv-8xq$IeCFcW zUw;yX)264P?ri_tH^Jef!cuDCI8l;(b>q%Y$ADdxxTSBEzVGIZv5{Kh z03!Q9q!mQqB)BCY8F{L@1G)0X6)=}-TgM9XY+M-KQK>mF2+G-=nu#Y44B*H(g^+q2 zy7H;p|Dl$MnG9ouR6h~8^O&-?gs>VtRXsigM5mmFmJP?&NYK0sd4ybW<%qiJq=U>H z=)XB0-M{}MIOMS!0uo&W18`HD!vPeoCdYtcoznr7VSLLBF~K!~UD??4fO!n(y7co2 z$yYBs(i`oGCz^3E1l-tu1=$_RYKAK~{!hKOK%gumSj{Mg4Bm&oP-CLlTenNb@tu0D z4VYZmR?LvC`*Dy86TRNLZ8XP!&}%mdly)TB>Ih@9` z|C`F_$zfv=UNZ#~Ph|~`c8n>MZG}+hW62P3Dv>q(1lVG>9GpVcOVSLSZ-vVf1DB^rftos&G0oZO9m;s^#h@+Hm59q1>K z98Qtz7I+EDS1Loa9dmmk{bV#luJhJ4vx2fjWw Date: Sat, 27 Jun 2020 17:14:07 +0200 Subject: [PATCH 02/19] Display status for own messages instead of received ones --- src/main/java/envoy/client/ui/MessageListCell.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/envoy/client/ui/MessageListCell.java b/src/main/java/envoy/client/ui/MessageListCell.java index 21a094e..dbb8e1d 100644 --- a/src/main/java/envoy/client/ui/MessageListCell.java +++ b/src/main/java/envoy/client/ui/MessageListCell.java @@ -43,7 +43,7 @@ public class MessageListCell extends ListCell { setGraphic(null); } else { final var cell = new VBox(new Label(dateFormat.format(message.getCreationDate())), new Label(message.getText())); - if (message.getRecipientID() == client.getID()) { + if (message.getRecipientID() != client.getID()) { cell.getChildren().add(new Label("", new ImageView(statusImages.get(message.getStatus())))); cell.getStyleClass().add("own-message"); } else cell.getStyleClass().add("received-message"); From 1361c29d4fba093848ceed92ae8a62000abd1f95 Mon Sep 17 00:00:00 2001 From: kske Date: Sat, 27 Jun 2020 17:36:42 +0200 Subject: [PATCH 03/19] Bind message list cell width to message list width Fixes #156 --- .../java/envoy/client/ui/MessageListCell.java | 15 ++++++++++++++- .../envoy/client/ui/controller/ChatScene.java | 2 +- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/main/java/envoy/client/ui/MessageListCell.java b/src/main/java/envoy/client/ui/MessageListCell.java index dbb8e1d..a5568c1 100644 --- a/src/main/java/envoy/client/ui/MessageListCell.java +++ b/src/main/java/envoy/client/ui/MessageListCell.java @@ -6,6 +6,7 @@ import java.util.Map; import javafx.geometry.Insets; import javafx.scene.control.Label; import javafx.scene.control.ListCell; +import javafx.scene.control.ListView; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.VBox; @@ -26,10 +27,18 @@ import envoy.data.User; */ public class MessageListCell extends ListCell { + private final ListView listView; + private static User client; private static final DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm"); private static final Map 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 listView) { this.listView = listView; } + /** * Displays the text, the data of creation and the status of a message. * @@ -42,12 +51,16 @@ public class MessageListCell extends ListCell { setText(null); setGraphic(null); } else { - final var cell = new VBox(new Label(dateFormat.format(message.getCreationDate())), new Label(message.getText())); + 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); if (message.getRecipientID() != client.getID()) { cell.getChildren().add(new Label("", new ImageView(statusImages.get(message.getStatus())))); cell.getStyleClass().add("own-message"); } else cell.getStyleClass().add("received-message"); cell.paddingProperty().setValue(new Insets(5, 20, 5, 20)); + cell.prefWidthProperty().bind(listView.widthProperty().subtract(40)); setGraphic(cell); } } diff --git a/src/main/java/envoy/client/ui/controller/ChatScene.java b/src/main/java/envoy/client/ui/controller/ChatScene.java index 91665c8..d1a6bfa 100644 --- a/src/main/java/envoy/client/ui/controller/ChatScene.java +++ b/src/main/java/envoy/client/ui/controller/ChatScene.java @@ -92,7 +92,7 @@ public final class ChatScene { private void initialize() { // Initialize message and user rendering - messageList.setCellFactory(listView -> new MessageListCell()); + messageList.setCellFactory(listView -> new MessageListCell(listView)); userList.setCellFactory(listView -> new ContactListCell()); settingsButton.setGraphic(new ImageView(IconUtil.load("/icons/settings.png", 16))); From 08e5fad42be48ca80e53a6d39c7afa32364c1492 Mon Sep 17 00:00:00 2001 From: delvh Date: Sat, 27 Jun 2020 18:27:13 +0200 Subject: [PATCH 04/19] Fixed padding of status icon and implemented Tooltip Additionally added commentary in MessageListCell. --- .../java/envoy/client/ui/MessageListCell.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main/java/envoy/client/ui/MessageListCell.java b/src/main/java/envoy/client/ui/MessageListCell.java index a5568c1..e33c502 100644 --- a/src/main/java/envoy/client/ui/MessageListCell.java +++ b/src/main/java/envoy/client/ui/MessageListCell.java @@ -4,12 +4,11 @@ import java.time.format.DateTimeFormatter; import java.util.Map; import javafx.geometry.Insets; -import javafx.scene.control.Label; -import javafx.scene.control.ListCell; -import javafx.scene.control.ListView; +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.data.Message; import envoy.data.Message.MessageStatus; @@ -51,16 +50,26 @@ public class MessageListCell extends ListCell { 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()) { - cell.getChildren().add(new Label("", new ImageView(statusImages.get(message.getStatus())))); + final var statusIcon = new Label("", new ImageView(statusImages.get(message.getStatus()))); + statusIcon.setPadding(new Insets(1, 0, 5, 5)); + 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)); 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); } } From dee66458d9df8e2e4f94b6333d426711c97c61c8 Mon Sep 17 00:00:00 2001 From: delvh Date: Sat, 27 Jun 2020 18:44:57 +0200 Subject: [PATCH 05/19] Wrapped text in userList (as suggested by @CyB3RC0nN0R) It is nice to see that JavaFX is less prone to shittyness than Swing is. --- .../java/envoy/client/ui/ContactListCell.java | 18 ++++++++++++++---- .../envoy/client/ui/controller/ChatScene.java | 4 ++-- .../ui/controller/ContactSearchScene.java | 2 +- .../ui/controller/GroupCreationScene.java | 4 ++-- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/main/java/envoy/client/ui/ContactListCell.java b/src/main/java/envoy/client/ui/ContactListCell.java index 283a89a..b13543b 100644 --- a/src/main/java/envoy/client/ui/ContactListCell.java +++ b/src/main/java/envoy/client/ui/ContactListCell.java @@ -2,6 +2,7 @@ package envoy.client.ui; import javafx.scene.control.Label; import javafx.scene.control.ListCell; +import javafx.scene.control.ListView; import javafx.scene.layout.VBox; import envoy.data.Contact; @@ -18,6 +19,14 @@ import envoy.data.User; */ public class ContactListCell extends ListCell { + private final ListView listView; + + /** + * @param listView the list view inside which this cell is contained + * @since Envoy Client v0.1-beta + */ + public ContactListCell(ListView listView) { this.listView = listView; } + /** * Displays the name of a contact. If the contact is a user, their online status * is displayed as well. @@ -32,17 +41,18 @@ public class ContactListCell extends ListCell { setGraphic(null); } else { // Container with contact name - final var vbox = new VBox(new Label(contact.getName())); + 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 + } else // Member count vbox.getChildren().add(new Label(((Group) contact).getContacts().size() + " members")); - } + prefWidthProperty().bind(listView.widthProperty().subtract(40)); setGraphic(vbox); } } diff --git a/src/main/java/envoy/client/ui/controller/ChatScene.java b/src/main/java/envoy/client/ui/controller/ChatScene.java index d1a6bfa..c27a857 100644 --- a/src/main/java/envoy/client/ui/controller/ChatScene.java +++ b/src/main/java/envoy/client/ui/controller/ChatScene.java @@ -92,8 +92,8 @@ public final class ChatScene { private void initialize() { // Initialize message and user rendering - messageList.setCellFactory(listView -> new MessageListCell(listView)); - userList.setCellFactory(listView -> new ContactListCell()); + messageList.setCellFactory(MessageListCell::new); + userList.setCellFactory(ContactListCell::new); settingsButton.setGraphic(new ImageView(IconUtil.load("/icons/settings.png", 16))); diff --git a/src/main/java/envoy/client/ui/controller/ContactSearchScene.java b/src/main/java/envoy/client/ui/controller/ContactSearchScene.java index 54c505c..7e70a80 100644 --- a/src/main/java/envoy/client/ui/controller/ContactSearchScene.java +++ b/src/main/java/envoy/client/ui/controller/ContactSearchScene.java @@ -67,7 +67,7 @@ public class ContactSearchScene { @FXML private void initialize() { - contactList.setCellFactory(e -> new ContactListCell()); + contactList.setCellFactory(ContactListCell::new); eventBus.register(ContactSearchResult.class, response -> Platform.runLater(() -> { contactList.getItems().clear(); contactList.getItems().addAll(response.get()); })); } diff --git a/src/main/java/envoy/client/ui/controller/GroupCreationScene.java b/src/main/java/envoy/client/ui/controller/GroupCreationScene.java index c6d7d05..9234fa2 100644 --- a/src/main/java/envoy/client/ui/controller/GroupCreationScene.java +++ b/src/main/java/envoy/client/ui/controller/GroupCreationScene.java @@ -41,7 +41,7 @@ public class GroupCreationScene { @FXML private void initialize() { - contactList.setCellFactory(e -> new ContactListCell()); + contactList.setCellFactory(ContactListCell::new); contactList.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); } @@ -59,7 +59,7 @@ public class GroupCreationScene { /** * Enables the {@code createButton} if at least one contact is selected. - * + * * @since Envoy Client v0.1-beta */ @FXML From 6eb726af31421e93549bd0f574ef4f2dd9c9e295 Mon Sep 17 00:00:00 2001 From: delvh Date: Sun, 28 Jun 2020 22:30:14 +0200 Subject: [PATCH 06/19] Updated UI (again) --- .../ui/controller/ContactSearchScene.java | 39 +-- .../ui/controller/GroupCreationScene.java | 22 +- .../client/ui/controller/LoginScene.java | 15 +- src/main/resources/fxml/ChatScene.fxml | 29 +-- .../resources/fxml/ContactSearchScene.fxml | 131 +++++----- .../resources/fxml/GroupCreationScene.fxml | 134 ++++++----- src/main/resources/fxml/LoginScene.fxml | 223 +++++++++++------- src/main/resources/fxml/SettingsScene.fxml | 73 +++--- 8 files changed, 369 insertions(+), 297 deletions(-) diff --git a/src/main/java/envoy/client/ui/controller/ContactSearchScene.java b/src/main/java/envoy/client/ui/controller/ContactSearchScene.java index 54c505c..743759c 100644 --- a/src/main/java/envoy/client/ui/controller/ContactSearchScene.java +++ b/src/main/java/envoy/client/ui/controller/ContactSearchScene.java @@ -5,11 +5,14 @@ import java.util.logging.Logger; import javafx.application.Platform; import javafx.fxml.FXML; -import javafx.scene.control.*; +import javafx.scene.control.Alert; import javafx.scene.control.Alert.AlertType; +import javafx.scene.control.ButtonType; +import javafx.scene.control.ListView; import envoy.client.data.LocalDB; import envoy.client.event.SendEvent; +import envoy.client.ui.ClearableTextField; import envoy.client.ui.ContactListCell; import envoy.client.ui.SceneContext; import envoy.data.Contact; @@ -31,19 +34,7 @@ import envoy.util.EnvoyLog; public class ContactSearchScene { @FXML - private Button backButton; - - @FXML - private Button clearButton; - - @FXML - private Button searchButton; - - @FXML - private Button newGroupButton; - - @FXML - private TextField searchBar; + private ClearableTextField searchBar; @FXML private ListView contactList; @@ -78,20 +69,12 @@ public class ContactSearchScene { * @since Envoy Client v0.1-beta */ @FXML - private void checkClearButton() { - final var containsContent = searchBar.getText().strip().isEmpty(); - clearButton.setDisable(containsContent); - searchButton.setDisable(containsContent); + private void sendRequest() { + final var text = searchBar.getTextField().getText().strip(); + if (!text.isBlank()) eventBus.dispatch(new SendEvent(new ContactSearchRequest(text))); + else contactList.getItems().clear(); } - /** - * Sends a {@link ContactSearchRequest} to the server. - * - * @since Envoy Client v0.1-beta - */ - @FXML - private void suggestContacts() { eventBus.dispatch(new SendEvent(new ContactSearchRequest(searchBar.getText()))); } - /** * Clears the text in the search bar and the items shown in the list. * Additionally disables both clear and search button. @@ -100,10 +83,8 @@ public class ContactSearchScene { */ @FXML private void clear() { - searchBar.setText(null); + searchBar.getTextField().setText(null); contactList.getItems().clear(); - clearButton.setDisable(true); - searchButton.setDisable(true); } /** diff --git a/src/main/java/envoy/client/ui/controller/GroupCreationScene.java b/src/main/java/envoy/client/ui/controller/GroupCreationScene.java index c6d7d05..484d207 100644 --- a/src/main/java/envoy/client/ui/controller/GroupCreationScene.java +++ b/src/main/java/envoy/client/ui/controller/GroupCreationScene.java @@ -9,6 +9,7 @@ import javafx.scene.control.Alert.AlertType; import envoy.client.data.LocalDB; import envoy.client.event.SendEvent; +import envoy.client.ui.ClearableTextField; import envoy.client.ui.ContactListCell; import envoy.client.ui.SceneContext; import envoy.data.Contact; @@ -30,7 +31,7 @@ public class GroupCreationScene { private Button createButton; @FXML - private TextField groupNameField; + private ClearableTextField groupNameField; @FXML private ListView contactList; @@ -59,11 +60,22 @@ public class GroupCreationScene { /** * Enables the {@code createButton} if at least one contact is selected. - * + * * @since Envoy Client v0.1-beta */ @FXML - private void contactListClicked() { createButton.setDisable(contactList.getSelectionModel().isEmpty()); } + private void contactListClicked() { + createButton.setDisable(contactList.getSelectionModel().isEmpty() || groupNameField.getTextField().getText().isBlank()); + } + + /** + * Checks, whether the {@code createButton} can be enabled because text is + * present in the textfield. + * + * @since Envoy Client v0.1-beta + */ + @FXML + private void textUpdated() { createButton.setDisable(groupNameField.getTextField().getText().isBlank()); } /** * Sends a {@link GroupCreation} to the server and closes this scene. @@ -74,10 +86,10 @@ public class GroupCreationScene { */ @FXML private void createButtonClicked() { - final var name = groupNameField.getText(); + final var name = groupNameField.getTextField().getText(); if (!Bounds.isValidContactName(name)) { new Alert(AlertType.ERROR, "The entered group name is not valid (" + Bounds.CONTACT_NAME_PATTERN + ")").showAndWait(); - groupNameField.clear(); + groupNameField.getTextField().clear(); } else { eventBus.dispatch(new SendEvent(new GroupCreation(name, contactList.getSelectionModel().getSelectedItems().stream().map(Contact::getID).collect(Collectors.toSet())))); diff --git a/src/main/java/envoy/client/ui/controller/LoginScene.java b/src/main/java/envoy/client/ui/controller/LoginScene.java index 380842a..db75bc4 100644 --- a/src/main/java/envoy/client/ui/controller/LoginScene.java +++ b/src/main/java/envoy/client/ui/controller/LoginScene.java @@ -13,6 +13,7 @@ import javafx.scene.control.Alert.AlertType; import envoy.client.data.*; import envoy.client.net.Client; +import envoy.client.ui.ClearableTextField; import envoy.client.ui.SceneContext; import envoy.client.ui.Startup; import envoy.data.LoginCredentials; @@ -38,7 +39,7 @@ import envoy.util.EnvoyLog; public final class LoginScene { @FXML - private TextField userTextField; + private ClearableTextField userTextField; @FXML private PasswordField passwordField; @@ -116,17 +117,17 @@ public final class LoginScene { if (registerCheckBox.isSelected() && !passwordField.getText().equals(repeatPasswordField.getText())) { new Alert(AlertType.ERROR, "The entered password is unequal to the repeated one").showAndWait(); repeatPasswordField.clear(); - } else if (!Bounds.isValidContactName(userTextField.getText())) { + } else if (!Bounds.isValidContactName(userTextField.getTextField().getText())) { new Alert(AlertType.ERROR, "The entered user name is not valid (" + Bounds.CONTACT_NAME_PATTERN + ")").showAndWait(); - userTextField.clear(); - } else - performHandshake( - new LoginCredentials(userTextField.getText(), passwordField.getText().toCharArray(), registerCheckBox.isSelected(), Startup.VERSION)); + userTextField.getTextField().clear(); + } else performHandshake(new LoginCredentials(userTextField.getTextField().getText(), passwordField.getText().toCharArray(), + registerCheckBox.isSelected(), Startup.VERSION)); } @FXML private void offlineModeButtonPressed() { - attemptOfflineMode(new LoginCredentials(userTextField.getText(), passwordField.getText().toCharArray(), false, Startup.VERSION)); + attemptOfflineMode( + new LoginCredentials(userTextField.getTextField().getText(), passwordField.getText().toCharArray(), false, Startup.VERSION)); } @FXML diff --git a/src/main/resources/fxml/ChatScene.fxml b/src/main/resources/fxml/ChatScene.fxml index fa1a4ef..666a148 100644 --- a/src/main/resources/fxml/ChatScene.fxml +++ b/src/main/resources/fxml/ChatScene.fxml @@ -12,9 +12,9 @@ - @@ -47,7 +47,7 @@ prefHeight="211.0" prefWidth="300.0" GridPane.rowIndex="1" GridPane.rowSpan="2147483647"> - + @@ -64,7 +64,7 @@ + + +