source: josm/trunk/src/org/openstreetmap/josm/gui/oauth/OAuthAuthorizationWizard.java@ 6113

Last change on this file since 6113 was 6084, checked in by bastiK, 11 years ago

see #8902 - add missing @Override annotations (patch by shinigami)

  • Property svn:eol-style set to native
File size: 13.6 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.oauth;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.BorderLayout;
7import java.awt.Component;
8import java.awt.Dimension;
9import java.awt.FlowLayout;
10import java.awt.Font;
11import java.awt.GridBagConstraints;
12import java.awt.GridBagLayout;
13import java.awt.Insets;
14import java.awt.event.ActionEvent;
15import java.awt.event.ComponentEvent;
16import java.awt.event.ComponentListener;
17import java.awt.event.ItemEvent;
18import java.awt.event.ItemListener;
19import java.awt.event.KeyEvent;
20import java.awt.event.WindowAdapter;
21import java.awt.event.WindowEvent;
22import java.beans.PropertyChangeEvent;
23import java.beans.PropertyChangeListener;
24
25import javax.swing.AbstractAction;
26import javax.swing.BorderFactory;
27import javax.swing.JComponent;
28import javax.swing.JDialog;
29import javax.swing.JLabel;
30import javax.swing.JOptionPane;
31import javax.swing.JPanel;
32import javax.swing.JScrollPane;
33import javax.swing.KeyStroke;
34import javax.swing.UIManager;
35import javax.swing.event.HyperlinkEvent;
36import javax.swing.event.HyperlinkListener;
37
38import org.openstreetmap.josm.Main;
39import org.openstreetmap.josm.data.CustomConfigurator;
40import org.openstreetmap.josm.data.Preferences;
41import org.openstreetmap.josm.data.oauth.OAuthParameters;
42import org.openstreetmap.josm.data.oauth.OAuthToken;
43import org.openstreetmap.josm.gui.SideButton;
44import org.openstreetmap.josm.gui.help.ContextSensitiveHelpAction;
45import org.openstreetmap.josm.gui.help.HelpUtil;
46import org.openstreetmap.josm.gui.widgets.HtmlPanel;
47import org.openstreetmap.josm.tools.CheckParameterUtil;
48import org.openstreetmap.josm.tools.ImageProvider;
49import org.openstreetmap.josm.tools.OpenBrowser;
50import org.openstreetmap.josm.tools.WindowGeometry;
51
52/**
53 * This wizard walks the user to the necessary steps to retrieve an OAuth Access Token which
54 * allows JOSM to access the OSM API on the users behalf.
55 *
56 */
57public class OAuthAuthorizationWizard extends JDialog {
58 private HtmlPanel pnlMessage;
59 private boolean canceled;
60 private final String apiUrl;
61
62 private AuthorizationProcedureComboBox cbAuthorisationProcedure;
63 private FullyAutomaticAuthorizationUI pnlFullyAutomaticAuthorisationUI;
64 private SemiAutomaticAuthorizationUI pnlSemiAutomaticAuthorisationUI;
65 private ManualAuthorizationUI pnlManualAuthorisationUI;
66 private JScrollPane spAuthorisationProcedureUI;
67
68 /**
69 * Builds the row with the action buttons
70 *
71 * @return panel with buttons
72 */
73 protected JPanel buildButtonRow(){
74 JPanel pnl = new JPanel(new FlowLayout(FlowLayout.CENTER));
75
76 AcceptAccessTokenAction actAcceptAccessToken = new AcceptAccessTokenAction();
77 pnlFullyAutomaticAuthorisationUI.addPropertyChangeListener(actAcceptAccessToken);
78 pnlSemiAutomaticAuthorisationUI.addPropertyChangeListener(actAcceptAccessToken);
79 pnlManualAuthorisationUI.addPropertyChangeListener(actAcceptAccessToken);
80
81 pnl.add(new SideButton(actAcceptAccessToken));
82 pnl.add(new SideButton(new CancelAction()));
83 pnl.add(new SideButton(new ContextSensitiveHelpAction(HelpUtil.ht("/Dialog/OAuthAuthorisationWizard"))));
84
85 return pnl;
86 }
87
88 /**
89 * Builds the panel with general information in the header
90 *
91 * @return panel woth information display
92 */
93 protected JPanel buildHeaderInfoPanel() {
94 JPanel pnl = new JPanel(new GridBagLayout());
95 pnl.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
96 GridBagConstraints gc = new GridBagConstraints();
97
98 // the oauth logo in the header
99 gc.anchor = GridBagConstraints.NORTHWEST;
100 gc.fill = GridBagConstraints.HORIZONTAL;
101 gc.weightx = 1.0;
102 gc.gridwidth = 2;
103 JLabel lbl = new JLabel();
104 lbl.setIcon(ImageProvider.get("oauth", "oauth-logo"));
105 lbl.setOpaque(true);
106 pnl.add(lbl, gc);
107
108 // OAuth in a nutshell ...
109 gc.gridy = 1;
110 gc.insets = new Insets(5,0,0,5);
111 pnlMessage = new HtmlPanel();
112 pnlMessage.setText("<html><body>"
113 + tr("With OAuth you grant JOSM the right to upload map data and GPS tracks "
114 + "on your behalf (<a href=\"{0}\">more info...</a>).", "http://oauth.net/")
115 + "</body></html>"
116 );
117 pnlMessage.getEditorPane().addHyperlinkListener(new ExternalBrowserLauncher());
118 pnl.add(pnlMessage, gc);
119
120 // the authorisation procedure
121 gc.gridy = 2;
122 gc.gridwidth = 1;
123 gc.weightx = 0.0;
124 lbl = new JLabel(tr("Please select an authorization procedure: "));
125 lbl.setFont(lbl.getFont().deriveFont(Font.PLAIN));
126 pnl.add(lbl,gc);
127
128 gc.gridx = 1;
129 gc.gridwidth = 1;
130 gc.weightx = 1.0;
131 pnl.add(cbAuthorisationProcedure = new AuthorizationProcedureComboBox(),gc);
132 cbAuthorisationProcedure.addItemListener(new AuthorisationProcedureChangeListener());
133 return pnl;
134 }
135
136 /**
137 * Refreshes the view of the authorisation panel, depending on the authorisation procedure
138 * currently selected
139 */
140 protected void refreshAuthorisationProcedurePanel() {
141 AuthorizationProcedure procedure = (AuthorizationProcedure)cbAuthorisationProcedure.getSelectedItem();
142 switch(procedure) {
143 case FULLY_AUTOMATIC:
144 spAuthorisationProcedureUI.getViewport().setView(pnlFullyAutomaticAuthorisationUI);
145 pnlFullyAutomaticAuthorisationUI.revalidate();
146 break;
147 case SEMI_AUTOMATIC:
148 spAuthorisationProcedureUI.getViewport().setView(pnlSemiAutomaticAuthorisationUI);
149 pnlSemiAutomaticAuthorisationUI.revalidate();
150 break;
151 case MANUALLY:
152 spAuthorisationProcedureUI.getViewport().setView(pnlManualAuthorisationUI);
153 pnlManualAuthorisationUI.revalidate();
154 break;
155 }
156 validate();
157 repaint();
158 }
159
160 /**
161 * builds the UI
162 */
163 protected void build() {
164 getContentPane().setLayout(new BorderLayout());
165 getContentPane().add(buildHeaderInfoPanel(), BorderLayout.NORTH);
166
167 setTitle(tr("Get an Access Token for ''{0}''", apiUrl));
168
169 pnlFullyAutomaticAuthorisationUI = new FullyAutomaticAuthorizationUI(apiUrl);
170 pnlSemiAutomaticAuthorisationUI = new SemiAutomaticAuthorizationUI(apiUrl);
171 pnlManualAuthorisationUI = new ManualAuthorizationUI(apiUrl);
172
173 spAuthorisationProcedureUI = new JScrollPane(new JPanel());
174 spAuthorisationProcedureUI.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
175 spAuthorisationProcedureUI.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
176 spAuthorisationProcedureUI.getVerticalScrollBar().addComponentListener(
177 new ComponentListener() {
178 @Override
179 public void componentShown(ComponentEvent e) {
180 spAuthorisationProcedureUI.setBorder(UIManager.getBorder("ScrollPane.border"));
181 }
182
183 @Override
184 public void componentHidden(ComponentEvent e) {
185 spAuthorisationProcedureUI.setBorder(null);
186 }
187
188 @Override
189 public void componentResized(ComponentEvent e) {}
190 @Override
191 public void componentMoved(ComponentEvent e) {}
192 }
193 );
194 getContentPane().add(spAuthorisationProcedureUI, BorderLayout.CENTER);
195 getContentPane().add(buildButtonRow(), BorderLayout.SOUTH);
196
197 addWindowListener(new WindowEventHandler());
198 getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "cancel");
199 getRootPane().getActionMap().put("cancel", new CancelAction());
200
201 refreshAuthorisationProcedurePanel();
202
203 HelpUtil.setHelpContext(getRootPane(), HelpUtil.ht("/Dialog/OAuthAuthorisationWizard"));
204 }
205
206 /**
207 * Creates the wizard.
208 *
209 * @param apiUrl the API URL. Must not be null.
210 * @throws IllegalArgumentException thrown if apiUrl is null
211 */
212 public OAuthAuthorizationWizard(String apiUrl) throws IllegalArgumentException {
213 this(Main.parent, apiUrl);
214 }
215
216 /**
217 * Creates the wizard.
218 *
219 * @param parent the component relative to which the dialog is displayed
220 * @param apiUrl the API URL. Must not be null.
221 * @throws IllegalArgumentException thrown if apiUrl is null
222 */
223 public OAuthAuthorizationWizard(Component parent, String apiUrl) {
224 super(JOptionPane.getFrameForComponent(parent), ModalityType.DOCUMENT_MODAL);
225 CheckParameterUtil.ensureParameterNotNull(apiUrl, "apiUrl");
226 this.apiUrl = apiUrl;
227 build();
228 }
229
230 /**
231 * Replies true if the dialog was canceled
232 *
233 * @return true if the dialog was canceled
234 */
235 public boolean isCanceled() {
236 return canceled;
237 }
238
239 protected AbstractAuthorizationUI getCurrentAuthorisationUI() {
240 switch((AuthorizationProcedure)cbAuthorisationProcedure.getSelectedItem()) {
241 case FULLY_AUTOMATIC: return pnlFullyAutomaticAuthorisationUI;
242 case MANUALLY: return pnlManualAuthorisationUI;
243 case SEMI_AUTOMATIC: return pnlSemiAutomaticAuthorisationUI;
244 default: return null;
245 }
246 }
247
248 /**
249 * Replies the Access Token entered using the wizard
250 *
251 * @return the access token. May be null if the wizard was canceled.
252 */
253 public OAuthToken getAccessToken() {
254 return getCurrentAuthorisationUI().getAccessToken();
255 }
256
257 /**
258 * Replies the current OAuth parameters.
259 *
260 * @return the current OAuth parameters.
261 */
262 public OAuthParameters getOAuthParameters() {
263 return getCurrentAuthorisationUI().getOAuthParameters();
264 }
265
266 /**
267 * Replies true if the currently selected Access Token shall be saved to
268 * the preferences.
269 *
270 * @return true if the currently selected Access Token shall be saved to
271 * the preferences
272 */
273 public boolean isSaveAccessTokenToPreferences() {
274 return getCurrentAuthorisationUI().isSaveAccessTokenToPreferences();
275 }
276
277 /**
278 * Initializes the dialog with values from the preferences
279 *
280 */
281 public void initFromPreferences() {
282 // Copy current JOSM preferences to update API url with the one used in this wizard
283 Preferences copyPref = CustomConfigurator.clonePreferences(Main.pref);
284 copyPref.put("osm-server-url", apiUrl);
285 pnlFullyAutomaticAuthorisationUI.initFromPreferences(copyPref);
286 pnlSemiAutomaticAuthorisationUI.initFromPreferences(copyPref);
287 pnlManualAuthorisationUI.initFromPreferences(copyPref);
288 }
289
290 @Override
291 public void setVisible(boolean visible) {
292 if (visible) {
293 new WindowGeometry(
294 getClass().getName() + ".geometry",
295 WindowGeometry.centerInWindow(
296 Main.parent,
297 new Dimension(450,540)
298 )
299 ).applySafe(this);
300 initFromPreferences();
301 } else if (isShowing()) { // Avoid IllegalComponentStateException like in #8775
302 new WindowGeometry(this).remember(getClass().getName() + ".geometry");
303 }
304 super.setVisible(visible);
305 }
306
307 protected void setCanceled(boolean canceled) {
308 this.canceled = canceled;
309 }
310
311 class AuthorisationProcedureChangeListener implements ItemListener {
312 @Override
313 public void itemStateChanged(ItemEvent arg0) {
314 refreshAuthorisationProcedurePanel();
315 }
316 }
317
318 class CancelAction extends AbstractAction {
319 public CancelAction() {
320 putValue(NAME, tr("Cancel"));
321 putValue(SMALL_ICON, ImageProvider.get("cancel"));
322 putValue(SHORT_DESCRIPTION, tr("Close the dialog and cancel authorization"));
323 }
324
325 public void cancel() {
326 setCanceled(true);
327 setVisible(false);
328 }
329
330 @Override
331 public void actionPerformed(ActionEvent evt) {
332 cancel();
333 }
334 }
335
336 class AcceptAccessTokenAction extends AbstractAction implements PropertyChangeListener {
337 private OAuthToken token;
338
339 public AcceptAccessTokenAction() {
340 putValue(NAME, tr("Accept Access Token"));
341 putValue(SMALL_ICON, ImageProvider.get("ok"));
342 putValue(SHORT_DESCRIPTION, tr("Close the dialog and accept the Access Token"));
343 updateEnabledState(null);
344 }
345
346 @Override
347 public void actionPerformed(ActionEvent evt) {
348 setCanceled(false);
349 setVisible(false);
350 }
351
352 public void updateEnabledState(OAuthToken token) {
353 setEnabled(token != null);
354 }
355
356 @Override
357 public void propertyChange(PropertyChangeEvent evt) {
358 if (!evt.getPropertyName().equals(AbstractAuthorizationUI.ACCESS_TOKEN_PROP))
359 return;
360 token = (OAuthToken)evt.getNewValue();
361 updateEnabledState(token);
362 }
363 }
364
365 class WindowEventHandler extends WindowAdapter {
366 @Override
367 public void windowClosing(WindowEvent arg0) {
368 new CancelAction().cancel();
369 }
370 }
371
372 static class ExternalBrowserLauncher implements HyperlinkListener {
373 @Override
374 public void hyperlinkUpdate(HyperlinkEvent e) {
375 if (e.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) {
376 OpenBrowser.displayUrl(e.getDescription());
377 }
378 }
379 }
380}
Note: See TracBrowser for help on using the repository browser.