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

Last change on this file since 3530 was 3530, checked in by stoecker, 14 years ago

fix array preferences

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