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

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

fix #12983 - replace calls to Main.main.get[Active|Edit]Layer() by Main.getLayerManager().get[Active|Edit]Layer() - gsoc-core

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