source: josm/trunk/src/org/openstreetmap/josm/gui/io/CredentialDialog.java@ 12012

Last change on this file since 12012 was 10791, checked in by simon04, 8 years ago

see #13319 - Use InputMapUtils where applicable (VK_ESCAPE)

  • Property svn:eol-style set to native
File size: 15.0 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.io;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.BorderLayout;
7import java.awt.Dimension;
8import java.awt.FlowLayout;
9import java.awt.Font;
10import java.awt.GridBagConstraints;
11import java.awt.GridBagLayout;
12import java.awt.Insets;
13import java.awt.event.ActionEvent;
14import java.awt.event.FocusAdapter;
15import java.awt.event.FocusEvent;
16import java.awt.event.KeyAdapter;
17import java.awt.event.KeyEvent;
18import java.awt.event.WindowAdapter;
19import java.awt.event.WindowEvent;
20import java.util.Objects;
21
22import javax.swing.AbstractAction;
23import javax.swing.BorderFactory;
24import javax.swing.JCheckBox;
25import javax.swing.JDialog;
26import javax.swing.JLabel;
27import javax.swing.JPanel;
28import javax.swing.JTextField;
29
30import org.openstreetmap.josm.Main;
31import org.openstreetmap.josm.gui.SideButton;
32import org.openstreetmap.josm.gui.help.ContextSensitiveHelpAction;
33import org.openstreetmap.josm.gui.help.HelpUtil;
34import org.openstreetmap.josm.gui.preferences.server.ProxyPreferencesPanel;
35import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
36import org.openstreetmap.josm.gui.widgets.JosmPasswordField;
37import org.openstreetmap.josm.gui.widgets.JosmTextField;
38import org.openstreetmap.josm.io.OsmApi;
39import org.openstreetmap.josm.tools.ImageProvider;
40import org.openstreetmap.josm.tools.InputMapUtils;
41import org.openstreetmap.josm.tools.WindowGeometry;
42
43public class CredentialDialog extends JDialog {
44
45 public static CredentialDialog getOsmApiCredentialDialog(String username, String password, String host,
46 String saveUsernameAndPasswordCheckboxText) {
47 CredentialDialog dialog = new CredentialDialog(saveUsernameAndPasswordCheckboxText);
48 if (Objects.equals(OsmApi.getOsmApi().getHost(), host)) {
49 dialog.prepareForOsmApiCredentials(username, password);
50 } else {
51 dialog.prepareForOtherHostCredentials(username, password, host);
52 }
53 dialog.pack();
54 return dialog;
55 }
56
57 public static CredentialDialog getHttpProxyCredentialDialog(String username, String password, String host,
58 String saveUsernameAndPasswordCheckboxText) {
59 CredentialDialog dialog = new CredentialDialog(saveUsernameAndPasswordCheckboxText);
60 dialog.prepareForProxyCredentials(username, password);
61 dialog.pack();
62 return dialog;
63 }
64
65 private boolean canceled;
66 protected CredentialPanel pnlCredentials;
67 private final String saveUsernameAndPasswordCheckboxText;
68
69 public boolean isCanceled() {
70 return canceled;
71 }
72
73 protected void setCanceled(boolean canceled) {
74 this.canceled = canceled;
75 }
76
77 @Override
78 public void setVisible(boolean visible) {
79 if (visible) {
80 WindowGeometry.centerInWindow(Main.parent, new Dimension(350, 300)).applySafe(this);
81 }
82 super.setVisible(visible);
83 }
84
85 protected JPanel createButtonPanel() {
86 JPanel pnl = new JPanel(new FlowLayout());
87 pnl.add(new SideButton(new OKAction()));
88 pnl.add(new SideButton(new CancelAction()));
89 pnl.add(new SideButton(new ContextSensitiveHelpAction(HelpUtil.ht("/Dialog/Password"))));
90 return pnl;
91 }
92
93 protected void build() {
94 getContentPane().setLayout(new BorderLayout());
95 getContentPane().add(createButtonPanel(), BorderLayout.SOUTH);
96
97 addWindowListener(new WindowEventHander());
98 InputMapUtils.addEscapeAction(getRootPane(), new CancelAction());
99
100 getRootPane().setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
101 }
102
103 public CredentialDialog(String saveUsernameAndPasswordCheckboxText) {
104 this.saveUsernameAndPasswordCheckboxText = saveUsernameAndPasswordCheckboxText;
105 setModalityType(ModalityType.DOCUMENT_MODAL);
106 try {
107 setAlwaysOnTop(true);
108 } catch (SecurityException e) {
109 Main.warn(e, tr("Failed to put Credential Dialog always on top. Caught security exception."));
110 }
111 build();
112 }
113
114 public void prepareForOsmApiCredentials(String username, String password) {
115 setTitle(tr("Enter credentials for OSM API"));
116 pnlCredentials = new OsmApiCredentialsPanel(this);
117 getContentPane().add(pnlCredentials, BorderLayout.CENTER);
118 pnlCredentials.init(username, password);
119 validate();
120 }
121
122 public void prepareForOtherHostCredentials(String username, String password, String host) {
123 setTitle(tr("Enter credentials for host"));
124 pnlCredentials = new OtherHostCredentialsPanel(this, host);
125 getContentPane().add(pnlCredentials, BorderLayout.CENTER);
126 pnlCredentials.init(username, password);
127 validate();
128 }
129
130 public void prepareForProxyCredentials(String username, String password) {
131 setTitle(tr("Enter credentials for HTTP proxy"));
132 pnlCredentials = new HttpProxyCredentialsPanel(this);
133 getContentPane().add(pnlCredentials, BorderLayout.CENTER);
134 pnlCredentials.init(username, password);
135 validate();
136 }
137
138 public String getUsername() {
139 if (pnlCredentials == null)
140 return null;
141 return pnlCredentials.getUserName();
142 }
143
144 public char[] getPassword() {
145 if (pnlCredentials == null)
146 return null;
147 return pnlCredentials.getPassword();
148 }
149
150 public boolean isSaveCredentials() {
151 if (pnlCredentials == null)
152 return false;
153 return pnlCredentials.isSaveCredentials();
154 }
155
156 protected static class CredentialPanel extends JPanel {
157 protected JosmTextField tfUserName;
158 protected JosmPasswordField tfPassword;
159 protected JCheckBox cbSaveCredentials;
160 protected final JMultilineLabel lblHeading = new JMultilineLabel("");
161 protected final JMultilineLabel lblWarning = new JMultilineLabel("");
162 protected CredentialDialog owner; // owner Dependency Injection to use Key listeners for username and password text fields
163
164 protected void build() {
165 tfUserName = new JosmTextField(20);
166 tfPassword = new JosmPasswordField(20);
167 tfUserName.addFocusListener(new SelectAllOnFocusHandler());
168 tfPassword.addFocusListener(new SelectAllOnFocusHandler());
169 tfUserName.addKeyListener(new TFKeyListener(owner, tfUserName, tfPassword));
170 tfPassword.addKeyListener(new TFKeyListener(owner, tfPassword, tfUserName));
171 cbSaveCredentials = new JCheckBox(owner != null ? owner.saveUsernameAndPasswordCheckboxText : "");
172
173 setLayout(new GridBagLayout());
174 GridBagConstraints gc = new GridBagConstraints();
175 gc.gridwidth = 2;
176 gc.gridheight = 1;
177 gc.fill = GridBagConstraints.HORIZONTAL;
178 gc.weightx = 1.0;
179 gc.weighty = 0.0;
180 gc.insets = new Insets(0, 0, 10, 0);
181 add(lblHeading, gc);
182
183 gc.gridx = 0;
184 gc.gridy = 1;
185 gc.gridwidth = 1;
186 gc.gridheight = 1;
187 gc.fill = GridBagConstraints.HORIZONTAL;
188 gc.weightx = 0.0;
189 gc.weighty = 0.0;
190 gc.insets = new Insets(0, 0, 10, 10);
191 add(new JLabel(tr("Username")), gc);
192 gc.gridx = 1;
193 gc.gridy = 1;
194 gc.weightx = 1.0;
195 add(tfUserName, gc);
196 gc.gridx = 0;
197 gc.gridy = 2;
198 gc.weightx = 0.0;
199 add(new JLabel(tr("Password")), gc);
200
201 gc.gridx = 1;
202 gc.gridy = 2;
203 gc.weightx = 0.0;
204 add(tfPassword, gc);
205
206 gc.gridx = 0;
207 gc.gridy = 3;
208 gc.gridwidth = 2;
209 gc.gridheight = 1;
210 gc.fill = GridBagConstraints.BOTH;
211 gc.weightx = 1.0;
212 gc.weighty = 0.0;
213 lblWarning.setFont(lblWarning.getFont().deriveFont(Font.ITALIC));
214 add(lblWarning, gc);
215
216 gc.gridx = 0;
217 gc.gridy = 4;
218 gc.weighty = 0.0;
219 add(cbSaveCredentials, gc);
220
221 // consume the remaining space
222 gc.gridx = 0;
223 gc.gridy = 5;
224 gc.weighty = 1.0;
225 add(new JPanel(), gc);
226
227 }
228
229 public CredentialPanel(CredentialDialog owner) {
230 this.owner = owner;
231 }
232
233 public void init(String username, String password) {
234 username = username == null ? "" : username;
235 password = password == null ? "" : password;
236 tfUserName.setText(username);
237 tfPassword.setText(password);
238 cbSaveCredentials.setSelected(!username.isEmpty() && !password.isEmpty());
239 }
240
241 public void startUserInput() {
242 tfUserName.requestFocusInWindow();
243 }
244
245 public String getUserName() {
246 return tfUserName.getText();
247 }
248
249 public char[] getPassword() {
250 return tfPassword.getPassword();
251 }
252
253 public boolean isSaveCredentials() {
254 return cbSaveCredentials.isSelected();
255 }
256
257 protected final void updateWarningLabel(String url) {
258 boolean https = url != null && url.startsWith("https");
259 if (https) {
260 lblWarning.setText(null);
261 } else {
262 lblWarning.setText(tr("Warning: The password is transferred unencrypted."));
263 }
264 lblWarning.setVisible(!https);
265 }
266 }
267
268 private static class OsmApiCredentialsPanel extends CredentialPanel {
269
270 @Override
271 protected void build() {
272 super.build();
273 tfUserName.setToolTipText(tr("Please enter the user name of your OSM account"));
274 tfPassword.setToolTipText(tr("Please enter the password of your OSM account"));
275 String apiUrl = OsmApi.getOsmApi().getBaseUrl();
276 lblHeading.setText(
277 "<html>" + tr("Authenticating at the OSM API ''{0}'' failed. Please enter a valid username and a valid password.",
278 apiUrl) + "</html>");
279 updateWarningLabel(apiUrl);
280 }
281
282 OsmApiCredentialsPanel(CredentialDialog owner) {
283 super(owner);
284 build();
285 }
286 }
287
288 private static class OtherHostCredentialsPanel extends CredentialPanel {
289
290 private final String host;
291
292 @Override
293 protected void build() {
294 super.build();
295 tfUserName.setToolTipText(tr("Please enter the user name of your account"));
296 tfPassword.setToolTipText(tr("Please enter the password of your account"));
297 lblHeading.setText(
298 "<html>" + tr("Authenticating at the host ''{0}'' failed. Please enter a valid username and a valid password.",
299 host) + "</html>");
300 updateWarningLabel(host);
301 }
302
303 OtherHostCredentialsPanel(CredentialDialog owner, String host) {
304 super(owner);
305 this.host = host;
306 build();
307 }
308 }
309
310 private static class HttpProxyCredentialsPanel extends CredentialPanel {
311 @Override
312 protected void build() {
313 super.build();
314 tfUserName.setToolTipText(tr("Please enter the user name for authenticating at your proxy server"));
315 tfPassword.setToolTipText(tr("Please enter the password for authenticating at your proxy server"));
316 lblHeading.setText(
317 "<html>" + tr("Authenticating at the HTTP proxy ''{0}'' failed. Please enter a valid username and a valid password.",
318 Main.pref.get(ProxyPreferencesPanel.PROXY_HTTP_HOST) + ':' +
319 Main.pref.get(ProxyPreferencesPanel.PROXY_HTTP_PORT)) + "</html>");
320 lblWarning.setText("<html>" +
321 tr("Warning: depending on the authentication method the proxy server uses the password may be transferred unencrypted.")
322 + "</html>");
323 }
324
325 HttpProxyCredentialsPanel(CredentialDialog owner) {
326 super(owner);
327 build();
328 }
329 }
330
331 private static class SelectAllOnFocusHandler extends FocusAdapter {
332 @Override
333 public void focusGained(FocusEvent e) {
334 if (e.getSource() instanceof JTextField) {
335 JTextField tf = (JTextField) e.getSource();
336 tf.selectAll();
337 }
338 }
339 }
340
341 /**
342 * Listener for username and password text fields key events.
343 * When user presses Enter:
344 * If current text field is empty (or just contains a sequence of spaces), nothing happens (or all spaces become selected).
345 * If current text field is not empty, but the next one is (or just contains a sequence of spaces), focuses the next text field.
346 * If both text fields contain characters, submits the form by calling owner's {@link OKAction}.
347 */
348 private static class TFKeyListener extends KeyAdapter {
349 protected CredentialDialog owner; // owner Dependency Injection to call OKAction
350 protected JTextField currentTF;
351 protected JTextField nextTF;
352
353 TFKeyListener(CredentialDialog owner, JTextField currentTF, JTextField nextTF) {
354 this.owner = owner;
355 this.currentTF = currentTF;
356 this.nextTF = nextTF;
357 }
358
359 @Override
360 public void keyPressed(KeyEvent e) {
361 if (e.getKeyChar() == KeyEvent.VK_ENTER) {
362 if (currentTF.getText().trim().isEmpty()) {
363 currentTF.selectAll();
364 return;
365 } else if (nextTF.getText().trim().isEmpty()) {
366 nextTF.requestFocusInWindow();
367 nextTF.selectAll();
368 return;
369 } else {
370 OKAction okAction = owner.new OKAction();
371 okAction.actionPerformed(null);
372 }
373 }
374 }
375 }
376
377 class OKAction extends AbstractAction {
378 OKAction() {
379 putValue(NAME, tr("Authenticate"));
380 putValue(SHORT_DESCRIPTION, tr("Authenticate with the supplied username and password"));
381 putValue(SMALL_ICON, ImageProvider.get("ok"));
382 }
383
384 @Override
385 public void actionPerformed(ActionEvent arg0) {
386 setCanceled(false);
387 setVisible(false);
388 }
389 }
390
391 class CancelAction extends AbstractAction {
392 CancelAction() {
393 putValue(NAME, tr("Cancel"));
394 putValue(SHORT_DESCRIPTION, tr("Cancel authentication"));
395 putValue(SMALL_ICON, ImageProvider.get("cancel"));
396 }
397
398 public void cancel() {
399 setCanceled(true);
400 setVisible(false);
401 }
402
403 @Override
404 public void actionPerformed(ActionEvent arg0) {
405 cancel();
406 }
407 }
408
409 class WindowEventHander extends WindowAdapter {
410
411 @Override
412 public void windowActivated(WindowEvent e) {
413 if (pnlCredentials != null) {
414 pnlCredentials.startUserInput();
415 }
416 }
417
418 @Override
419 public void windowClosing(WindowEvent e) {
420 new CancelAction().cancel();
421 }
422 }
423}
Note: See TracBrowser for help on using the repository browser.