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

Last change on this file since 12726 was 12634, checked in by Don-vip, 7 years ago

see #15182 - deprecate Main.worker, replace it by gui.MainApplication.worker + code refactoring to make sure only editor packages use it

  • 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.put("upload.changeset.close", true);
259 break;
260 case ItemEvent.DESELECTED:
261 firePropertyChange(CLOSE_CHANGESET_AFTER_UPLOAD, true, false);
262 Main.pref.put("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.