diff options
| author | 2020-04-22 20:21:15 +0200 | |
|---|---|---|
| committer | 2020-06-03 23:55:56 +0200 | |
| commit | 493b291dceb20b58b659764db2e4013681c26999 (patch) | |
| tree | babe0cb7d820d70bf774689be5323cb191ee34e9 /enigma-swing | |
| parent | Fix 'Save Mappings' entry missing from the menu and ctrl+s not working (diff) | |
| download | enigma-493b291dceb20b58b659764db2e4013681c26999.tar.gz enigma-493b291dceb20b58b659764db2e4013681c26999.tar.xz enigma-493b291dceb20b58b659764db2e4013681c26999.zip | |
Improve connect dialog
Diffstat (limited to 'enigma-swing')
3 files changed, 175 insertions, 51 deletions
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 c5f505cf..070d03d4 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 @@ | |||
| 1 | package cuchaz.enigma.gui.dialog; | 1 | package cuchaz.enigma.gui.dialog; |
| 2 | 2 | ||
| 3 | import java.awt.*; | ||
| 4 | import java.util.Arrays; | ||
| 5 | import java.util.List; | ||
| 6 | import java.util.Objects; | ||
| 7 | import java.util.stream.Collectors; | ||
| 8 | import java.util.stream.Stream; | ||
| 9 | |||
| 10 | import javax.swing.*; | ||
| 11 | |||
| 12 | import cuchaz.enigma.gui.elements.VerifiableTextField; | ||
| 3 | import cuchaz.enigma.network.EnigmaServer; | 13 | import cuchaz.enigma.network.EnigmaServer; |
| 4 | import cuchaz.enigma.utils.I18n; | 14 | import cuchaz.enigma.utils.I18n; |
| 15 | import cuchaz.enigma.utils.ServerAddress; | ||
| 5 | 16 | ||
| 6 | import javax.swing.*; | 17 | public class ConnectToServerDialog extends JDialog { |
| 7 | import java.awt.Frame; | 18 | |
| 8 | 19 | private final JTextField usernameField; | |
| 9 | public class ConnectToServerDialog { | 20 | private final VerifiableTextField ipField; |
| 10 | 21 | private final JPasswordField passwordField; | |
| 11 | public static Result show(Frame parentComponent) { | 22 | private boolean success = false; |
| 12 | JTextField usernameField = new JTextField(System.getProperty("user.name"), 20); | 23 | |
| 13 | JPanel usernameRow = new JPanel(); | 24 | public ConnectToServerDialog(Frame owner) { |
| 14 | usernameRow.add(new JLabel(I18n.translate("prompt.connect.username"))); | 25 | super(owner, I18n.translate("prompt.connect.title"), true); |
| 15 | usernameRow.add(usernameField); | 26 | |
| 16 | JTextField ipField = new JTextField(20); | 27 | Container contentPane = getContentPane(); |
| 17 | JPanel ipRow = new JPanel(); | 28 | contentPane.setLayout(new BorderLayout()); |
| 18 | ipRow.add(new JLabel(I18n.translate("prompt.connect.ip"))); | 29 | Container inputContainer = new JPanel(new GridBagLayout()); |
| 19 | ipRow.add(ipField); | 30 | GridBagConstraints c = new GridBagConstraints(); |
| 20 | JTextField portField = new JTextField(String.valueOf(EnigmaServer.DEFAULT_PORT), 10); | 31 | usernameField = new JTextField(System.getProperty("user.name")); |
| 21 | JPanel portRow = new JPanel(); | 32 | ipField = new VerifiableTextField(); |
| 22 | portRow.add(new JLabel(I18n.translate("prompt.port"))); | 33 | passwordField = new JPasswordField(); |
| 23 | portRow.add(portField); | 34 | |
| 24 | JPasswordField passwordField = new JPasswordField(20); | 35 | List<JLabel> labels = Stream.of("prompt.connect.username", "prompt.connect.address", "prompt.password") |
| 25 | JPanel passwordRow = new JPanel(); | 36 | .map(I18n::translate) |
| 26 | passwordRow.add(new JLabel(I18n.translate("prompt.password"))); | 37 | .map(JLabel::new) |
| 27 | passwordRow.add(passwordField); | 38 | .collect(Collectors.toList()); |
| 28 | 39 | List<JTextField> inputs = Arrays.asList(usernameField, ipField, passwordField); | |
| 29 | int response = JOptionPane.showConfirmDialog(parentComponent, new Object[]{usernameRow, ipRow, portRow, passwordRow}, I18n.translate("prompt.connect.title"), JOptionPane.OK_CANCEL_OPTION); | 40 | |
| 30 | if (response != JOptionPane.OK_OPTION) { | 41 | for (int i = 0; i < inputs.size(); i += 1) { |
| 31 | return null; | 42 | c.gridy = i; |
| 43 | c.insets = new Insets(4, 4, 4, 4); | ||
| 44 | |||
| 45 | c.gridx = 0; | ||
| 46 | c.weightx = 0.0; | ||
| 47 | c.anchor = GridBagConstraints.LINE_END; | ||
| 48 | c.fill = GridBagConstraints.NONE; | ||
| 49 | inputContainer.add(labels.get(i), c); | ||
| 50 | |||
| 51 | c.gridx = 1; | ||
| 52 | c.weightx = 1.0; | ||
| 53 | c.anchor = GridBagConstraints.LINE_START; | ||
| 54 | c.fill = GridBagConstraints.HORIZONTAL; | ||
| 55 | inputs.get(i).addActionListener(event -> confirm()); | ||
| 56 | inputContainer.add(inputs.get(i), c); | ||
| 32 | } | 57 | } |
| 58 | contentPane.add(inputContainer, BorderLayout.CENTER); | ||
| 59 | Container buttonContainer = new JPanel(new GridBagLayout()); | ||
| 60 | c = new GridBagConstraints(); | ||
| 61 | c.weightx = 1.0; | ||
| 62 | c.insets = new Insets(4, 4, 4, 4); | ||
| 63 | c.anchor = GridBagConstraints.LINE_END; | ||
| 64 | JButton connectButton = new JButton(I18n.translate("prompt.connect.confirm")); | ||
| 65 | connectButton.addActionListener(event -> confirm()); | ||
| 66 | buttonContainer.add(connectButton, c); | ||
| 67 | c.weightx = 0.0; | ||
| 68 | c.anchor = GridBagConstraints.CENTER; | ||
| 69 | JButton abortButton = new JButton(I18n.translate("prompt.connect.cancel")); | ||
| 70 | abortButton.addActionListener(event -> cancel()); | ||
| 71 | buttonContainer.add(abortButton, c); | ||
| 72 | contentPane.add(buttonContainer, BorderLayout.SOUTH); | ||
| 73 | |||
| 74 | setLocationRelativeTo(owner); | ||
| 75 | setSize(new Dimension(400, 185)); | ||
| 76 | } | ||
| 33 | 77 | ||
| 34 | String username = usernameField.getText(); | 78 | private void confirm() { |
| 35 | String ip = ipField.getText(); | 79 | if (validateInputs()) { |
| 36 | int port; | 80 | success = true; |
| 37 | try { | 81 | setVisible(false); |
| 38 | port = Integer.parseInt(portField.getText()); | ||
| 39 | } catch (NumberFormatException e) { | ||
| 40 | JOptionPane.showMessageDialog(parentComponent, I18n.translate("prompt.port.nan"), I18n.translate("prompt.connect.title"), JOptionPane.ERROR_MESSAGE); | ||
| 41 | return null; | ||
| 42 | } | 82 | } |
| 43 | if (port < 0 || port >= 65536) { | 83 | } |
| 44 | JOptionPane.showMessageDialog(parentComponent, I18n.translate("prompt.port.invalid"), I18n.translate("prompt.connect.title"), JOptionPane.ERROR_MESSAGE); | 84 | |
| 45 | return null; | 85 | private void cancel() { |
| 86 | success = false; | ||
| 87 | setVisible(false); | ||
| 88 | } | ||
| 89 | |||
| 90 | public boolean validateInputs() { | ||
| 91 | boolean error = false; | ||
| 92 | ipField.setErrorState(false); | ||
| 93 | |||
| 94 | if (ServerAddress.from(ipField.getText(), EnigmaServer.DEFAULT_PORT) == null) { | ||
| 95 | ipField.setErrorState(true); | ||
| 96 | error = true; | ||
| 46 | } | 97 | } |
| 47 | char[] password = passwordField.getPassword(); | ||
| 48 | 98 | ||
| 49 | return new Result(username, ip, port, password); | 99 | return !error; |
| 100 | } | ||
| 101 | |||
| 102 | public Result getResult() { | ||
| 103 | if (!success) return null; | ||
| 104 | return new Result( | ||
| 105 | usernameField.getText(), | ||
| 106 | Objects.requireNonNull(ServerAddress.from(ipField.getText(), EnigmaServer.DEFAULT_PORT)), | ||
| 107 | passwordField.getPassword() | ||
| 108 | ); | ||
| 109 | } | ||
| 110 | |||
| 111 | public static Result show(Frame parent) { | ||
| 112 | ConnectToServerDialog d = new ConnectToServerDialog(parent); | ||
| 113 | |||
| 114 | d.setVisible(true); | ||
| 115 | Result r = d.getResult(); | ||
| 116 | |||
| 117 | d.dispose(); | ||
| 118 | return r; | ||
| 50 | } | 119 | } |
| 51 | 120 | ||
| 52 | public static class Result { | 121 | public static class Result { |
| 53 | private final String username; | 122 | private final String username; |
| 54 | private final String ip; | 123 | private final ServerAddress address; |
| 55 | private final int port; | ||
| 56 | private final char[] password; | 124 | private final char[] password; |
| 57 | 125 | ||
| 58 | public Result(String username, String ip, int port, char[] password) { | 126 | public Result(String username, ServerAddress address, char[] password) { |
| 59 | this.username = username; | 127 | this.username = username; |
| 60 | this.ip = ip; | 128 | this.address = address; |
| 61 | this.port = port; | ||
| 62 | this.password = password; | 129 | this.password = password; |
| 63 | } | 130 | } |
| 64 | 131 | ||
| @@ -66,12 +133,8 @@ public class ConnectToServerDialog { | |||
| 66 | return username; | 133 | return username; |
| 67 | } | 134 | } |
| 68 | 135 | ||
| 69 | public String getIp() { | 136 | public ServerAddress getAddress() { |
| 70 | return ip; | 137 | return address; |
| 71 | } | ||
| 72 | |||
| 73 | public int getPort() { | ||
| 74 | return port; | ||
| 75 | } | 138 | } |
| 76 | 139 | ||
| 77 | public char[] getPassword() { | 140 | 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 3378d1a4..1481a9dc 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 { | |||
| 227 | } | 227 | } |
| 228 | this.gui.getController().disconnectIfConnected(null); | 228 | this.gui.getController().disconnectIfConnected(null); |
| 229 | try { | 229 | try { |
| 230 | this.gui.getController().createClient(result.getUsername(), result.getIp(), result.getPort(), result.getPassword()); | 230 | this.gui.getController().createClient(result.getUsername(), result.getAddress().address, result.getAddress().port, result.getPassword()); |
| 231 | } catch (IOException e) { | 231 | } catch (IOException e) { |
| 232 | JOptionPane.showMessageDialog(this.gui.getFrame(), e.toString(), I18n.translate("menu.collab.connect.error"), JOptionPane.ERROR_MESSAGE); | 232 | JOptionPane.showMessageDialog(this.gui.getFrame(), e.toString(), I18n.translate("menu.collab.connect.error"), JOptionPane.ERROR_MESSAGE); |
| 233 | this.gui.getController().disconnectIfConnected(null); | 233 | 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 00000000..41a24840 --- /dev/null +++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/elements/VerifiableTextField.java | |||
| @@ -0,0 +1,61 @@ | |||
| 1 | package cuchaz.enigma.gui.elements; | ||
| 2 | |||
| 3 | import java.awt.Color; | ||
| 4 | import java.awt.Graphics; | ||
| 5 | import java.awt.event.FocusAdapter; | ||
| 6 | import java.awt.event.FocusEvent; | ||
| 7 | |||
| 8 | import javax.swing.JTextField; | ||
| 9 | import javax.swing.text.Document; | ||
| 10 | |||
| 11 | public class VerifiableTextField extends JTextField { | ||
| 12 | |||
| 13 | private boolean hasError; | ||
| 14 | |||
| 15 | public VerifiableTextField() { | ||
| 16 | } | ||
| 17 | |||
| 18 | public VerifiableTextField(String text) { | ||
| 19 | super(text); | ||
| 20 | } | ||
| 21 | |||
| 22 | public VerifiableTextField(int columns) { | ||
| 23 | super(columns); | ||
| 24 | } | ||
| 25 | |||
| 26 | public VerifiableTextField(String text, int columns) { | ||
| 27 | super(text, columns); | ||
| 28 | } | ||
| 29 | |||
| 30 | public VerifiableTextField(Document doc, String text, int columns) { | ||
| 31 | super(doc, text, columns); | ||
| 32 | } | ||
| 33 | |||
| 34 | { | ||
| 35 | addFocusListener(new FocusAdapter() { | ||
| 36 | @Override | ||
| 37 | public void focusGained(FocusEvent e) { | ||
| 38 | setErrorState(false); | ||
| 39 | } | ||
| 40 | }); | ||
| 41 | } | ||
| 42 | |||
| 43 | public void setErrorState(boolean b) { | ||
| 44 | this.hasError = b; | ||
| 45 | repaint(); | ||
| 46 | } | ||
| 47 | |||
| 48 | @Override | ||
| 49 | public void paint(Graphics g) { | ||
| 50 | super.paint(g); | ||
| 51 | if (hasError) { | ||
| 52 | g.setColor(Color.RED); | ||
| 53 | int x1 = getWidth() - 9; | ||
| 54 | int x2 = getWidth() - 2; | ||
| 55 | int y1 = 1; | ||
| 56 | int y2 = 8; | ||
| 57 | g.fillPolygon(new int[]{x1, x2, x2}, new int[]{y1, y1, y2}, 3); | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 61 | } | ||