From e23aef92dc1fcaedd347be0347726b2a7af21517 Mon Sep 17 00:00:00 2001 From: Speedy Date: Wed, 1 Mar 2017 22:17:57 -0600 Subject: [PATCH] SPARK-1899 Room password dialog should mask/hide the actual password (#309) * SPARK-1899 Room password dialog should mask/hide the actual password * SPARK-1899 Room password dialog should mask/hide the actual password --- .../spark/ui/RequestFocusListener.java | 65 +++++++++++++++++++ .../ui/conferences/JoinRoomSwingWorker.java | 8 ++- 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 core/src/main/java/org/jivesoftware/spark/ui/RequestFocusListener.java diff --git a/core/src/main/java/org/jivesoftware/spark/ui/RequestFocusListener.java b/core/src/main/java/org/jivesoftware/spark/ui/RequestFocusListener.java new file mode 100644 index 000000000..6f02871ad --- /dev/null +++ b/core/src/main/java/org/jivesoftware/spark/ui/RequestFocusListener.java @@ -0,0 +1,65 @@ +package org.jivesoftware.spark.ui; + +import javax.swing.JComponent; +import javax.swing.event.AncestorEvent; +import javax.swing.event.AncestorListener; + +/** + * Convenience class to request focus on a component. + * + * When the component is added to a realized Window then component will + * request focus immediately, since the ancestorAdded event is fired + * immediately. + * + * When the component is added to a non realized Window, then the focus + * request will be made once the window is realized, since the + * ancestorAdded event will not be fired until then. + * + * Using the default constructor will cause the listener to be removed + * from the component once the AncestorEvent is generated. A second constructor + * allows you to specify a boolean value of false to prevent the + * AncestorListener from being removed when the event is generated. This will + * allow you to reuse the listener each time the event is generated. + * + * @author Rob Camick + */ + +public class RequestFocusListener implements AncestorListener { + private boolean removeListener; + + /* + * Convenience constructor. The listener is only used once and then it is + * removed from the component. + */ + + public RequestFocusListener() { + this(true); + } + + /* + * Constructor that controls whether this listen can be used once or + * multiple times. + * + * @param removeListener when true this listener is only invoked once + * otherwise it can be invoked multiple times. + */ + + public RequestFocusListener(boolean removeListener) { + this.removeListener = removeListener; + } + + @Override + public void ancestorAdded(AncestorEvent e) { + JComponent component = e.getComponent(); + component.requestFocusInWindow(); + + if (removeListener) + component.removeAncestorListener( this ); + } + + @Override + public void ancestorMoved(AncestorEvent e) {} + + @Override + public void ancestorRemoved(AncestorEvent e) {} +} diff --git a/core/src/main/java/org/jivesoftware/spark/ui/conferences/JoinRoomSwingWorker.java b/core/src/main/java/org/jivesoftware/spark/ui/conferences/JoinRoomSwingWorker.java index dcd37756f..219a64550 100644 --- a/core/src/main/java/org/jivesoftware/spark/ui/conferences/JoinRoomSwingWorker.java +++ b/core/src/main/java/org/jivesoftware/spark/ui/conferences/JoinRoomSwingWorker.java @@ -10,6 +10,7 @@ import org.jivesoftware.spark.SparkManager; import org.jivesoftware.spark.ui.ChatContainer; import org.jivesoftware.spark.ui.ChatRoom; import org.jivesoftware.spark.ui.ChatRoomNotFoundException; +import org.jivesoftware.spark.ui.RequestFocusListener; import org.jivesoftware.spark.ui.rooms.GroupChatRoom; import org.jivesoftware.spark.util.ModelUtil; import org.jivesoftware.spark.util.SwingWorker; @@ -112,7 +113,12 @@ public class JoinRoomSwingWorker extends SwingWorker { if ( password == null && ConferenceUtils.isPasswordRequired( roomJID ) ) { - password = JOptionPane.showInputDialog( null, Res.getString("message.enter.room.password"), Res.getString("title.password.required"), JOptionPane.QUESTION_MESSAGE ); + JLabel label = new JLabel(Res.getString("message.enter.room.password")); + JPasswordField passwordField = new JPasswordField(); + passwordField.addAncestorListener(new RequestFocusListener()); + JOptionPane.showConfirmDialog(null, new Object[]{label, passwordField}, Res.getString("title.password.required"), JOptionPane.OK_CANCEL_OPTION); + password = new String(passwordField.getPassword()); + if ( !ModelUtil.hasLength( password ) ) { return null;