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.BorderLayout;
007import java.awt.GridBagConstraints;
008import java.awt.GridBagLayout;
009import java.awt.Insets;
010import java.awt.event.ItemEvent;
011import java.awt.event.ItemListener;
012import java.util.EnumMap;
013import java.util.Map;
014
015import javax.swing.BorderFactory;
016import javax.swing.ButtonGroup;
017import javax.swing.JCheckBox;
018import javax.swing.JPanel;
019import javax.swing.JRadioButton;
020
021import org.openstreetmap.josm.Main;
022import org.openstreetmap.josm.data.Bounds;
023import org.openstreetmap.josm.gui.JosmUserIdentityManager;
024import org.openstreetmap.josm.gui.widgets.HtmlPanel;
025import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
026import org.openstreetmap.josm.io.ChangesetQuery;
027
028/**
029 * This panel presents a list of basic queries for changests.
030 *
031 */
032public class BasicChangesetQueryPanel extends JPanel {
033
034    /**
035     * Enumeration of basic, predefined queries
036     */
037    private enum BasicQuery {
038        MOST_RECENT_CHANGESETS,
039        MY_OPEN_CHANGESETS,
040        CHANGESETS_IN_MAP_VIEW;
041    }
042
043    private transient Map<BasicQuery, JRadioButton> rbQueries;
044    private transient Map<BasicQuery, JMultilineLabel> lblQueries;
045    private JCheckBox cbMyChangesetsOnly;
046
047    protected JPanel buildQueriesPanel() {
048        JPanel pnl = new JPanel(new GridBagLayout());
049
050        ButtonGroup bgQueries = new ButtonGroup();
051        rbQueries = new EnumMap<>(BasicQuery.class);
052        lblQueries = new EnumMap<>(BasicQuery.class);
053        SelectQueryHandler selectedQueryHandler = new SelectQueryHandler();
054        for (BasicQuery q: BasicQuery.values()) {
055            JRadioButton rb = new JRadioButton();
056            rb.addItemListener(selectedQueryHandler);
057            rbQueries.put(q, rb);
058            bgQueries.add(rb);
059            lblQueries.put(q, new JMultilineLabel(""));
060        }
061
062        GridBagConstraints gc = new GridBagConstraints();
063        // -- most recent changes
064        gc.fill = GridBagConstraints.NONE;
065        gc.anchor = GridBagConstraints.NORTHWEST;
066        gc.insets = new Insets(0, 0, 5, 3);
067        pnl.add(rbQueries.get(BasicQuery.MOST_RECENT_CHANGESETS), gc);
068
069        gc.gridx = 1;
070        gc.fill = GridBagConstraints.HORIZONTAL;
071        gc.weightx = 1.0;
072        pnl.add(lblQueries.get(BasicQuery.MOST_RECENT_CHANGESETS), gc);
073
074        // -- most recent changes
075        gc.gridx = 0;
076        gc.gridy = 1;
077        gc.fill = GridBagConstraints.NONE;
078        gc.weightx = 0.0;
079        pnl.add(rbQueries.get(BasicQuery.MY_OPEN_CHANGESETS), gc);
080
081        gc.gridx = 1;
082        gc.fill = GridBagConstraints.HORIZONTAL;
083        gc.weightx = 1.0;
084        pnl.add(lblQueries.get(BasicQuery.MY_OPEN_CHANGESETS), gc);
085
086        // -- changesets in map view
087        gc.gridx = 0;
088        gc.gridy = 2;
089        gc.fill = GridBagConstraints.NONE;
090        gc.weightx = 0.0;
091        pnl.add(rbQueries.get(BasicQuery.CHANGESETS_IN_MAP_VIEW), gc);
092
093        gc.gridx = 1;
094        gc.fill = GridBagConstraints.HORIZONTAL;
095        gc.weightx = 1.0;
096        pnl.add(lblQueries.get(BasicQuery.CHANGESETS_IN_MAP_VIEW), gc);
097
098        // -- checkbox my changesets only
099        gc.gridx = 0;
100        gc.gridy = 3;
101        gc.gridwidth = 2;
102        gc.insets = new Insets(5, 0, 3, 3);
103        gc.fill = GridBagConstraints.HORIZONTAL;
104        gc.weightx = 1.0;
105        cbMyChangesetsOnly = new JCheckBox(tr("Download my changesets only"));
106        pnl.add(cbMyChangesetsOnly, gc);
107        cbMyChangesetsOnly.setToolTipText(
108                tr("<html>Select to restrict the query to your changesets only.<br>Unselect to include all changesets in the query.</html>"));
109
110        // grab remaining space
111        gc.gridx = 0;
112        gc.gridy = 4;
113        gc.gridwidth = 2;
114        gc.insets = new Insets(5, 0, 3, 3);
115        gc.fill = GridBagConstraints.BOTH;
116        gc.weightx = 1.0;
117        gc.weighty = 1.0;
118        pnl.add(new JPanel(), gc);
119
120        return pnl;
121    }
122
123    protected JPanel buildInfoPanel() {
124        HtmlPanel pnlInfos = new HtmlPanel();
125        pnlInfos.setText(tr("<html>Please select one the following <strong>standard queries</strong>."
126                + "Select <strong>Download my changesets only</strong>"
127                + " if you only want to download changesets created by yourself.<br>"
128                + "Note that JOSM will download max. 100 changesets.</html>")
129        );
130        return pnlInfos;
131    }
132
133    protected final void build() {
134        setLayout(new BorderLayout(0, 5));
135        setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
136        add(buildInfoPanel(), BorderLayout.NORTH);
137        add(buildQueriesPanel(), BorderLayout.CENTER);
138    }
139
140    /**
141     * Constructs a new {@code BasicChangesetQueryPanel}.
142     */
143    public BasicChangesetQueryPanel() {
144        build();
145    }
146
147    public void init() {
148        JMultilineLabel lbl = lblQueries.get(BasicQuery.MOST_RECENT_CHANGESETS);
149        lbl.setText(tr("<html>Download the latest changesets</html>"));
150
151        // query for open changesets only possible if we have a current user which is at least
152        // partially identified
153        lbl = lblQueries.get(BasicQuery.MY_OPEN_CHANGESETS);
154        if (JosmUserIdentityManager.getInstance().isAnonymous()) {
155            rbQueries.get(BasicQuery.MY_OPEN_CHANGESETS).setEnabled(false);
156            lbl.setText(tr("<html>Download my open changesets<br><em>Disabled. " +
157                    "Please enter your OSM user name in the preferences first.</em></html>"));
158        } else {
159            rbQueries.get(BasicQuery.MY_OPEN_CHANGESETS).setEnabled(true);
160            lbl.setText(tr("<html>Download my open changesets</html>"));
161        }
162
163        // query for changesets in the current map view only if there *is* a current
164        // map view
165        lbl = lblQueries.get(BasicQuery.CHANGESETS_IN_MAP_VIEW);
166        if (!Main.isDisplayingMapView()) {
167            rbQueries.get(BasicQuery.CHANGESETS_IN_MAP_VIEW).setEnabled(false);
168            lbl.setText(tr("<html>Download changesets in the current map view.<br><em>Disabled. " +
169                    "There is currently no map view active.</em></html>"));
170        } else {
171            rbQueries.get(BasicQuery.CHANGESETS_IN_MAP_VIEW).setEnabled(true);
172            lbl.setText(tr("<html>Download changesets in the current map view</html>"));
173        }
174
175        restoreFromPreferences();
176    }
177
178    public void rememberInPreferences() {
179        BasicQuery q = getSelectedQuery();
180        if (q == null) {
181            Main.pref.put("changeset-query.basic.query", null);
182        } else {
183            Main.pref.put("changeset-query.basic.query", q.toString());
184        }
185        Main.pref.put("changeset-query.basic.my-changesets-only", cbMyChangesetsOnly.isSelected());
186    }
187
188    public void restoreFromPreferences() {
189        BasicQuery q;
190        String value = Main.pref.get("changeset-query.basic.query", null);
191        if (value == null) {
192            q = BasicQuery.MOST_RECENT_CHANGESETS;
193        } else {
194            try {
195                q = BasicQuery.valueOf(BasicQuery.class, value);
196            } catch (IllegalArgumentException e) {
197                Main.warn(tr("Unexpected value for preference ''{0}'', got ''{1}''. Resetting to default query.",
198                        "changeset-query.basic.query", value));
199                q = BasicQuery.MOST_RECENT_CHANGESETS;
200            }
201        }
202        rbQueries.get(q).setSelected(true);
203        boolean mineOnly = Main.pref.getBoolean("changeset-query.basic.my-changesets-only", false);
204        mineOnly = mineOnly || q.equals(BasicQuery.MY_OPEN_CHANGESETS);
205        cbMyChangesetsOnly.setSelected(mineOnly);
206    }
207
208    protected BasicQuery getSelectedQuery() {
209        for (BasicQuery q : BasicQuery.values()) {
210            if (rbQueries.get(q).isSelected())
211                return q;
212        }
213        return null;
214    }
215
216    public ChangesetQuery buildChangesetQuery() {
217        BasicQuery q = getSelectedQuery();
218        ChangesetQuery query = new ChangesetQuery();
219        JosmUserIdentityManager im = JosmUserIdentityManager.getInstance();
220        if (q == null)
221            return query;
222        switch(q) {
223        case MOST_RECENT_CHANGESETS:
224            break;
225        case MY_OPEN_CHANGESETS:
226            query = query.beingOpen(true);
227            break;
228        case CHANGESETS_IN_MAP_VIEW:
229            Bounds b = Main.map.mapView.getLatLonBounds(Main.map.mapView.getBounds());
230            query = query.inBbox(b);
231            break;
232        }
233
234        if (cbMyChangesetsOnly.isSelected()) {
235            if (im.isPartiallyIdentified()) {
236                query = query.forUser(im.getUserName());
237            } else if (im.isFullyIdentified()) {
238                query = query.forUser(im.getUserId()).beingOpen(true);
239            } else
240                // anonymous -- can happen with a fresh config.
241                throw new IllegalStateException(tr("Cannot create changeset query for open changesets of anonymous user"));
242        }
243
244        return query;
245    }
246
247    /**
248     * Responds to changes in the selected query
249     *
250     */
251    class SelectQueryHandler implements ItemListener {
252        @Override
253        public void itemStateChanged(ItemEvent e) {
254            BasicQuery q = getSelectedQuery();
255            if (q == null) return;
256            if (q.equals(BasicQuery.MY_OPEN_CHANGESETS)) {
257                cbMyChangesetsOnly.setSelected(true);
258                cbMyChangesetsOnly.setEnabled(false);
259            } else {
260                if (!cbMyChangesetsOnly.isEnabled()) {
261                    cbMyChangesetsOnly.setEnabled(true);
262                }
263            }
264        }
265    }
266}