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

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

Sonar/FindBugs - Replace singular fields by local variables

  • Property svn:eol-style set to native
File size: 17.9 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.JMultilineLabel;
43import org.openstreetmap.josm.gui.MapView;
44import org.openstreetmap.josm.gui.MapView.EditLayerChangeListener;
45import org.openstreetmap.josm.gui.help.HelpUtil;
46import org.openstreetmap.josm.gui.history.HistoryBrowserDialogManager;
47import org.openstreetmap.josm.gui.history.HistoryLoadTask;
48import org.openstreetmap.josm.gui.layer.OsmDataLayer;
49import org.openstreetmap.josm.gui.util.GuiHelper;
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 scollable 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 Changeset currentChangeset;
65
66 private DonwloadChangesetContentAction actDownloadContentAction;
67 private ShowHistoryAction actShowHistory;
68 private SelectInCurrentLayerAction actSelectInCurrentLayerAction;
69 private ZoomInCurrentLayerAction actZoomInCurrentLayerAction;
70
71 private HeaderPanel pnlHeader;
72
73 protected void buildModels() {
74 DefaultListSelectionModel selectionModel =new DefaultListSelectionModel();
75 model = new ChangesetContentTableModel(selectionModel);
76 actDownloadContentAction = new DonwloadChangesetContentAction();
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 void build() {
129 setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
130 setLayout(new BorderLayout());
131 buildModels();
132
133 add(pnlHeader = new HeaderPanel(), BorderLayout.NORTH);
134 add(buildActionButtonPanel(), BorderLayout.WEST);
135 add(buildContentPanel(), BorderLayout.CENTER);
136
137 }
138
139 /**
140 * Constructs a new {@code ChangesetContentPanel}.
141 */
142 public ChangesetContentPanel() {
143 build();
144 }
145
146 /**
147 * Replies the changeset content model
148 * @return The model
149 */
150 public ChangesetContentTableModel getModel() {
151 return model;
152 }
153
154 protected void setCurrentChangeset(Changeset cs) {
155 currentChangeset = cs;
156 if (cs == null) {
157 model.populate(null);
158 } else {
159 model.populate(cs.getContent());
160 }
161 actDownloadContentAction.initProperties(cs);
162 pnlHeader.setChangeset(cs);
163 }
164
165 /* ---------------------------------------------------------------------------- */
166 /* interface PropertyChangeListener */
167 /* ---------------------------------------------------------------------------- */
168 @Override
169 public void propertyChange(PropertyChangeEvent evt) {
170 if(!evt.getPropertyName().equals(ChangesetCacheManagerModel.CHANGESET_IN_DETAIL_VIEW_PROP))
171 return;
172 Changeset cs = (Changeset)evt.getNewValue();
173 setCurrentChangeset(cs);
174 }
175
176 /**
177 * Downloads/Updates the content of the changeset
178 *
179 */
180 class DonwloadChangesetContentAction extends AbstractAction{
181 public DonwloadChangesetContentAction() {
182 putValue(NAME, tr("Download content"));
183 putValue(SMALL_ICON, ImageProvider.get("dialogs/changeset","downloadchangesetcontent"));
184 putValue(SHORT_DESCRIPTION, tr("Download the changeset content from the OSM server"));
185 }
186
187 @Override
188 public void actionPerformed(ActionEvent evt) {
189 if (currentChangeset == null) return;
190 ChangesetContentDownloadTask task = new ChangesetContentDownloadTask(ChangesetContentPanel.this,currentChangeset.getId());
191 ChangesetCacheManager.getInstance().runDownloadTask(task);
192 }
193
194 public void initProperties(Changeset cs) {
195 if (cs == null) {
196 setEnabled(false);
197 return;
198 } else {
199 setEnabled(true);
200 }
201 if (cs.getContent() == null) {
202 putValue(NAME, tr("Download content"));
203 putValue(SMALL_ICON, ImageProvider.get("dialogs/changeset","downloadchangesetcontent"));
204 putValue(SHORT_DESCRIPTION, tr("Download the changeset content from the OSM server"));
205 } else {
206 putValue(NAME, tr("Update content"));
207 putValue(SMALL_ICON, ImageProvider.get("dialogs/changeset","updatechangesetcontent"));
208 putValue(SHORT_DESCRIPTION, tr("Update the changeset content from the OSM server"));
209 }
210 }
211 }
212
213 class ChangesetContentTablePopupMenu extends JPopupMenu {
214 public ChangesetContentTablePopupMenu() {
215 add(actDownloadContentAction);
216 add(actShowHistory);
217 add(new JSeparator());
218 add(actSelectInCurrentLayerAction);
219 add(actZoomInCurrentLayerAction);
220 }
221 }
222
223 class ShowHistoryAction extends AbstractAction implements ListSelectionListener{
224 public ShowHistoryAction() {
225 putValue(NAME, tr("Show history"));
226 putValue(SMALL_ICON, ImageProvider.get("dialogs", "history"));
227 putValue(SHORT_DESCRIPTION, tr("Download and show the history of the selected objects"));
228 updateEnabledState();
229 }
230
231 protected List<HistoryOsmPrimitive> filterPrimitivesWithUnloadedHistory(Collection<HistoryOsmPrimitive> primitives) {
232 ArrayList<HistoryOsmPrimitive> ret = new ArrayList<HistoryOsmPrimitive>(primitives.size());
233 for (HistoryOsmPrimitive p: primitives) {
234 if (HistoryDataSet.getInstance().getHistory(p.getPrimitiveId()) == null) {
235 ret.add(p);
236 }
237 }
238 return ret;
239 }
240
241 public void showHistory(final Collection<HistoryOsmPrimitive> primitives) {
242
243 List<HistoryOsmPrimitive> toLoad = filterPrimitivesWithUnloadedHistory(primitives);
244 if (!toLoad.isEmpty()) {
245 HistoryLoadTask task = new HistoryLoadTask(ChangesetContentPanel.this);
246 for (HistoryOsmPrimitive p: toLoad) {
247 task.add(p);
248 }
249 Main.worker.submit(task);
250 }
251
252 Runnable r = new Runnable() {
253 @Override
254 public void run() {
255 try {
256 for (HistoryOsmPrimitive p : primitives) {
257 final History h = HistoryDataSet.getInstance().getHistory(p.getPrimitiveId());
258 if (h == null) {
259 continue;
260 }
261 GuiHelper.runInEDT(new Runnable() {
262 @Override public void run() {
263 HistoryBrowserDialogManager.getInstance().show(h);
264 }
265 });
266 }
267 } catch (final Exception e) {
268 GuiHelper.runInEDT(new Runnable() {
269 @Override
270 public void run() {
271 BugReportExceptionHandler.handleException(e);
272 }
273 });
274 }
275
276 }
277 };
278 Main.worker.submit(r);
279 }
280
281 protected void updateEnabledState() {
282 setEnabled(model.hasSelectedPrimitives());
283 }
284
285 @Override
286 public void actionPerformed(ActionEvent arg0) {
287 Set<HistoryOsmPrimitive> selected = model.getSelectedPrimitives();
288 if (selected.isEmpty()) return;
289 showHistory(selected);
290 }
291
292 @Override
293 public void valueChanged(ListSelectionEvent e) {
294 updateEnabledState();
295 }
296 }
297
298 class SelectInCurrentLayerAction extends AbstractAction implements ListSelectionListener, EditLayerChangeListener{
299
300 public SelectInCurrentLayerAction() {
301 putValue(NAME, tr("Select in layer"));
302 putValue(SMALL_ICON, ImageProvider.get("dialogs", "select"));
303 putValue(SHORT_DESCRIPTION, tr("Select the corresponding primitives in the current data layer"));
304 updateEnabledState();
305 }
306
307 protected void alertNoPrimitivesToSelect(Collection<HistoryOsmPrimitive> primitives) {
308 HelpAwareOptionPane.showOptionDialog(
309 ChangesetContentPanel.this,
310 trn("<html>The selected object is not available in the current<br>"
311 + "edit layer ''{0}''.</html>",
312 "<html>None of the selected objects is available in the current<br>"
313 + "edit layer ''{0}''.</html>",
314 primitives.size(),
315 Main.main.getEditLayer().getName()
316 ),
317 tr("Nothing to select"),
318 JOptionPane.WARNING_MESSAGE,
319 HelpUtil.ht("/Dialog/ChangesetCacheManager#NothingToSelectInLayer")
320 );
321 }
322
323 @Override
324 public void actionPerformed(ActionEvent arg0) {
325 if (!isEnabled())
326 return;
327 if (Main.main == null || Main.main.getEditLayer() == null) return;
328 OsmDataLayer layer = Main.main.getEditLayer();
329 Set<HistoryOsmPrimitive> selected = model.getSelectedPrimitives();
330 Set<OsmPrimitive> target = new HashSet<OsmPrimitive>();
331 for (HistoryOsmPrimitive p : model.getSelectedPrimitives()) {
332 OsmPrimitive op = layer.data.getPrimitiveById(p.getPrimitiveId());
333 if (op != null) {
334 target.add(op);
335 }
336 }
337 if (target.isEmpty()) {
338 alertNoPrimitivesToSelect(selected);
339 return;
340 }
341 layer.data.setSelected(target);
342 }
343
344 public void updateEnabledState() {
345 if (Main.main == null || Main.main.getEditLayer() == null){
346 setEnabled(false);
347 return;
348 }
349 setEnabled(model.hasSelectedPrimitives());
350 }
351
352 @Override
353 public void valueChanged(ListSelectionEvent e) {
354 updateEnabledState();
355 }
356
357 @Override
358 public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
359 updateEnabledState();
360 }
361 }
362
363 class ZoomInCurrentLayerAction extends AbstractAction implements ListSelectionListener, EditLayerChangeListener{
364
365 public ZoomInCurrentLayerAction() {
366 putValue(NAME, tr("Zoom to in layer"));
367 putValue(SMALL_ICON, ImageProvider.get("dialogs/autoscale", "selection"));
368 putValue(SHORT_DESCRIPTION, tr("Zoom to the corresponding objects in the current data layer"));
369 updateEnabledState();
370 }
371
372 protected void alertNoPrimitivesToZoomTo(Collection<HistoryOsmPrimitive> primitives) {
373 HelpAwareOptionPane.showOptionDialog(
374 ChangesetContentPanel.this,
375 trn("<html>The selected object is not available in the current<br>"
376 + "edit layer ''{0}''.</html>",
377 "<html>None of the selected objects is available in the current<br>"
378 + "edit layer ''{0}''.</html>",
379 primitives.size(),
380 Main.main.getEditLayer().getName()
381 ),
382 tr("Nothing to zoom to"),
383 JOptionPane.WARNING_MESSAGE,
384 HelpUtil.ht("/Dialog/ChangesetCacheManager#NothingToZoomTo")
385 );
386 }
387
388 @Override
389 public void actionPerformed(ActionEvent arg0) {
390 if (!isEnabled())
391 return;
392 if (Main.main == null || Main.main.getEditLayer() == null) return;
393 OsmDataLayer layer = Main.main.getEditLayer();
394 Set<HistoryOsmPrimitive> selected = model.getSelectedPrimitives();
395 Set<OsmPrimitive> target = new HashSet<OsmPrimitive>();
396 for (HistoryOsmPrimitive p : model.getSelectedPrimitives()) {
397 OsmPrimitive op = layer.data.getPrimitiveById(p.getPrimitiveId());
398 if (op != null) {
399 target.add(op);
400 }
401 }
402 if (target.isEmpty()) {
403 alertNoPrimitivesToZoomTo(selected);
404 return;
405 }
406 layer.data.setSelected(target);
407 AutoScaleAction.zoomToSelection();
408 }
409
410 public void updateEnabledState() {
411 if (Main.main == null || Main.main.getEditLayer() == null){
412 setEnabled(false);
413 return;
414 }
415 setEnabled(model.hasSelectedPrimitives());
416 }
417
418 @Override
419 public void valueChanged(ListSelectionEvent e) {
420 updateEnabledState();
421 }
422
423 @Override
424 public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
425 updateEnabledState();
426 }
427 }
428
429 static private class HeaderPanel extends JPanel {
430
431 private JMultilineLabel lblMessage;
432 private Changeset current;
433
434 protected void build() {
435 setLayout(new FlowLayout(FlowLayout.LEFT));
436 lblMessage = new JMultilineLabel(
437 tr("The content of this changeset is not downloaded yet.")
438 );
439 add(lblMessage);
440 add(new JButton(new DownloadAction()));
441
442 }
443
444 public HeaderPanel() {
445 build();
446 }
447
448 public void setChangeset(Changeset cs) {
449 setVisible(cs != null && cs.getContent() == null);
450 this.current = cs;
451 }
452
453 private class DownloadAction extends AbstractAction {
454 public DownloadAction() {
455 putValue(NAME, tr("Download now"));
456 putValue(SHORT_DESCRIPTION, tr("Download the changeset content"));
457 putValue(SMALL_ICON, ImageProvider.get("dialogs/changeset", "downloadchangesetcontent"));
458 }
459
460 @Override
461 public void actionPerformed(ActionEvent evt) {
462 if (current == null) return;
463 ChangesetContentDownloadTask task = new ChangesetContentDownloadTask(HeaderPanel.this, current.getId());
464 ChangesetCacheManager.getInstance().runDownloadTask(task);
465 }
466 }
467 }
468}
Note: See TracBrowser for help on using the repository browser.