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

Last change on this file since 2613 was 2613, checked in by Gubaer, 14 years ago

new: global in-memory cache for downloaded changesets
new: toggle dialog for changesets
new: downloading of changesets (currently without changeset content, will follow later)

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