001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.dialogs.changeset.query;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.awt.Color;
007import java.awt.GridBagConstraints;
008import java.awt.GridBagLayout;
009import java.awt.event.ItemEvent;
010import java.awt.event.ItemListener;
011
012import javax.swing.BorderFactory;
013import javax.swing.ButtonGroup;
014import javax.swing.JLabel;
015import javax.swing.JOptionPane;
016import javax.swing.JPanel;
017import javax.swing.JRadioButton;
018
019import org.openstreetmap.josm.data.UserIdentityManager;
020import org.openstreetmap.josm.gui.HelpAwareOptionPane;
021import org.openstreetmap.josm.gui.help.HelpUtil;
022import org.openstreetmap.josm.gui.preferences.server.UserNameValidator;
023import org.openstreetmap.josm.gui.widgets.JosmTextField;
024import org.openstreetmap.josm.gui.widgets.SelectAllOnFocusGainedDecorator;
025import org.openstreetmap.josm.io.ChangesetQuery;
026import org.openstreetmap.josm.spi.preferences.Config;
027import org.openstreetmap.josm.tools.CheckParameterUtil;
028import org.openstreetmap.josm.tools.GBC;
029
030/**
031 * This is the panel for selecting whether the query should be restricted to a specific user.
032 * @since 11326 (extracted from AdvancedChangesetQueryPanel)
033 */
034public class UserRestrictionPanel extends JPanel implements RestrictionPanel {
035    private static final String PREF_ROOT = "changeset-query.advanced.user-restrictions";
036    private static final String PREF_QUERY_TYPE = PREF_ROOT + ".query-type";
037
038    private final ButtonGroup bgUserRestrictions = new ButtonGroup();
039    private final JRadioButton rbRestrictToMyself = new JRadioButton(); // text is set in #startUserInput
040    private final JRadioButton rbRestrictToUid = new JRadioButton(tr("Only changesets owned by the user with the following user ID"));
041    private final JRadioButton rbRestrictToUserName = new JRadioButton(tr("Only changesets owned by the user with the following user name"));
042    private final JosmTextField tfUid = new JosmTextField(10);
043    private transient UidInputFieldValidator valUid;
044    private final JosmTextField tfUserName = new JosmTextField(10);
045    private transient UserNameValidator valUserName;
046
047    /**
048     * Constructs a new {@code UserRestrictionPanel}.
049     */
050    public UserRestrictionPanel() {
051        build();
052    }
053
054    protected JPanel buildUidInputPanel() {
055        JPanel pnl = new JPanel(new GridBagLayout());
056        pnl.add(new JLabel(tr("User ID:")), GBC.std());
057
058        pnl.add(tfUid, GBC.eol().fill(GridBagConstraints.HORIZONTAL));
059        SelectAllOnFocusGainedDecorator.decorate(tfUid);
060        valUid = UidInputFieldValidator.decorate(tfUid);
061
062        return pnl;
063    }
064
065    protected JPanel buildUserNameInputPanel() {
066        JPanel pnl = new JPanel(new GridBagLayout());
067        pnl.add(new JLabel(tr("User name:")), GBC.std());
068
069        pnl.add(tfUserName, GBC.eol().fill(GridBagConstraints.HORIZONTAL));
070        SelectAllOnFocusGainedDecorator.decorate(tfUserName);
071        valUserName = new UserNameValidator(tfUserName);
072
073        return pnl;
074    }
075
076    protected void build() {
077        setLayout(new GridBagLayout());
078        setBorder(BorderFactory.createCompoundBorder(
079                BorderFactory.createEmptyBorder(3, 3, 3, 3),
080                BorderFactory.createCompoundBorder(
081                        BorderFactory.createLineBorder(Color.GRAY),
082                        BorderFactory.createEmptyBorder(5, 5, 5, 5)
083                )
084        ));
085
086        ItemListener userRestrictionChangeHandler = new UserRestrictionChangedHandler();
087        GridBagConstraints gc = GBC.eol().fill(GridBagConstraints.HORIZONTAL);
088
089        add(rbRestrictToMyself, gc);
090        rbRestrictToMyself.addItemListener(userRestrictionChangeHandler);
091
092        add(rbRestrictToUid, gc);
093        rbRestrictToUid.addItemListener(userRestrictionChangeHandler);
094        add(buildUidInputPanel(), gc);
095
096        add(rbRestrictToUserName, gc);
097        rbRestrictToUserName.addItemListener(userRestrictionChangeHandler);
098
099        add(buildUserNameInputPanel(), gc);
100
101        bgUserRestrictions.add(rbRestrictToMyself);
102        bgUserRestrictions.add(rbRestrictToUid);
103        bgUserRestrictions.add(rbRestrictToUserName);
104    }
105
106    /**
107     * Initializes HMI for user input.
108     */
109    public void startUserInput() {
110        if (UserIdentityManager.getInstance().isAnonymous()) {
111            rbRestrictToMyself.setText(tr("Only changesets owned by myself (disabled. JOSM is currently run by an anonymous user)"));
112            rbRestrictToMyself.setEnabled(false);
113            if (rbRestrictToMyself.isSelected()) {
114                rbRestrictToUid.setSelected(true);
115            }
116        } else {
117            rbRestrictToMyself.setText(tr("Only changesets owned by myself"));
118            rbRestrictToMyself.setEnabled(true);
119            rbRestrictToMyself.setSelected(true);
120        }
121        restoreFromSettings();
122    }
123
124    /**
125     * Sets the query restrictions on <code>query</code> for changeset owner based restrictions.
126     *
127     * @param query the query. Must not be null.
128     * @throws IllegalArgumentException if query is null
129     * @throws IllegalStateException if one of the available values for query parameters in this panel isn't valid
130     */
131    @Override
132    public void fillInQuery(ChangesetQuery query) {
133        CheckParameterUtil.ensureParameterNotNull(query, "query");
134        if (rbRestrictToMyself.isSelected()) {
135            UserIdentityManager im = UserIdentityManager.getInstance();
136            if (im.isPartiallyIdentified()) {
137                query.forUser(im.getUserName());
138            } else if (im.isFullyIdentified()) {
139                query.forUser(im.getUserId());
140            } else
141                throw new IllegalStateException(
142                        tr("Cannot restrict changeset query to the current user because the current user is anonymous"));
143        } else if (rbRestrictToUid.isSelected()) {
144            int uid = valUid.getUid();
145            if (uid > 0) {
146                query.forUser(uid);
147            } else
148                throw new IllegalStateException(tr("Current value ''{0}'' for user ID is not valid", tfUid.getText()));
149        } else if (rbRestrictToUserName.isSelected()) {
150            if (!valUserName.isValid())
151                throw new IllegalStateException(
152                        tr("Cannot restrict the changeset query to the user name ''{0}''", tfUserName.getText()));
153            query.forUser(tfUserName.getText());
154        }
155    }
156
157    /**
158     * Determines if the changeset query time information is valid.
159     * @return {@code true} if the changeset query time information is valid.
160     */
161    @Override
162    public boolean isValidChangesetQuery() {
163        if (rbRestrictToUid.isSelected())
164            return valUid.isValid();
165        else if (rbRestrictToUserName.isSelected())
166            return valUserName.isValid();
167        return true;
168    }
169
170    protected void alertInvalidUid() {
171        HelpAwareOptionPane.showOptionDialog(
172                this,
173                tr("Please enter a valid user ID"),
174                tr("Invalid user ID"),
175                JOptionPane.ERROR_MESSAGE,
176                HelpUtil.ht("/Dialog/ChangesetQueryDialog#InvalidUserId")
177        );
178    }
179
180    protected void alertInvalidUserName() {
181        HelpAwareOptionPane.showOptionDialog(
182                this,
183                tr("Please enter a non-empty user name"),
184                tr("Invalid user name"),
185                JOptionPane.ERROR_MESSAGE,
186                HelpUtil.ht("/Dialog/ChangesetQueryDialog#InvalidUserName")
187        );
188    }
189
190    @Override
191    public void displayMessageIfInvalid() {
192        if (rbRestrictToUid.isSelected()) {
193            if (!valUid.isValid()) {
194                alertInvalidUid();
195            }
196        } else if (rbRestrictToUserName.isSelected()) {
197            if (!valUserName.isValid()) {
198                alertInvalidUserName();
199            }
200        }
201    }
202
203    /**
204     * Remember settings in preferences.
205     */
206    public void rememberSettings() {
207        if (rbRestrictToMyself.isSelected()) {
208            Config.getPref().put(PREF_QUERY_TYPE, "mine");
209        } else if (rbRestrictToUid.isSelected()) {
210            Config.getPref().put(PREF_QUERY_TYPE, "uid");
211        } else if (rbRestrictToUserName.isSelected()) {
212            Config.getPref().put(PREF_QUERY_TYPE, "username");
213        }
214        Config.getPref().put(PREF_ROOT + ".uid", tfUid.getText());
215        Config.getPref().put(PREF_ROOT + ".username", tfUserName.getText());
216    }
217
218    /**
219     * Restore settings from preferences.
220     */
221    public void restoreFromSettings() {
222        String v = Config.getPref().get(PREF_QUERY_TYPE, "mine");
223        if ("mine".equals(v)) {
224            UserIdentityManager im = UserIdentityManager.getInstance();
225            if (im.isAnonymous()) {
226                rbRestrictToUid.setSelected(true);
227            } else {
228                rbRestrictToMyself.setSelected(true);
229            }
230        } else if ("uid".equals(v)) {
231            rbRestrictToUid.setSelected(true);
232        } else if ("username".equals(v)) {
233            rbRestrictToUserName.setSelected(true);
234        }
235        tfUid.setText(Config.getPref().get(PREF_ROOT + ".uid", ""));
236        if (!valUid.isValid()) {
237            tfUid.setText("");
238        }
239        tfUserName.setText(Config.getPref().get(PREF_ROOT + ".username", ""));
240    }
241
242    class UserRestrictionChangedHandler implements ItemListener {
243        @Override
244        public void itemStateChanged(ItemEvent e) {
245            tfUid.setEnabled(rbRestrictToUid.isSelected());
246            tfUserName.setEnabled(rbRestrictToUserName.isSelected());
247            if (rbRestrictToUid.isSelected()) {
248                tfUid.requestFocusInWindow();
249            } else if (rbRestrictToUserName.isSelected()) {
250                tfUserName.requestFocusInWindow();
251            }
252        }
253    }
254}