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

Last change on this file since 6340 was 6340, checked in by Don-vip, 5 years ago

refactor of some GUI/widgets classes (impacts some plugins):

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