source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetContentPanel.java@ 9059

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

checkstyle

  • Property svn:eol-style set to native
File size: 17.2 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.dialogs.changeset;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5import static org.openstreetmap.josm.tools.I18n.trn;
6
7import java.awt.BorderLayout;
8import java.awt.FlowLayout;
9import java.awt.event.ActionEvent;
10import java.awt.event.ComponentAdapter;
11import java.awt.event.ComponentEvent;
12import java.beans.PropertyChangeEvent;
13import java.beans.PropertyChangeListener;
14import java.util.ArrayList;
15import java.util.Collection;
16import java.util.HashSet;
17import java.util.List;
18import java.util.Set;
19
20import javax.swing.AbstractAction;
21import javax.swing.BorderFactory;
22import javax.swing.DefaultListSelectionModel;
23import javax.swing.JButton;
24import javax.swing.JOptionPane;
25import javax.swing.JPanel;
26import javax.swing.JPopupMenu;
27import javax.swing.JScrollPane;
28import javax.swing.JSeparator;
29import javax.swing.JTable;
30import javax.swing.JToolBar;
31import javax.swing.event.ListSelectionEvent;
32import javax.swing.event.ListSelectionListener;
33
34import org.openstreetmap.josm.Main;
35import org.openstreetmap.josm.actions.AutoScaleAction;
36import org.openstreetmap.josm.data.osm.Changeset;
37import org.openstreetmap.josm.data.osm.OsmPrimitive;
38import org.openstreetmap.josm.data.osm.history.History;
39import org.openstreetmap.josm.data.osm.history.HistoryDataSet;
40import org.openstreetmap.josm.data.osm.history.HistoryOsmPrimitive;
41import org.openstreetmap.josm.gui.HelpAwareOptionPane;
42import org.openstreetmap.josm.gui.MapView;
43import org.openstreetmap.josm.gui.MapView.EditLayerChangeListener;
44import org.openstreetmap.josm.gui.help.HelpUtil;
45import org.openstreetmap.josm.gui.history.HistoryBrowserDialogManager;
46import org.openstreetmap.josm.gui.history.HistoryLoadTask;
47import org.openstreetmap.josm.gui.layer.OsmDataLayer;
48import org.openstreetmap.josm.gui.util.GuiHelper;
49import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
50import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
51import org.openstreetmap.josm.tools.BugReportExceptionHandler;
52import org.openstreetmap.josm.tools.ImageProvider;
53
54/**
55 * The panel which displays the content of a changeset in a scrollable table.
56 *
57 * It listens to property change events for {@link ChangesetCacheManagerModel#CHANGESET_IN_DETAIL_VIEW_PROP}
58 * and updates its view accordingly.
59 *
60 */
61public class ChangesetContentPanel extends JPanel implements PropertyChangeListener {
62
63 private ChangesetContentTableModel model;
64 private transient Changeset currentChangeset;
65
66 private DownloadChangesetContentAction actDownloadContentAction;
67 private ShowHistoryAction actShowHistory;
68 private SelectInCurrentLayerAction actSelectInCurrentLayerAction;
69 private ZoomInCurrentLayerAction actZoomInCurrentLayerAction;
70
71 private final HeaderPanel pnlHeader = new HeaderPanel();
72
73 protected void buildModels() {
74 DefaultListSelectionModel selectionModel = new DefaultListSelectionModel();
75 model = new ChangesetContentTableModel(selectionModel);
76 actDownloadContentAction = new DownloadChangesetContentAction();
77 actDownloadContentAction.initProperties(currentChangeset);
78 actShowHistory = new ShowHistoryAction();
79 model.getSelectionModel().addListSelectionListener(actShowHistory);
80
81 actSelectInCurrentLayerAction = new SelectInCurrentLayerAction();
82 model.getSelectionModel().addListSelectionListener(actSelectInCurrentLayerAction);
83 MapView.addEditLayerChangeListener(actSelectInCurrentLayerAction);
84
85 actZoomInCurrentLayerAction = new ZoomInCurrentLayerAction();
86 model.getSelectionModel().addListSelectionListener(actZoomInCurrentLayerAction);
87 MapView.addEditLayerChangeListener(actZoomInCurrentLayerAction);
88
89 addComponentListener(
90 new ComponentAdapter() {
91 @Override
92 public void componentHidden(ComponentEvent e) {
93 // make sure the listener is unregistered when the panel becomes
94 // invisible
95 MapView.removeEditLayerChangeListener(actSelectInCurrentLayerAction);
96 MapView.removeEditLayerChangeListener(actZoomInCurrentLayerAction);
97 }
98 }
99 );
100 }
101
102 protected JPanel buildContentPanel() {
103 JPanel pnl = new JPanel(new BorderLayout());
104 JTable tblContent = new JTable(
105 model,
106 new ChangesetContentTableColumnModel(),
107 model.getSelectionModel()
108 );
109 tblContent.addMouseListener(new PopupMenuLauncher(new ChangesetContentTablePopupMenu()));
110 pnl.add(new JScrollPane(tblContent), BorderLayout.CENTER);
111 return pnl;
112 }
113
114 protected JPanel buildActionButtonPanel() {
115 JPanel pnl = new JPanel(new FlowLayout(FlowLayout.LEFT));
116 JToolBar tb = new JToolBar(JToolBar.VERTICAL);
117 tb.setFloatable(false);
118
119 tb.add(actDownloadContentAction);
120 tb.add(actShowHistory);
121 tb.add(actSelectInCurrentLayerAction);
122 tb.add(actZoomInCurrentLayerAction);
123
124 pnl.add(tb);
125 return pnl;
126 }
127
128 protected final void build() {
129 setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
130 setLayout(new BorderLayout());
131 buildModels();
132
133 add(pnlHeader, BorderLayout.NORTH);
134 add(buildActionButtonPanel(), BorderLayout.WEST);
135 add(buildContentPanel(), BorderLayout.CENTER);
136 }
137
138 /**
139 * Constructs a new {@code ChangesetContentPanel}.
140 */
141 public ChangesetContentPanel() {
142 build();
143 }
144
145 /**
146 * Replies the changeset content model
147 * @return The model
148 */
149 public ChangesetContentTableModel getModel() {
150 return model;
151 }
152
153 protected void setCurrentChangeset(Changeset cs) {
154 currentChangeset = cs;
155 if (cs == null) {
156 model.populate(null);
157 } else {
158 model.populate(cs.getContent());
159 }
160 actDownloadContentAction.initProperties(cs);
161 pnlHeader.setChangeset(cs);
162 }
163
164 /* ---------------------------------------------------------------------------- */
165 /* interface PropertyChangeListener */
166 /* ---------------------------------------------------------------------------- */
167 @Override
168 public void propertyChange(PropertyChangeEvent evt) {
169 if (!evt.getPropertyName().equals(ChangesetCacheManagerModel.CHANGESET_IN_DETAIL_VIEW_PROP))
170 return;
171 Changeset cs = (Changeset) evt.getNewValue();
172 setCurrentChangeset(cs);
173 }
174
175 private void alertNoPrimitivesTo(Collection<HistoryOsmPrimitive> primitives, String title, String helpTopic) {
176 HelpAwareOptionPane.showOptionDialog(
177 ChangesetContentPanel.this,
178 trn("<html>The selected object is not available in the current<br>"
179 + "edit layer ''{0}''.</html>",
180 "<html>None of the selected objects is available in the current<br>"
181 + "edit layer ''{0}''.</html>",
182 primitives.size(),
183 Main.main.getEditLayer().getName()
184 ),
185 title, JOptionPane.WARNING_MESSAGE, helpTopic
186 );
187 }
188
189 /**
190 * Downloads/Updates the content of the changeset
191 *
192 */
193 class DownloadChangesetContentAction extends AbstractAction {
194 DownloadChangesetContentAction() {
195 putValue(NAME, tr("Download content"));
196 putValue(SMALL_ICON, ChangesetCacheManager.DOWNLOAD_CONTENT_ICON);
197 putValue(SHORT_DESCRIPTION, tr("Download the changeset content from the OSM server"));
198 }
199
200 @Override
201 public void actionPerformed(ActionEvent evt) {
202 if (currentChangeset == null) return;
203 ChangesetContentDownloadTask task = new ChangesetContentDownloadTask(ChangesetContentPanel.this, currentChangeset.getId());
204 ChangesetCacheManager.getInstance().runDownloadTask(task);
205 }
206
207 public void initProperties(Changeset cs) {
208 if (cs == null) {
209 setEnabled(false);
210 return;
211 } else {
212 setEnabled(true);
213 }
214 if (cs.getContent() == null) {
215 putValue(NAME, tr("Download content"));
216 putValue(SMALL_ICON, ChangesetCacheManager.DOWNLOAD_CONTENT_ICON);
217 putValue(SHORT_DESCRIPTION, tr("Download the changeset content from the OSM server"));
218 } else {
219 putValue(NAME, tr("Update content"));
220 putValue(SMALL_ICON, ChangesetCacheManager.UPDATE_CONTENT_ICON);
221 putValue(SHORT_DESCRIPTION, tr("Update the changeset content from the OSM server"));
222 }
223 }
224 }
225
226 class ChangesetContentTablePopupMenu extends JPopupMenu {
227 ChangesetContentTablePopupMenu() {
228 add(actDownloadContentAction);
229 add(actShowHistory);
230 add(new JSeparator());
231 add(actSelectInCurrentLayerAction);
232 add(actZoomInCurrentLayerAction);
233 }
234 }
235
236 class ShowHistoryAction extends AbstractAction implements ListSelectionListener {
237
238 private final class ShowHistoryTask implements Runnable {
239 private final Collection<HistoryOsmPrimitive> primitives;
240
241 private ShowHistoryTask(Collection<HistoryOsmPrimitive> primitives) {
242 this.primitives = primitives;
243 }
244
245 @Override
246 public void run() {
247 try {
248 for (HistoryOsmPrimitive p : primitives) {
249 final History h = HistoryDataSet.getInstance().getHistory(p.getPrimitiveId());
250 if (h == null) {
251 continue;
252 }
253 GuiHelper.runInEDT(new Runnable() {
254 @Override
255 public void run() {
256 HistoryBrowserDialogManager.getInstance().show(h);
257 }
258 });
259 }
260 } catch (final Exception e) {
261 GuiHelper.runInEDT(new Runnable() {
262 @Override
263 public void run() {
264 BugReportExceptionHandler.handleException(e);
265 }
266 });
267 }
268 }
269 }
270
271 ShowHistoryAction() {
272 putValue(NAME, tr("Show history"));
273 putValue(SMALL_ICON, ImageProvider.get("dialogs", "history"));
274 putValue(SHORT_DESCRIPTION, tr("Download and show the history of the selected objects"));
275 updateEnabledState();
276 }
277
278 protected List<HistoryOsmPrimitive> filterPrimitivesWithUnloadedHistory(Collection<HistoryOsmPrimitive> primitives) {
279 List<HistoryOsmPrimitive> ret = new ArrayList<>(primitives.size());
280 for (HistoryOsmPrimitive p: primitives) {
281 if (HistoryDataSet.getInstance().getHistory(p.getPrimitiveId()) == null) {
282 ret.add(p);
283 }
284 }
285 return ret;
286 }
287
288 public void showHistory(final Collection<HistoryOsmPrimitive> primitives) {
289
290 List<HistoryOsmPrimitive> toLoad = filterPrimitivesWithUnloadedHistory(primitives);
291 if (!toLoad.isEmpty()) {
292 HistoryLoadTask task = new HistoryLoadTask(ChangesetContentPanel.this);
293 for (HistoryOsmPrimitive p: toLoad) {
294 task.add(p);
295 }
296 Main.worker.submit(task);
297 }
298
299 Main.worker.submit(new ShowHistoryTask(primitives));
300 }
301
302 protected final void updateEnabledState() {
303 setEnabled(model.hasSelectedPrimitives());
304 }
305
306 @Override
307 public void actionPerformed(ActionEvent arg0) {
308 Set<HistoryOsmPrimitive> selected = model.getSelectedPrimitives();
309 if (selected.isEmpty()) return;
310 showHistory(selected);
311 }
312
313 @Override
314 public void valueChanged(ListSelectionEvent e) {
315 updateEnabledState();
316 }
317 }
318
319 class SelectInCurrentLayerAction extends AbstractAction implements ListSelectionListener, EditLayerChangeListener {
320
321 SelectInCurrentLayerAction() {
322 putValue(NAME, tr("Select in layer"));
323 putValue(SMALL_ICON, ImageProvider.get("dialogs", "select"));
324 putValue(SHORT_DESCRIPTION, tr("Select the corresponding primitives in the current data layer"));
325 updateEnabledState();
326 }
327
328 @Override
329 public void actionPerformed(ActionEvent arg0) {
330 if (!isEnabled())
331 return;
332 if (Main.main == null || !Main.main.hasEditLayer()) return;
333 OsmDataLayer layer = Main.main.getEditLayer();
334 Set<HistoryOsmPrimitive> selected = model.getSelectedPrimitives();
335 Set<OsmPrimitive> target = new HashSet<>();
336 for (HistoryOsmPrimitive p : model.getSelectedPrimitives()) {
337 OsmPrimitive op = layer.data.getPrimitiveById(p.getPrimitiveId());
338 if (op != null) {
339 target.add(op);
340 }
341 }
342 if (target.isEmpty()) {
343 alertNoPrimitivesTo(selected, tr("Nothing to select"),
344 HelpUtil.ht("/Dialog/ChangesetCacheManager#NothingToSelectInLayer"));
345 return;
346 }
347 layer.data.setSelected(target);
348 }
349
350 public final void updateEnabledState() {
351 if (Main.main == null || !Main.main.hasEditLayer()) {
352 setEnabled(false);
353 return;
354 }
355 setEnabled(model.hasSelectedPrimitives());
356 }
357
358 @Override
359 public void valueChanged(ListSelectionEvent e) {
360 updateEnabledState();
361 }
362
363 @Override
364 public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
365 updateEnabledState();
366 }
367 }
368
369 class ZoomInCurrentLayerAction extends AbstractAction implements ListSelectionListener, EditLayerChangeListener {
370
371 ZoomInCurrentLayerAction() {
372 putValue(NAME, tr("Zoom to in layer"));
373 putValue(SMALL_ICON, ImageProvider.get("dialogs/autoscale", "selection"));
374 putValue(SHORT_DESCRIPTION, tr("Zoom to the corresponding objects in the current data layer"));
375 updateEnabledState();
376 }
377
378 @Override
379 public void actionPerformed(ActionEvent arg0) {
380 if (!isEnabled())
381 return;
382 if (Main.main == null || !Main.main.hasEditLayer()) return;
383 OsmDataLayer layer = Main.main.getEditLayer();
384 Set<HistoryOsmPrimitive> selected = model.getSelectedPrimitives();
385 Set<OsmPrimitive> target = new HashSet<>();
386 for (HistoryOsmPrimitive p : model.getSelectedPrimitives()) {
387 OsmPrimitive op = layer.data.getPrimitiveById(p.getPrimitiveId());
388 if (op != null) {
389 target.add(op);
390 }
391 }
392 if (target.isEmpty()) {
393 alertNoPrimitivesTo(selected, tr("Nothing to zoom to"),
394 HelpUtil.ht("/Dialog/ChangesetCacheManager#NothingToZoomTo"));
395 return;
396 }
397 layer.data.setSelected(target);
398 AutoScaleAction.zoomToSelection();
399 }
400
401 public final void updateEnabledState() {
402 if (Main.main == null || !Main.main.hasEditLayer()) {
403 setEnabled(false);
404 return;
405 }
406 setEnabled(model.hasSelectedPrimitives());
407 }
408
409 @Override
410 public void valueChanged(ListSelectionEvent e) {
411 updateEnabledState();
412 }
413
414 @Override
415 public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
416 updateEnabledState();
417 }
418 }
419
420 private static class HeaderPanel extends JPanel {
421
422 private JMultilineLabel lblMessage;
423 private transient Changeset current;
424
425 protected final void build() {
426 setLayout(new FlowLayout(FlowLayout.LEFT));
427 lblMessage = new JMultilineLabel(
428 tr("The content of this changeset is not downloaded yet.")
429 );
430 add(lblMessage);
431 add(new JButton(new DownloadAction()));
432
433 }
434
435 HeaderPanel() {
436 build();
437 }
438
439 public void setChangeset(Changeset cs) {
440 setVisible(cs != null && cs.getContent() == null);
441 this.current = cs;
442 }
443
444 private class DownloadAction extends AbstractAction {
445 DownloadAction() {
446 putValue(NAME, tr("Download now"));
447 putValue(SHORT_DESCRIPTION, tr("Download the changeset content"));
448 putValue(SMALL_ICON, ChangesetCacheManager.DOWNLOAD_CONTENT_ICON);
449 }
450
451 @Override
452 public void actionPerformed(ActionEvent evt) {
453 if (current == null) return;
454 ChangesetContentDownloadTask task = new ChangesetContentDownloadTask(HeaderPanel.this, current.getId());
455 ChangesetCacheManager.getInstance().runDownloadTask(task);
456 }
457 }
458 }
459}
Note: See TracBrowser for help on using the repository browser.