From 493b291dceb20b58b659764db2e4013681c26999 Mon Sep 17 00:00:00 2001 From: 2xsaiko Date: Wed, 22 Apr 2020 20:21:15 +0200 Subject: Improve connect dialog --- .../enigma/gui/dialog/ConnectToServerDialog.java | 163 ++++++++++++++------- .../java/cuchaz/enigma/gui/elements/MenuBar.java | 2 +- .../enigma/gui/elements/VerifiableTextField.java | 61 ++++++++ 3 files changed, 175 insertions(+), 51 deletions(-) create mode 100644 enigma-swing/src/main/java/cuchaz/enigma/gui/elements/VerifiableTextField.java (limited to 'enigma-swing/src/main/java') diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java index c5f505c..070d03d 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java @@ -1,64 +1,131 @@ package cuchaz.enigma.gui.dialog; +import java.awt.*; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import javax.swing.*; + +import cuchaz.enigma.gui.elements.VerifiableTextField; import cuchaz.enigma.network.EnigmaServer; import cuchaz.enigma.utils.I18n; +import cuchaz.enigma.utils.ServerAddress; -import javax.swing.*; -import java.awt.Frame; - -public class ConnectToServerDialog { - - public static Result show(Frame parentComponent) { - JTextField usernameField = new JTextField(System.getProperty("user.name"), 20); - JPanel usernameRow = new JPanel(); - usernameRow.add(new JLabel(I18n.translate("prompt.connect.username"))); - usernameRow.add(usernameField); - JTextField ipField = new JTextField(20); - JPanel ipRow = new JPanel(); - ipRow.add(new JLabel(I18n.translate("prompt.connect.ip"))); - ipRow.add(ipField); - JTextField portField = new JTextField(String.valueOf(EnigmaServer.DEFAULT_PORT), 10); - JPanel portRow = new JPanel(); - portRow.add(new JLabel(I18n.translate("prompt.port"))); - portRow.add(portField); - JPasswordField passwordField = new JPasswordField(20); - JPanel passwordRow = new JPanel(); - passwordRow.add(new JLabel(I18n.translate("prompt.password"))); - passwordRow.add(passwordField); - - int response = JOptionPane.showConfirmDialog(parentComponent, new Object[]{usernameRow, ipRow, portRow, passwordRow}, I18n.translate("prompt.connect.title"), JOptionPane.OK_CANCEL_OPTION); - if (response != JOptionPane.OK_OPTION) { - return null; +public class ConnectToServerDialog extends JDialog { + + private final JTextField usernameField; + private final VerifiableTextField ipField; + private final JPasswordField passwordField; + private boolean success = false; + + public ConnectToServerDialog(Frame owner) { + super(owner, I18n.translate("prompt.connect.title"), true); + + Container contentPane = getContentPane(); + contentPane.setLayout(new BorderLayout()); + Container inputContainer = new JPanel(new GridBagLayout()); + GridBagConstraints c = new GridBagConstraints(); + usernameField = new JTextField(System.getProperty("user.name")); + ipField = new VerifiableTextField(); + passwordField = new JPasswordField(); + + List labels = Stream.of("prompt.connect.username", "prompt.connect.address", "prompt.password") + .map(I18n::translate) + .map(JLabel::new) + .collect(Collectors.toList()); + List inputs = Arrays.asList(usernameField, ipField, passwordField); + + for (int i = 0; i < inputs.size(); i += 1) { + c.gridy = i; + c.insets = new Insets(4, 4, 4, 4); + + c.gridx = 0; + c.weightx = 0.0; + c.anchor = GridBagConstraints.LINE_END; + c.fill = GridBagConstraints.NONE; + inputContainer.add(labels.get(i), c); + + c.gridx = 1; + c.weightx = 1.0; + c.anchor = GridBagConstraints.LINE_START; + c.fill = GridBagConstraints.HORIZONTAL; + inputs.get(i).addActionListener(event -> confirm()); + inputContainer.add(inputs.get(i), c); } + contentPane.add(inputContainer, BorderLayout.CENTER); + Container buttonContainer = new JPanel(new GridBagLayout()); + c = new GridBagConstraints(); + c.weightx = 1.0; + c.insets = new Insets(4, 4, 4, 4); + c.anchor = GridBagConstraints.LINE_END; + JButton connectButton = new JButton(I18n.translate("prompt.connect.confirm")); + connectButton.addActionListener(event -> confirm()); + buttonContainer.add(connectButton, c); + c.weightx = 0.0; + c.anchor = GridBagConstraints.CENTER; + JButton abortButton = new JButton(I18n.translate("prompt.connect.cancel")); + abortButton.addActionListener(event -> cancel()); + buttonContainer.add(abortButton, c); + contentPane.add(buttonContainer, BorderLayout.SOUTH); + + setLocationRelativeTo(owner); + setSize(new Dimension(400, 185)); + } - String username = usernameField.getText(); - String ip = ipField.getText(); - int port; - try { - port = Integer.parseInt(portField.getText()); - } catch (NumberFormatException e) { - JOptionPane.showMessageDialog(parentComponent, I18n.translate("prompt.port.nan"), I18n.translate("prompt.connect.title"), JOptionPane.ERROR_MESSAGE); - return null; + private void confirm() { + if (validateInputs()) { + success = true; + setVisible(false); } - if (port < 0 || port >= 65536) { - JOptionPane.showMessageDialog(parentComponent, I18n.translate("prompt.port.invalid"), I18n.translate("prompt.connect.title"), JOptionPane.ERROR_MESSAGE); - return null; + } + + private void cancel() { + success = false; + setVisible(false); + } + + public boolean validateInputs() { + boolean error = false; + ipField.setErrorState(false); + + if (ServerAddress.from(ipField.getText(), EnigmaServer.DEFAULT_PORT) == null) { + ipField.setErrorState(true); + error = true; } - char[] password = passwordField.getPassword(); - return new Result(username, ip, port, password); + return !error; + } + + public Result getResult() { + if (!success) return null; + return new Result( + usernameField.getText(), + Objects.requireNonNull(ServerAddress.from(ipField.getText(), EnigmaServer.DEFAULT_PORT)), + passwordField.getPassword() + ); + } + + public static Result show(Frame parent) { + ConnectToServerDialog d = new ConnectToServerDialog(parent); + + d.setVisible(true); + Result r = d.getResult(); + + d.dispose(); + return r; } public static class Result { private final String username; - private final String ip; - private final int port; + private final ServerAddress address; private final char[] password; - public Result(String username, String ip, int port, char[] password) { + public Result(String username, ServerAddress address, char[] password) { this.username = username; - this.ip = ip; - this.port = port; + this.address = address; this.password = password; } @@ -66,12 +133,8 @@ public class ConnectToServerDialog { return username; } - public String getIp() { - return ip; - } - - public int getPort() { - return port; + public ServerAddress getAddress() { + return address; } public char[] getPassword() { diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java index 3378d1a..1481a9d 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java @@ -227,7 +227,7 @@ public class MenuBar { } this.gui.getController().disconnectIfConnected(null); try { - this.gui.getController().createClient(result.getUsername(), result.getIp(), result.getPort(), result.getPassword()); + this.gui.getController().createClient(result.getUsername(), result.getAddress().address, result.getAddress().port, result.getPassword()); } catch (IOException e) { JOptionPane.showMessageDialog(this.gui.getFrame(), e.toString(), I18n.translate("menu.collab.connect.error"), JOptionPane.ERROR_MESSAGE); this.gui.getController().disconnectIfConnected(null); diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/elements/VerifiableTextField.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/elements/VerifiableTextField.java new file mode 100644 index 0000000..41a2484 --- /dev/null +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/elements/VerifiableTextField.java @@ -0,0 +1,61 @@ +package cuchaz.enigma.gui.elements; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; + +import javax.swing.JTextField; +import javax.swing.text.Document; + +public class VerifiableTextField extends JTextField { + + private boolean hasError; + + public VerifiableTextField() { + } + + public VerifiableTextField(String text) { + super(text); + } + + public VerifiableTextField(int columns) { + super(columns); + } + + public VerifiableTextField(String text, int columns) { + super(text, columns); + } + + public VerifiableTextField(Document doc, String text, int columns) { + super(doc, text, columns); + } + + { + addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + setErrorState(false); + } + }); + } + + public void setErrorState(boolean b) { + this.hasError = b; + repaint(); + } + + @Override + public void paint(Graphics g) { + super.paint(g); + if (hasError) { + g.setColor(Color.RED); + int x1 = getWidth() - 9; + int x2 = getWidth() - 2; + int y1 = 1; + int y2 = 8; + g.fillPolygon(new int[]{x1, x2, x2}, new int[]{y1, y1, y2}, 3); + } + } + +} -- cgit v1.2.3 From 8dcba3b6b98936791d3d35146e819da8b97fd78a Mon Sep 17 00:00:00 2001 From: 2xsaiko Date: Wed, 22 Apr 2020 20:50:50 +0200 Subject: Prepare for allowing error messages in VerifiableTextField --- .../enigma/gui/dialog/ConnectToServerDialog.java | 4 +-- .../enigma/gui/elements/VerifiableTextField.java | 32 ++++++++++++++++++---- 2 files changed, 29 insertions(+), 7 deletions(-) (limited to 'enigma-swing/src/main/java') diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java index 070d03d..4bac97b 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java @@ -89,10 +89,10 @@ public class ConnectToServerDialog extends JDialog { public boolean validateInputs() { boolean error = false; - ipField.setErrorState(false); + ipField.clearErrorState(); if (ServerAddress.from(ipField.getText(), EnigmaServer.DEFAULT_PORT) == null) { - ipField.setErrorState(true); + ipField.addError("Invalid IP/Port combination"); error = true; } diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/elements/VerifiableTextField.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/elements/VerifiableTextField.java index 41a2484..928372c 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/elements/VerifiableTextField.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/elements/VerifiableTextField.java @@ -6,6 +6,8 @@ import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; import javax.swing.JTextField; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; import javax.swing.text.Document; public class VerifiableTextField extends JTextField { @@ -32,16 +34,36 @@ public class VerifiableTextField extends JTextField { } { - addFocusListener(new FocusAdapter() { + getDocument().addDocumentListener(new DocumentListener() { @Override - public void focusGained(FocusEvent e) { - setErrorState(false); + public void insertUpdate(DocumentEvent e) { + clearErrorState(); + } + + @Override + public void removeUpdate(DocumentEvent e) { + clearErrorState(); + } + + @Override + public void changedUpdate(DocumentEvent e) { + clearErrorState(); } }); } - public void setErrorState(boolean b) { - this.hasError = b; + @Override + public void setText(String t) { + super.setText(t); + } + + public void clearErrorState() { + this.hasError = false; + repaint(); + } + + public void addError(String message) { + this.hasError = true; repaint(); } -- cgit v1.2.3 From f51c8a16770216003a1c8039a94e1632b2b1bb3c Mon Sep 17 00:00:00 2001 From: 2xsaiko Date: Wed, 22 Apr 2020 22:59:41 +0200 Subject: Extend validation system --- .../enigma/gui/dialog/ConnectToServerDialog.java | 37 +++++----- .../enigma/gui/elements/VerifiableTextField.java | 83 ---------------------- 2 files changed, 21 insertions(+), 99 deletions(-) delete mode 100644 enigma-swing/src/main/java/cuchaz/enigma/gui/elements/VerifiableTextField.java (limited to 'enigma-swing/src/main/java') diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java index 4bac97b..eede946 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java @@ -9,15 +9,19 @@ import java.util.stream.Stream; import javax.swing.*; -import cuchaz.enigma.gui.elements.VerifiableTextField; +import cuchaz.enigma.gui.elements.ValidatableTextField; import cuchaz.enigma.network.EnigmaServer; import cuchaz.enigma.utils.I18n; import cuchaz.enigma.utils.ServerAddress; +import cuchaz.enigma.utils.validation.Message; +import cuchaz.enigma.utils.validation.ValidationContext; public class ConnectToServerDialog extends JDialog { + private final ValidationContext vc = new ValidationContext(); + private final JTextField usernameField; - private final VerifiableTextField ipField; + private final ValidatableTextField ipField; private final JPasswordField passwordField; private boolean success = false; @@ -29,7 +33,7 @@ public class ConnectToServerDialog extends JDialog { Container inputContainer = new JPanel(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); usernameField = new JTextField(System.getProperty("user.name")); - ipField = new VerifiableTextField(); + ipField = new ValidatableTextField(); passwordField = new JPasswordField(); List labels = Stream.of("prompt.connect.username", "prompt.connect.address", "prompt.password") @@ -76,31 +80,32 @@ public class ConnectToServerDialog extends JDialog { } private void confirm() { - if (validateInputs()) { + vc.reset(); + validateInputs(); + if (vc.canProceed()) { success = true; setVisible(false); } } private void cancel() { - success = false; - setVisible(false); + success = false; + setVisible(false); } - public boolean validateInputs() { - boolean error = false; - ipField.clearErrorState(); - - if (ServerAddress.from(ipField.getText(), EnigmaServer.DEFAULT_PORT) == null) { - ipField.addError("Invalid IP/Port combination"); - error = true; + public void validateInputs() { + vc.setActiveElement(ipField); + if (ipField.getText().trim().isEmpty()) { + vc.raise(Message.EMPTY_FIELD); + } else if (ServerAddress.from(ipField.getText(), EnigmaServer.DEFAULT_PORT) == null) { + vc.raise(Message.INVALID_IP, ipField.getText()); } - - return !error; } public Result getResult() { - if (!success) return null; + vc.reset(); + validateInputs(); + if (!vc.canProceed()) return null; return new Result( usernameField.getText(), Objects.requireNonNull(ServerAddress.from(ipField.getText(), EnigmaServer.DEFAULT_PORT)), diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/elements/VerifiableTextField.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/elements/VerifiableTextField.java deleted file mode 100644 index 928372c..0000000 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/elements/VerifiableTextField.java +++ /dev/null @@ -1,83 +0,0 @@ -package cuchaz.enigma.gui.elements; - -import java.awt.Color; -import java.awt.Graphics; -import java.awt.event.FocusAdapter; -import java.awt.event.FocusEvent; - -import javax.swing.JTextField; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; -import javax.swing.text.Document; - -public class VerifiableTextField extends JTextField { - - private boolean hasError; - - public VerifiableTextField() { - } - - public VerifiableTextField(String text) { - super(text); - } - - public VerifiableTextField(int columns) { - super(columns); - } - - public VerifiableTextField(String text, int columns) { - super(text, columns); - } - - public VerifiableTextField(Document doc, String text, int columns) { - super(doc, text, columns); - } - - { - getDocument().addDocumentListener(new DocumentListener() { - @Override - public void insertUpdate(DocumentEvent e) { - clearErrorState(); - } - - @Override - public void removeUpdate(DocumentEvent e) { - clearErrorState(); - } - - @Override - public void changedUpdate(DocumentEvent e) { - clearErrorState(); - } - }); - } - - @Override - public void setText(String t) { - super.setText(t); - } - - public void clearErrorState() { - this.hasError = false; - repaint(); - } - - public void addError(String message) { - this.hasError = true; - repaint(); - } - - @Override - public void paint(Graphics g) { - super.paint(g); - if (hasError) { - g.setColor(Color.RED); - int x1 = getWidth() - 9; - int x2 = getWidth() - 2; - int y1 = 1; - int y2 = 8; - g.fillPolygon(new int[]{x1, x2, x2}, new int[]{y1, y1, y2}, 3); - } - } - -} -- cgit v1.2.3 From a648df9683fc93922daad22f7bcb3e8c247d1860 Mon Sep 17 00:00:00 2001 From: 2xsaiko Date: Wed, 22 Apr 2020 23:52:09 +0200 Subject: Improve CreateServerDialog --- .../enigma/gui/dialog/ConnectToServerDialog.java | 11 +- .../enigma/gui/dialog/CreateServerDialog.java | 141 ++++++++++++++++----- 2 files changed, 115 insertions(+), 37 deletions(-) (limited to 'enigma-swing/src/main/java') diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java index eede946..697fc51 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java @@ -23,7 +23,7 @@ public class ConnectToServerDialog extends JDialog { private final JTextField usernameField; private final ValidatableTextField ipField; private final JPasswordField passwordField; - private boolean success = false; + private boolean actionConfirm = false; public ConnectToServerDialog(Frame owner) { super(owner, I18n.translate("prompt.connect.title"), true); @@ -70,7 +70,7 @@ public class ConnectToServerDialog extends JDialog { buttonContainer.add(connectButton, c); c.weightx = 0.0; c.anchor = GridBagConstraints.CENTER; - JButton abortButton = new JButton(I18n.translate("prompt.connect.cancel")); + JButton abortButton = new JButton(I18n.translate("prompt.cancel")); abortButton.addActionListener(event -> cancel()); buttonContainer.add(abortButton, c); contentPane.add(buttonContainer, BorderLayout.SOUTH); @@ -83,13 +83,13 @@ public class ConnectToServerDialog extends JDialog { vc.reset(); validateInputs(); if (vc.canProceed()) { - success = true; + actionConfirm = true; setVisible(false); } } private void cancel() { - success = false; + actionConfirm = false; setVisible(false); } @@ -98,11 +98,12 @@ public class ConnectToServerDialog extends JDialog { if (ipField.getText().trim().isEmpty()) { vc.raise(Message.EMPTY_FIELD); } else if (ServerAddress.from(ipField.getText(), EnigmaServer.DEFAULT_PORT) == null) { - vc.raise(Message.INVALID_IP, ipField.getText()); + vc.raise(Message.INVALID_IP); } } public Result getResult() { + if (!actionConfirm) return null; vc.reset(); validateInputs(); if (!vc.canProceed()) return null; diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/CreateServerDialog.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/CreateServerDialog.java index eea1dff..bc4e9c9 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/CreateServerDialog.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/CreateServerDialog.java @@ -1,47 +1,124 @@ package cuchaz.enigma.gui.dialog; +import java.awt.*; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import javax.swing.*; + +import cuchaz.enigma.gui.elements.ValidatablePasswordField; +import cuchaz.enigma.gui.elements.ValidatableTextField; import cuchaz.enigma.network.EnigmaServer; import cuchaz.enigma.utils.I18n; +import cuchaz.enigma.utils.validation.Message; +import cuchaz.enigma.utils.validation.StandardValidation; +import cuchaz.enigma.utils.validation.ValidationContext; -import javax.swing.*; -import java.awt.*; +public class CreateServerDialog extends JDialog { -public class CreateServerDialog { - - public static Result show(Frame parentComponent) { - JTextField portField = new JTextField(String.valueOf(EnigmaServer.DEFAULT_PORT), 10); - JPanel portRow = new JPanel(); - portRow.add(new JLabel(I18n.translate("prompt.port"))); - portRow.add(portField); - JPasswordField passwordField = new JPasswordField(20); - JPanel passwordRow = new JPanel(); - passwordRow.add(new JLabel(I18n.translate("prompt.password"))); - passwordRow.add(passwordField); - - int response = JOptionPane.showConfirmDialog(parentComponent, new Object[]{portRow, passwordRow}, I18n.translate("prompt.create_server.title"), JOptionPane.OK_CANCEL_OPTION); - if (response != JOptionPane.OK_OPTION) { - return null; - } + private final ValidationContext vc = new ValidationContext(); + + private final ValidatableTextField portField; + private final ValidatablePasswordField passwordField; + private boolean actionConfirm = false; + + public CreateServerDialog(Frame owner) { + super(owner, I18n.translate("prompt.create_server.title"), true); + + Container contentPane = getContentPane(); + contentPane.setLayout(new BorderLayout()); + Container inputContainer = new JPanel(new GridBagLayout()); + GridBagConstraints c = new GridBagConstraints(); + portField = new ValidatableTextField(Integer.toString(EnigmaServer.DEFAULT_PORT)); + passwordField = new ValidatablePasswordField(); + + java.util.List labels = Stream.of("prompt.create_server.port", "prompt.password") + .map(I18n::translate) + .map(JLabel::new) + .collect(Collectors.toList()); + List inputs = Arrays.asList(portField, passwordField); + + for (int i = 0; i < inputs.size(); i += 1) { + c.gridy = i; + c.insets = new Insets(4, 4, 4, 4); - int port; - try { - port = Integer.parseInt(portField.getText()); - } catch (NumberFormatException e) { - JOptionPane.showMessageDialog(parentComponent, I18n.translate("prompt.port.nan"), I18n.translate("prompt.create_server.title"), JOptionPane.ERROR_MESSAGE); - return null; + c.gridx = 0; + c.weightx = 0.0; + c.anchor = GridBagConstraints.LINE_END; + c.fill = GridBagConstraints.NONE; + inputContainer.add(labels.get(i), c); + + c.gridx = 1; + c.weightx = 1.0; + c.anchor = GridBagConstraints.LINE_START; + c.fill = GridBagConstraints.HORIZONTAL; + inputs.get(i).addActionListener(event -> confirm()); + inputContainer.add(inputs.get(i), c); } - if (port < 0 || port >= 65536) { - JOptionPane.showMessageDialog(parentComponent, I18n.translate("prompt.port.invalid"), I18n.translate("prompt.create_server.title"), JOptionPane.ERROR_MESSAGE); - return null; + contentPane.add(inputContainer, BorderLayout.CENTER); + Container buttonContainer = new JPanel(new GridBagLayout()); + c = new GridBagConstraints(); + c.weightx = 1.0; + c.insets = new Insets(4, 4, 4, 4); + c.anchor = GridBagConstraints.LINE_END; + JButton connectButton = new JButton(I18n.translate("prompt.create_server.confirm")); + connectButton.addActionListener(event -> confirm()); + buttonContainer.add(connectButton, c); + c.weightx = 0.0; + c.anchor = GridBagConstraints.CENTER; + JButton abortButton = new JButton(I18n.translate("prompt.cancel")); + abortButton.addActionListener(event -> cancel()); + buttonContainer.add(abortButton, c); + contentPane.add(buttonContainer, BorderLayout.SOUTH); + + setLocationRelativeTo(owner); + setSize(new Dimension(400, 150)); + } + + private void confirm() { + vc.reset(); + validateInputs(); + if (vc.canProceed()) { + actionConfirm = true; + setVisible(false); } + } + + private void cancel() { + actionConfirm = false; + setVisible(false); + } - char[] password = passwordField.getPassword(); - if (password.length > EnigmaServer.MAX_PASSWORD_LENGTH) { - JOptionPane.showMessageDialog(parentComponent, I18n.translate("prompt.password.too_long"), I18n.translate("prompt.create_server.title"), JOptionPane.ERROR_MESSAGE); - return null; + public void validateInputs() { + vc.setActiveElement(portField); + StandardValidation.isIntInRange(vc, portField.getText(), 0, 65535); + vc.setActiveElement(passwordField); + if (passwordField.getPassword().length > EnigmaServer.MAX_PASSWORD_LENGTH) { + vc.raise(Message.FIELD_LENGTH_OUT_OF_RANGE, EnigmaServer.MAX_PASSWORD_LENGTH); } + } + + public Result getResult() { + if (!actionConfirm) return null; + vc.reset(); + validateInputs(); + if (!vc.canProceed()) return null; + return new Result( + Integer.parseInt(portField.getText()), + passwordField.getPassword() + ); + } + + public static Result show(Frame parent) { + CreateServerDialog d = new CreateServerDialog(parent); + + d.setVisible(true); + Result r = d.getResult(); - return new Result(port, password); + d.dispose(); + return r; } public static class Result { -- cgit v1.2.3 From 5fe6dbaacf5a11f26523889580219068c473b5ce Mon Sep 17 00:00:00 2001 From: 2xsaiko Date: Thu, 23 Apr 2020 00:15:07 +0200 Subject: Abstract out common code between ConnectToServerDialog and CreateServerDialog --- .../cuchaz/enigma/gui/dialog/AbstractDialog.java | 94 ++++++++++++++++++++ .../enigma/gui/dialog/ConnectToServerDialog.java | 99 ++++++---------------- .../enigma/gui/dialog/CreateServerDialog.java | 95 +++++---------------- 3 files changed, 142 insertions(+), 146 deletions(-) create mode 100644 enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/AbstractDialog.java (limited to 'enigma-swing/src/main/java') diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/AbstractDialog.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/AbstractDialog.java new file mode 100644 index 0000000..a4d8e1f --- /dev/null +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/AbstractDialog.java @@ -0,0 +1,94 @@ +package cuchaz.enigma.gui.dialog; + +import java.awt.*; +import java.util.List; + +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JPanel; + +import cuchaz.enigma.utils.I18n; +import cuchaz.enigma.utils.Pair; +import cuchaz.enigma.utils.validation.ValidationContext; + +public abstract class AbstractDialog extends JDialog { + + protected final ValidationContext vc = new ValidationContext(); + + private boolean actionConfirm = false; + + public AbstractDialog(Frame owner, String title, String confirmAction, String cancelAction) { + super(owner, I18n.translate(title), true); + + Container contentPane = getContentPane(); + contentPane.setLayout(new BorderLayout()); + Container inputContainer = new JPanel(new GridBagLayout()); + GridBagConstraints c = new GridBagConstraints(); + + List> components = createComponents(); + + for (int i = 0; i < components.size(); i += 1) { + Pair entry = components.get(i); + JLabel label = new JLabel(I18n.translate(entry.a)); + Component component = entry.b; + + c.gridy = i; + c.insets = new Insets(4, 4, 4, 4); + + c.gridx = 0; + c.weightx = 0.0; + c.anchor = GridBagConstraints.LINE_END; + c.fill = GridBagConstraints.NONE; + inputContainer.add(label, c); + + c.gridx = 1; + c.weightx = 1.0; + c.anchor = GridBagConstraints.LINE_START; + c.fill = GridBagConstraints.HORIZONTAL; + inputContainer.add(component, c); + } + contentPane.add(inputContainer, BorderLayout.CENTER); + Container buttonContainer = new JPanel(new GridBagLayout()); + c = new GridBagConstraints(); + c.weightx = 1.0; + c.insets = new Insets(4, 4, 4, 4); + c.anchor = GridBagConstraints.LINE_END; + JButton connectButton = new JButton(I18n.translate(confirmAction)); + connectButton.addActionListener(event -> confirm()); + buttonContainer.add(connectButton, c); + c.weightx = 0.0; + c.anchor = GridBagConstraints.CENTER; + JButton abortButton = new JButton(I18n.translate(cancelAction)); + abortButton.addActionListener(event -> cancel()); + buttonContainer.add(abortButton, c); + contentPane.add(buttonContainer, BorderLayout.SOUTH); + + pack(); + setLocationRelativeTo(owner); + } + + protected abstract List> createComponents(); + + protected void confirm() { + vc.reset(); + validateInputs(); + if (vc.canProceed()) { + actionConfirm = true; + setVisible(false); + } + } + + protected void cancel() { + actionConfirm = false; + setVisible(false); + } + + public boolean isActionConfirm() { + return actionConfirm; + } + + public void validateInputs() { + } + +} diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java index 697fc51..79b0c4e 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java @@ -1,96 +1,49 @@ package cuchaz.enigma.gui.dialog; -import java.awt.*; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Frame; import java.util.Arrays; import java.util.List; import java.util.Objects; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import javax.swing.*; +import javax.swing.JPasswordField; +import javax.swing.JTextField; import cuchaz.enigma.gui.elements.ValidatableTextField; import cuchaz.enigma.network.EnigmaServer; -import cuchaz.enigma.utils.I18n; +import cuchaz.enigma.utils.Pair; import cuchaz.enigma.utils.ServerAddress; import cuchaz.enigma.utils.validation.Message; -import cuchaz.enigma.utils.validation.ValidationContext; -public class ConnectToServerDialog extends JDialog { +public class ConnectToServerDialog extends AbstractDialog { - private final ValidationContext vc = new ValidationContext(); - - private final JTextField usernameField; - private final ValidatableTextField ipField; - private final JPasswordField passwordField; - private boolean actionConfirm = false; + private JTextField usernameField; + private ValidatableTextField ipField; + private JPasswordField passwordField; public ConnectToServerDialog(Frame owner) { - super(owner, I18n.translate("prompt.connect.title"), true); + super(owner, "prompt.connect.title", "prompt.connect.confirm", "prompt.cancel"); + + setSize(new Dimension(400, 185)); + setLocationRelativeTo(owner); + } - Container contentPane = getContentPane(); - contentPane.setLayout(new BorderLayout()); - Container inputContainer = new JPanel(new GridBagLayout()); - GridBagConstraints c = new GridBagConstraints(); + @Override + protected List> createComponents() { usernameField = new JTextField(System.getProperty("user.name")); ipField = new ValidatableTextField(); passwordField = new JPasswordField(); - List labels = Stream.of("prompt.connect.username", "prompt.connect.address", "prompt.password") - .map(I18n::translate) - .map(JLabel::new) - .collect(Collectors.toList()); - List inputs = Arrays.asList(usernameField, ipField, passwordField); - - for (int i = 0; i < inputs.size(); i += 1) { - c.gridy = i; - c.insets = new Insets(4, 4, 4, 4); - - c.gridx = 0; - c.weightx = 0.0; - c.anchor = GridBagConstraints.LINE_END; - c.fill = GridBagConstraints.NONE; - inputContainer.add(labels.get(i), c); - - c.gridx = 1; - c.weightx = 1.0; - c.anchor = GridBagConstraints.LINE_START; - c.fill = GridBagConstraints.HORIZONTAL; - inputs.get(i).addActionListener(event -> confirm()); - inputContainer.add(inputs.get(i), c); - } - contentPane.add(inputContainer, BorderLayout.CENTER); - Container buttonContainer = new JPanel(new GridBagLayout()); - c = new GridBagConstraints(); - c.weightx = 1.0; - c.insets = new Insets(4, 4, 4, 4); - c.anchor = GridBagConstraints.LINE_END; - JButton connectButton = new JButton(I18n.translate("prompt.connect.confirm")); - connectButton.addActionListener(event -> confirm()); - buttonContainer.add(connectButton, c); - c.weightx = 0.0; - c.anchor = GridBagConstraints.CENTER; - JButton abortButton = new JButton(I18n.translate("prompt.cancel")); - abortButton.addActionListener(event -> cancel()); - buttonContainer.add(abortButton, c); - contentPane.add(buttonContainer, BorderLayout.SOUTH); - - setLocationRelativeTo(owner); - setSize(new Dimension(400, 185)); - } - - private void confirm() { - vc.reset(); - validateInputs(); - if (vc.canProceed()) { - actionConfirm = true; - setVisible(false); - } - } + usernameField.addActionListener(event -> confirm()); + ipField.addActionListener(event -> confirm()); + passwordField.addActionListener(event -> confirm()); - private void cancel() { - actionConfirm = false; - setVisible(false); + return Arrays.asList( + new Pair<>("prompt.connect.username", usernameField), + new Pair<>("prompt.connect.address", ipField), + new Pair<>("prompt.password", passwordField) + ); } public void validateInputs() { @@ -103,7 +56,7 @@ public class ConnectToServerDialog extends JDialog { } public Result getResult() { - if (!actionConfirm) return null; + if (!isActionConfirm()) return null; vc.reset(); validateInputs(); if (!vc.canProceed()) return null; diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/CreateServerDialog.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/CreateServerDialog.java index bc4e9c9..f2bc7db 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/CreateServerDialog.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/CreateServerDialog.java @@ -1,96 +1,45 @@ package cuchaz.enigma.gui.dialog; -import java.awt.*; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Frame; import java.util.Arrays; import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import javax.swing.*; import cuchaz.enigma.gui.elements.ValidatablePasswordField; import cuchaz.enigma.gui.elements.ValidatableTextField; import cuchaz.enigma.network.EnigmaServer; -import cuchaz.enigma.utils.I18n; +import cuchaz.enigma.utils.Pair; import cuchaz.enigma.utils.validation.Message; import cuchaz.enigma.utils.validation.StandardValidation; -import cuchaz.enigma.utils.validation.ValidationContext; - -public class CreateServerDialog extends JDialog { - private final ValidationContext vc = new ValidationContext(); +public class CreateServerDialog extends AbstractDialog { - private final ValidatableTextField portField; - private final ValidatablePasswordField passwordField; - private boolean actionConfirm = false; + private ValidatableTextField portField; + private ValidatablePasswordField passwordField; public CreateServerDialog(Frame owner) { - super(owner, I18n.translate("prompt.create_server.title"), true); - - Container contentPane = getContentPane(); - contentPane.setLayout(new BorderLayout()); - Container inputContainer = new JPanel(new GridBagLayout()); - GridBagConstraints c = new GridBagConstraints(); - portField = new ValidatableTextField(Integer.toString(EnigmaServer.DEFAULT_PORT)); - passwordField = new ValidatablePasswordField(); + super(owner, "prompt.create_server.title", "prompt.create_server.confirm", "prompt.cancel"); - java.util.List labels = Stream.of("prompt.create_server.port", "prompt.password") - .map(I18n::translate) - .map(JLabel::new) - .collect(Collectors.toList()); - List inputs = Arrays.asList(portField, passwordField); - - for (int i = 0; i < inputs.size(); i += 1) { - c.gridy = i; - c.insets = new Insets(4, 4, 4, 4); - - c.gridx = 0; - c.weightx = 0.0; - c.anchor = GridBagConstraints.LINE_END; - c.fill = GridBagConstraints.NONE; - inputContainer.add(labels.get(i), c); - - c.gridx = 1; - c.weightx = 1.0; - c.anchor = GridBagConstraints.LINE_START; - c.fill = GridBagConstraints.HORIZONTAL; - inputs.get(i).addActionListener(event -> confirm()); - inputContainer.add(inputs.get(i), c); - } - contentPane.add(inputContainer, BorderLayout.CENTER); - Container buttonContainer = new JPanel(new GridBagLayout()); - c = new GridBagConstraints(); - c.weightx = 1.0; - c.insets = new Insets(4, 4, 4, 4); - c.anchor = GridBagConstraints.LINE_END; - JButton connectButton = new JButton(I18n.translate("prompt.create_server.confirm")); - connectButton.addActionListener(event -> confirm()); - buttonContainer.add(connectButton, c); - c.weightx = 0.0; - c.anchor = GridBagConstraints.CENTER; - JButton abortButton = new JButton(I18n.translate("prompt.cancel")); - abortButton.addActionListener(event -> cancel()); - buttonContainer.add(abortButton, c); - contentPane.add(buttonContainer, BorderLayout.SOUTH); - - setLocationRelativeTo(owner); setSize(new Dimension(400, 150)); + setLocationRelativeTo(owner); } - private void confirm() { - vc.reset(); - validateInputs(); - if (vc.canProceed()) { - actionConfirm = true; - setVisible(false); - } - } + @Override + protected List> createComponents() { + portField = new ValidatableTextField(Integer.toString(EnigmaServer.DEFAULT_PORT)); + passwordField = new ValidatablePasswordField(); - private void cancel() { - actionConfirm = false; - setVisible(false); + portField.addActionListener(event -> confirm()); + passwordField.addActionListener(event -> confirm()); + + return Arrays.asList( + new Pair<>("prompt.create_server.port", portField), + new Pair<>("prompt.password", passwordField) + ); } + @Override public void validateInputs() { vc.setActiveElement(portField); StandardValidation.isIntInRange(vc, portField.getText(), 0, 65535); @@ -101,7 +50,7 @@ public class CreateServerDialog extends JDialog { } public Result getResult() { - if (!actionConfirm) return null; + if (!isActionConfirm()) return null; vc.reset(); validateInputs(); if (!vc.canProceed()) return null; -- cgit v1.2.3 From 50a53b516b8567f2a013c0b595d6fdab37fb47bf Mon Sep 17 00:00:00 2001 From: 2xsaiko Date: Wed, 3 Jun 2020 21:46:50 +0200 Subject: Fix dialogs for scale --- .../java/cuchaz/enigma/gui/dialog/AbstractDialog.java | 15 +++++---------- .../cuchaz/enigma/gui/dialog/ConnectToServerDialog.java | 6 +++++- .../java/cuchaz/enigma/gui/dialog/CreateServerDialog.java | 6 +++++- 3 files changed, 15 insertions(+), 12 deletions(-) (limited to 'enigma-swing/src/main/java') diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/AbstractDialog.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/AbstractDialog.java index a4d8e1f..b179eac 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/AbstractDialog.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/AbstractDialog.java @@ -8,6 +8,7 @@ import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; +import cuchaz.enigma.gui.util.ScaleUtil; import cuchaz.enigma.utils.I18n; import cuchaz.enigma.utils.Pair; import cuchaz.enigma.utils.validation.ValidationContext; @@ -34,7 +35,7 @@ public abstract class AbstractDialog extends JDialog { Component component = entry.b; c.gridy = i; - c.insets = new Insets(4, 4, 4, 4); + c.insets = ScaleUtil.getInsets(4, 4, 4, 4); c.gridx = 0; c.weightx = 0.0; @@ -49,19 +50,13 @@ public abstract class AbstractDialog extends JDialog { inputContainer.add(component, c); } contentPane.add(inputContainer, BorderLayout.CENTER); - Container buttonContainer = new JPanel(new GridBagLayout()); - c = new GridBagConstraints(); - c.weightx = 1.0; - c.insets = new Insets(4, 4, 4, 4); - c.anchor = GridBagConstraints.LINE_END; + Container buttonContainer = new JPanel(new FlowLayout(FlowLayout.RIGHT, ScaleUtil.scale(4), ScaleUtil.scale(4))); JButton connectButton = new JButton(I18n.translate(confirmAction)); connectButton.addActionListener(event -> confirm()); - buttonContainer.add(connectButton, c); - c.weightx = 0.0; - c.anchor = GridBagConstraints.CENTER; + buttonContainer.add(connectButton); JButton abortButton = new JButton(I18n.translate(cancelAction)); abortButton.addActionListener(event -> cancel()); - buttonContainer.add(abortButton, c); + buttonContainer.add(abortButton); contentPane.add(buttonContainer, BorderLayout.SOUTH); pack(); diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java index 79b0c4e..d78e565 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java @@ -11,6 +11,7 @@ import javax.swing.JPasswordField; import javax.swing.JTextField; import cuchaz.enigma.gui.elements.ValidatableTextField; +import cuchaz.enigma.gui.util.ScaleUtil; import cuchaz.enigma.network.EnigmaServer; import cuchaz.enigma.utils.Pair; import cuchaz.enigma.utils.ServerAddress; @@ -25,7 +26,10 @@ public class ConnectToServerDialog extends AbstractDialog { public ConnectToServerDialog(Frame owner) { super(owner, "prompt.connect.title", "prompt.connect.confirm", "prompt.cancel"); - setSize(new Dimension(400, 185)); + Dimension preferredSize = getPreferredSize(); + preferredSize.width = ScaleUtil.scale(400); + setPreferredSize(preferredSize); + pack(); setLocationRelativeTo(owner); } diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/CreateServerDialog.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/CreateServerDialog.java index f2bc7db..ddd3bc3 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/CreateServerDialog.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/CreateServerDialog.java @@ -8,6 +8,7 @@ import java.util.List; import cuchaz.enigma.gui.elements.ValidatablePasswordField; import cuchaz.enigma.gui.elements.ValidatableTextField; +import cuchaz.enigma.gui.util.ScaleUtil; import cuchaz.enigma.network.EnigmaServer; import cuchaz.enigma.utils.Pair; import cuchaz.enigma.utils.validation.Message; @@ -21,7 +22,10 @@ public class CreateServerDialog extends AbstractDialog { public CreateServerDialog(Frame owner) { super(owner, "prompt.create_server.title", "prompt.create_server.confirm", "prompt.cancel"); - setSize(new Dimension(400, 150)); + Dimension preferredSize = getPreferredSize(); + preferredSize.width = ScaleUtil.scale(400); + setPreferredSize(preferredSize); + pack(); setLocationRelativeTo(owner); } -- cgit v1.2.3 From 535447cd4e5871336b444702a53bfca713267c8b Mon Sep 17 00:00:00 2001 From: 2xsaiko Date: Thu, 4 Jun 2020 00:53:27 +0200 Subject: Use StandardValidation.notBlank instead of manually checking field text --- .../main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'enigma-swing/src/main/java') diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java index d78e565..db1ceb1 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java @@ -16,6 +16,7 @@ import cuchaz.enigma.network.EnigmaServer; import cuchaz.enigma.utils.Pair; import cuchaz.enigma.utils.ServerAddress; import cuchaz.enigma.utils.validation.Message; +import cuchaz.enigma.utils.validation.StandardValidation; public class ConnectToServerDialog extends AbstractDialog { @@ -52,9 +53,7 @@ public class ConnectToServerDialog extends AbstractDialog { public void validateInputs() { vc.setActiveElement(ipField); - if (ipField.getText().trim().isEmpty()) { - vc.raise(Message.EMPTY_FIELD); - } else if (ServerAddress.from(ipField.getText(), EnigmaServer.DEFAULT_PORT) == null) { + if (StandardValidation.notBlank(vc, ipField.getText())) { vc.raise(Message.INVALID_IP); } } -- cgit v1.2.3 From a7163d46a6414c38c3eb4ba1e6783b3c158312db Mon Sep 17 00:00:00 2001 From: 2xsaiko Date: Thu, 4 Jun 2020 10:10:53 +0200 Subject: Move ServerAddress to enigma-server --- .../src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'enigma-swing/src/main/java') diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java index db1ceb1..f23007a 100644 --- a/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java @@ -13,8 +13,8 @@ import javax.swing.JTextField; import cuchaz.enigma.gui.elements.ValidatableTextField; import cuchaz.enigma.gui.util.ScaleUtil; import cuchaz.enigma.network.EnigmaServer; +import cuchaz.enigma.network.ServerAddress; import cuchaz.enigma.utils.Pair; -import cuchaz.enigma.utils.ServerAddress; import cuchaz.enigma.utils.validation.Message; import cuchaz.enigma.utils.validation.StandardValidation; -- cgit v1.2.3