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

Revision 4310, 14.1 KB checked in by stoecker, 10 months ago (diff)

fix #6680, fix #6677 - i18n issues

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