source: josm/trunk/src/org/openstreetmap/josm/gui/io/ChangesetManagementPanel.java @ 12841

Last change on this file since 12841 was 12841, checked in by bastiK, 3 months ago

see #15229 - fix deprecations caused by [12840]

  • Property svn:eol-style set to native
File size: 12.1 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.Dimension;
7import java.awt.GridBagConstraints;
8import java.awt.GridBagLayout;
9import java.awt.Insets;
10import java.awt.event.ActionEvent;
11import java.awt.event.ItemEvent;
12import java.awt.event.ItemListener;
13import java.util.Collections;
14
15import javax.swing.AbstractAction;
16import javax.swing.BorderFactory;
17import javax.swing.ButtonGroup;
18import javax.swing.JButton;
19import javax.swing.JCheckBox;
20import javax.swing.JPanel;
21import javax.swing.JRadioButton;
22import javax.swing.event.ListDataEvent;
23import javax.swing.event.ListDataListener;
24
25import org.openstreetmap.josm.Main;
26import org.openstreetmap.josm.data.osm.Changeset;
27import org.openstreetmap.josm.data.osm.ChangesetCache;
28import org.openstreetmap.josm.gui.MainApplication;
29import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
30import org.openstreetmap.josm.gui.widgets.JosmComboBox;
31import org.openstreetmap.josm.tools.CheckParameterUtil;
32import org.openstreetmap.josm.tools.ImageProvider;
33
34/**
35 * ChangesetManagementPanel allows to configure changeset to be used in the next
36 * upload.
37 *
38 * It is displayed as one of the configuration panels in the {@link UploadDialog}.
39 *
40 * ChangesetManagementPanel is a source for {@link java.beans.PropertyChangeEvent}s. Clients can listen
41 * to
42 * <ul>
43 *   <li>{@link #SELECTED_CHANGESET_PROP}  - the new value in the property change event is
44 *   the changeset selected by the user. The value is null if the user didn't select a
45 *   a changeset or if he chosed to use a new changeset.</li>
46 *   <li> {@link #CLOSE_CHANGESET_AFTER_UPLOAD} - the new value is a boolean value indicating
47 *   whether the changeset should be closed after the next upload</li>
48 * </ul>
49 */
50public class ChangesetManagementPanel extends JPanel implements ListDataListener {
51    static final String SELECTED_CHANGESET_PROP = ChangesetManagementPanel.class.getName() + ".selectedChangeset";
52    static final String CLOSE_CHANGESET_AFTER_UPLOAD = ChangesetManagementPanel.class.getName() + ".closeChangesetAfterUpload";
53
54    private JRadioButton rbUseNew;
55    private JRadioButton rbExisting;
56    private JosmComboBox<Changeset> cbOpenChangesets;
57    private JCheckBox cbCloseAfterUpload;
58    private OpenChangesetComboBoxModel model;
59
60    /**
61     * Constructs a new {@code ChangesetManagementPanel}.
62     *
63     * @param changesetCommentModel the changeset comment model. Must not be null.
64     * @throws IllegalArgumentException if {@code changesetCommentModel} is null
65     */
66    public ChangesetManagementPanel(ChangesetCommentModel changesetCommentModel) {
67        CheckParameterUtil.ensureParameterNotNull(changesetCommentModel, "changesetCommentModel");
68        build();
69        refreshGUI();
70    }
71
72    /**
73     * builds the GUI
74     */
75    protected void build() {
76        setLayout(new GridBagLayout());
77        GridBagConstraints gc = new GridBagConstraints();
78        setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
79
80        ButtonGroup bgUseNewOrExisting = new ButtonGroup();
81
82        gc.gridwidth = 4;
83        gc.gridx = 0;
84        gc.gridy = 0;
85        gc.fill = GridBagConstraints.HORIZONTAL;
86        gc.weightx = 1.0;
87        gc.weighty = 0.0;
88        gc.insets = new Insets(0, 0, 5, 0);
89        add(new JMultilineLabel(
90                tr("Please decide what changeset the data is uploaded to and whether to close the changeset after the next upload.")), gc);
91
92        gc.gridwidth = 4;
93        gc.gridy = 1;
94        gc.fill = GridBagConstraints.HORIZONTAL;
95        gc.weightx = 1.0;
96        gc.weighty = 0.0;
97        gc.insets = new Insets(0, 0, 0, 0);
98        gc.anchor = GridBagConstraints.FIRST_LINE_START;
99        rbUseNew = new JRadioButton(tr("Upload to a new changeset"));
100        rbUseNew.setToolTipText(tr("Open a new changeset and use it in the next upload"));
101        bgUseNewOrExisting.add(rbUseNew);
102        add(rbUseNew, gc);
103
104        gc.gridx = 0;
105        gc.gridy = 2;
106        gc.gridwidth = 1;
107        gc.weightx = 0.0;
108        gc.fill = GridBagConstraints.HORIZONTAL;
109        rbExisting = new JRadioButton(tr("Upload to an existing changeset"));
110        rbExisting.setToolTipText(tr("Upload data to an already existing and open changeset"));
111        bgUseNewOrExisting.add(rbExisting);
112        add(rbExisting, gc);
113
114        gc.gridx = 1;
115        gc.gridy = 2;
116        gc.gridwidth = 1;
117        gc.weightx = 1.0;
118        model = new OpenChangesetComboBoxModel();
119        ChangesetCache.getInstance().addChangesetCacheListener(model);
120        cbOpenChangesets = new JosmComboBox<>(model);
121        cbOpenChangesets.setToolTipText(tr("Select an open changeset"));
122        cbOpenChangesets.setRenderer(new ChangesetCellRenderer());
123        cbOpenChangesets.addItemListener(new ChangesetListItemStateListener());
124        Dimension d = cbOpenChangesets.getPreferredSize();
125        d.width = 200;
126        cbOpenChangesets.setPreferredSize(d);
127        d.width = 100;
128        cbOpenChangesets.setMinimumSize(d);
129        model.addListDataListener(this);
130        add(cbOpenChangesets, gc);
131
132        gc.gridx = 2;
133        gc.gridy = 2;
134        gc.weightx = 0.0;
135        gc.gridwidth = 1;
136        gc.weightx = 0.0;
137        JButton btnRefresh = new JButton(new RefreshAction());
138        btnRefresh.setMargin(new Insets(0, 0, 0, 0));
139        add(btnRefresh, gc);
140
141        gc.gridx = 3;
142        gc.gridy = 2;
143        gc.gridwidth = 1;
144        CloseChangesetAction closeChangesetAction = new CloseChangesetAction();
145        JButton btnClose = new JButton(closeChangesetAction);
146        btnClose.setMargin(new Insets(0, 0, 0, 0));
147        cbOpenChangesets.addItemListener(closeChangesetAction);
148        rbExisting.addItemListener(closeChangesetAction);
149        add(btnClose, gc);
150
151        gc.gridx = 0;
152        gc.gridy = 3;
153        gc.gridwidth = 4;
154        gc.weightx = 1.0;
155        cbCloseAfterUpload = new JCheckBox(tr("Close changeset after upload"));
156        cbCloseAfterUpload.setToolTipText(tr("Select to close the changeset after the next upload"));
157        add(cbCloseAfterUpload, gc);
158        cbCloseAfterUpload.setSelected(Main.pref.getBoolean("upload.changeset.close", true));
159        cbCloseAfterUpload.addItemListener(new CloseAfterUploadItemStateListener());
160
161        gc.gridx = 0;
162        gc.gridy = 5;
163        gc.gridwidth = 4;
164        gc.weightx = 1.0;
165        gc.weighty = 1.0;
166        gc.fill = GridBagConstraints.BOTH;
167        add(new JPanel(), gc);
168
169        rbUseNew.getModel().addItemListener(new RadioButtonHandler());
170        rbExisting.getModel().addItemListener(new RadioButtonHandler());
171    }
172
173    protected void refreshGUI() {
174        rbExisting.setEnabled(model.getSize() > 0);
175        if (model.getSize() == 0 && !rbUseNew.isSelected()) {
176            rbUseNew.setSelected(true);
177        }
178        cbOpenChangesets.setEnabled(model.getSize() > 0 && rbExisting.isSelected());
179    }
180
181    /**
182     * Sets the changeset to be used in the next upload
183     *
184     * @param cs the changeset
185     */
186    public void setSelectedChangesetForNextUpload(Changeset cs) {
187        int idx = model.getIndexOf(cs);
188        if (idx >= 0) {
189            rbExisting.setSelected(true);
190            model.setSelectedItem(cs);
191        }
192    }
193
194    /**
195     * Replies the currently selected changeset. null, if no changeset is
196     * selected or if the user has chosen to use a new changeset.
197     *
198     * @return the currently selected changeset. null, if no changeset is
199     * selected.
200     */
201    public Changeset getSelectedChangeset() {
202        if (rbUseNew.isSelected())
203            return null;
204        return (Changeset) cbOpenChangesets.getSelectedItem();
205    }
206
207    /**
208     * Determines if the user has chosen to close the changeset after the next upload.
209     * @return {@code true} if the user has chosen to close the changeset after the next upload
210     */
211    public boolean isCloseChangesetAfterUpload() {
212        return cbCloseAfterUpload.isSelected();
213    }
214
215    /* ---------------------------------------------------------------------------- */
216    /* Interface ListDataListener                                                   */
217    /* ---------------------------------------------------------------------------- */
218    @Override
219    public void contentsChanged(ListDataEvent e) {
220        refreshGUI();
221    }
222
223    @Override
224    public void intervalAdded(ListDataEvent e) {
225        refreshGUI();
226    }
227
228    @Override
229    public void intervalRemoved(ListDataEvent e) {
230        refreshGUI();
231    }
232
233    /**
234     * Listens to changes in the selected changeset and fires property change events.
235     */
236    class ChangesetListItemStateListener implements ItemListener {
237        @Override
238        public void itemStateChanged(ItemEvent e) {
239            Changeset cs = (Changeset) cbOpenChangesets.getSelectedItem();
240            if (cs == null) return;
241            if (rbExisting.isSelected()) {
242                firePropertyChange(SELECTED_CHANGESET_PROP, null, cs);
243            }
244        }
245    }
246
247    /**
248     * Listens to changes in "close after upload" flag and fires property change events.
249     */
250    class CloseAfterUploadItemStateListener implements ItemListener {
251        @Override
252        public void itemStateChanged(ItemEvent e) {
253            if (e.getItemSelectable() != cbCloseAfterUpload)
254                return;
255            switch(e.getStateChange()) {
256            case ItemEvent.SELECTED:
257                firePropertyChange(CLOSE_CHANGESET_AFTER_UPLOAD, false, true);
258                Main.pref.putBoolean("upload.changeset.close", true);
259                break;
260            case ItemEvent.DESELECTED:
261                firePropertyChange(CLOSE_CHANGESET_AFTER_UPLOAD, true, false);
262                Main.pref.putBoolean("upload.changeset.close", false);
263                break;
264            default: // Do nothing
265            }
266        }
267    }
268
269    /**
270     * Listens to changes in the two radio buttons rbUseNew and rbUseExisting.
271     */
272    class RadioButtonHandler implements ItemListener {
273        @Override
274        public void itemStateChanged(ItemEvent e) {
275            if (rbUseNew.isSelected()) {
276                cbOpenChangesets.setEnabled(false);
277                firePropertyChange(SELECTED_CHANGESET_PROP, null, null);
278            } else if (rbExisting.isSelected()) {
279                cbOpenChangesets.setEnabled(true);
280                if (cbOpenChangesets.getSelectedItem() == null) {
281                    model.selectFirstChangeset();
282                }
283                Changeset cs = (Changeset) cbOpenChangesets.getSelectedItem();
284                if (cs == null) return;
285                firePropertyChange(SELECTED_CHANGESET_PROP, null, cs);
286            }
287        }
288    }
289
290    /**
291     * Refreshes the list of open changesets
292     *
293     */
294    class RefreshAction extends AbstractAction {
295        RefreshAction() {
296            putValue(SHORT_DESCRIPTION, tr("Load the list of your open changesets from the server"));
297            putValue(SMALL_ICON, ImageProvider.get("dialogs", "refresh"));
298        }
299
300        @Override
301        public void actionPerformed(ActionEvent e) {
302            MainApplication.worker.submit(new DownloadOpenChangesetsTask(ChangesetManagementPanel.this));
303        }
304    }
305
306    /**
307     * Closes the currently selected changeset
308     *
309     */
310    class CloseChangesetAction extends AbstractAction implements ItemListener {
311        CloseChangesetAction() {
312            putValue(SMALL_ICON, ImageProvider.get("closechangeset"));
313            putValue(SHORT_DESCRIPTION, tr("Close the currently selected open changeset"));
314            refreshEnabledState();
315        }
316
317        @Override
318        public void actionPerformed(ActionEvent e) {
319            Changeset cs = (Changeset) cbOpenChangesets.getSelectedItem();
320            if (cs == null) return;
321            MainApplication.worker.submit(new CloseChangesetTask(Collections.singletonList(cs)));
322        }
323
324        protected void refreshEnabledState() {
325            setEnabled(
326                    cbOpenChangesets.getModel().getSize() > 0
327                    && cbOpenChangesets.getSelectedItem() != null
328                    && rbExisting.isSelected()
329            );
330        }
331
332        @Override
333        public void itemStateChanged(ItemEvent e) {
334            refreshEnabledState();
335        }
336    }
337}
Note: See TracBrowser for help on using the repository browser.