source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetDetailPanel.java@ 6070

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

see #4429 - Right click menu "undo, cut, copy, paste, delete, select all" for each text component (originally based on patch by NooN)

  • Property svn:eol-style set to native
File size: 16.5 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.trc;
6
7import java.awt.BorderLayout;
8import java.awt.FlowLayout;
9import java.awt.GridBagConstraints;
10import java.awt.GridBagLayout;
11import java.awt.Insets;
12import java.awt.event.ActionEvent;
13import java.awt.event.ComponentAdapter;
14import java.awt.event.ComponentEvent;
15import java.beans.PropertyChangeEvent;
16import java.beans.PropertyChangeListener;
17import java.text.DateFormat;
18import java.util.Collection;
19import java.util.Collections;
20import java.util.HashSet;
21import java.util.Set;
22
23import javax.swing.AbstractAction;
24import javax.swing.BorderFactory;
25import javax.swing.JLabel;
26import javax.swing.JOptionPane;
27import javax.swing.JPanel;
28import javax.swing.JToolBar;
29
30import org.openstreetmap.josm.Main;
31import org.openstreetmap.josm.actions.AutoScaleAction;
32import org.openstreetmap.josm.data.osm.Changeset;
33import org.openstreetmap.josm.data.osm.ChangesetCache;
34import org.openstreetmap.josm.data.osm.OsmPrimitive;
35import org.openstreetmap.josm.gui.HelpAwareOptionPane;
36import org.openstreetmap.josm.gui.MapView;
37import org.openstreetmap.josm.gui.MapView.EditLayerChangeListener;
38import org.openstreetmap.josm.gui.help.HelpUtil;
39import org.openstreetmap.josm.gui.layer.OsmDataLayer;
40import org.openstreetmap.josm.gui.widgets.JosmTextArea;
41import org.openstreetmap.josm.gui.widgets.JosmTextField;
42import org.openstreetmap.josm.tools.ImageProvider;
43
44
45/**
46 * This panel displays the properties of the currently selected changeset in the
47 * {@link ChangesetCacheManager}.
48 *
49 */
50public class ChangesetDetailPanel extends JPanel implements PropertyChangeListener{
51
52 private JosmTextField tfID;
53 private JosmTextArea taComment;
54 private JosmTextField tfOpen;
55 private JosmTextField tfUser;
56 private JosmTextField tfCreatedOn;
57 private JosmTextField tfClosedOn;
58 private DonwloadChangesetContentAction actDownloadChangesetContent;
59 private UpdateChangesetAction actUpdateChangesets;
60 private RemoveFromCacheAction actRemoveFromCache;
61 private SelectInCurrentLayerAction actSelectInCurrentLayer;
62 private ZoomInCurrentLayerAction actZoomInCurrentLayerAction;
63
64 private Changeset current = null;
65
66 protected JPanel buildActionButtonPanel() {
67 JPanel pnl = new JPanel(new FlowLayout(FlowLayout.LEFT));
68
69 JToolBar tb = new JToolBar(JToolBar.VERTICAL);
70 tb.setFloatable(false);
71
72 // -- remove from cache action
73 tb.add(actRemoveFromCache = new RemoveFromCacheAction());
74 actRemoveFromCache.initProperties(current);
75
76 // -- changeset update
77 tb.add(actUpdateChangesets = new UpdateChangesetAction());
78 actUpdateChangesets.initProperties(current);
79
80 // -- changeset content download
81 tb.add(actDownloadChangesetContent =new DonwloadChangesetContentAction());
82 actDownloadChangesetContent.initProperties(current);
83
84 tb.add(actSelectInCurrentLayer = new SelectInCurrentLayerAction());
85 MapView.addEditLayerChangeListener(actSelectInCurrentLayer);
86
87 tb.add(actZoomInCurrentLayerAction = new ZoomInCurrentLayerAction());
88 MapView.addEditLayerChangeListener(actZoomInCurrentLayerAction);
89
90 addComponentListener(
91 new ComponentAdapter() {
92 @Override
93 public void componentHidden(ComponentEvent e) {
94 // make sure the listener is unregistered when the panel becomes
95 // invisible
96 MapView.removeEditLayerChangeListener(actSelectInCurrentLayer);
97 MapView.removeEditLayerChangeListener(actZoomInCurrentLayerAction);
98 }
99 }
100 );
101
102 pnl.add(tb);
103 return pnl;
104 }
105
106 protected JPanel buildDetailViewPanel() {
107 JPanel pnl = new JPanel(new GridBagLayout());
108
109 GridBagConstraints gc = new GridBagConstraints();
110 gc.anchor = GridBagConstraints.FIRST_LINE_START;
111 gc.insets = new Insets(0,0,2,3);
112
113 //-- id
114 gc.fill = GridBagConstraints.HORIZONTAL;
115 gc.weightx = 0.0;
116 pnl.add(new JLabel(tr("ID:")), gc);
117
118 gc.fill = GridBagConstraints.HORIZONTAL;
119 gc.weightx = 0.0;
120 gc.gridx = 1;
121 pnl.add(tfID = new JosmTextField(10), gc);
122 tfID.setEditable(false);
123
124 //-- comment
125 gc.gridx = 0;
126 gc.gridy = 1;
127 gc.fill = GridBagConstraints.HORIZONTAL;
128 gc.weightx = 0.0;
129 pnl.add(new JLabel(tr("Comment:")), gc);
130
131 gc.fill = GridBagConstraints.BOTH;
132 gc.weightx = 1.0;
133 gc.weighty = 1.0;
134 gc.gridx = 1;
135 pnl.add(taComment= new JosmTextArea(5,40), gc);
136 taComment.setEditable(false);
137
138 //-- Open/Closed
139 gc.gridx = 0;
140 gc.gridy = 2;
141 gc.fill = GridBagConstraints.HORIZONTAL;
142 gc.weightx = 0.0;
143 gc.weighty = 0.0;
144 pnl.add(new JLabel(tr("Open/Closed:")), gc);
145
146 gc.fill = GridBagConstraints.HORIZONTAL;
147 gc.gridx = 1;
148 pnl.add(tfOpen= new JosmTextField(10), gc);
149 tfOpen.setEditable(false);
150
151 //-- Created by:
152 gc.gridx = 0;
153 gc.gridy = 3;
154 gc.fill = GridBagConstraints.HORIZONTAL;
155 gc.weightx = 0.0;
156 pnl.add(new JLabel(tr("Created by:")), gc);
157
158 gc.fill = GridBagConstraints.HORIZONTAL;
159 gc.weightx = 1.0;
160 gc.gridx = 1;
161 pnl.add(tfUser= new JosmTextField(""), gc);
162 tfUser.setEditable(false);
163
164 //-- Created On:
165 gc.gridx = 0;
166 gc.gridy = 4;
167 gc.fill = GridBagConstraints.HORIZONTAL;
168 gc.weightx = 0.0;
169 pnl.add(new JLabel(tr("Created on:")), gc);
170
171 gc.fill = GridBagConstraints.HORIZONTAL;
172 gc.gridx = 1;
173 pnl.add(tfCreatedOn= new JosmTextField(20), gc);
174 tfCreatedOn.setEditable(false);
175
176 //-- Closed On:
177 gc.gridx = 0;
178 gc.gridy = 5;
179 gc.fill = GridBagConstraints.HORIZONTAL;
180 gc.weightx = 0.0;
181 pnl.add(new JLabel(tr("Closed on:")), gc);
182
183 gc.fill = GridBagConstraints.HORIZONTAL;
184 gc.gridx = 1;
185 pnl.add(tfClosedOn= new JosmTextField(20), gc);
186 tfClosedOn.setEditable(false);
187
188 return pnl;
189 }
190
191 protected void build() {
192 setLayout(new BorderLayout());
193 setBorder(BorderFactory.createEmptyBorder(3,3,3,3));
194 add(buildDetailViewPanel(), BorderLayout.CENTER);
195 add(buildActionButtonPanel(), BorderLayout.WEST);
196 }
197
198 protected void clearView() {
199 tfID.setText("");
200 taComment.setText("");
201 tfOpen.setText("");
202 tfUser.setText("");
203 tfCreatedOn.setText("");
204 tfClosedOn.setText("");
205 }
206
207 protected void updateView(Changeset cs) {
208 String msg;
209 if (cs == null) return;
210 tfID.setText(Integer.toString(cs.getId()));
211 String comment = cs.get("comment");
212 taComment.setText(comment == null ? "" : comment);
213
214 if (cs.isOpen()) {
215 msg = trc("changeset.state", "Open");
216 } else {
217 msg = trc("changeset.state", "Closed");
218 }
219 tfOpen.setText(msg);
220
221 if (cs.getUser() == null) {
222 msg = tr("anonymous");
223 } else {
224 msg = cs.getUser().getName();
225 }
226 tfUser.setText(msg);
227 DateFormat sdf = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
228
229 tfCreatedOn.setText(cs.getCreatedAt() == null ? "" : sdf.format(cs.getCreatedAt()));
230 tfClosedOn.setText(cs.getClosedAt() == null ? "" : sdf.format(cs.getClosedAt()));
231 }
232
233 /**
234 * Constructs a new {@code ChangesetDetailPanel}.
235 */
236 public ChangesetDetailPanel() {
237 build();
238 }
239
240 protected void setCurrentChangeset(Changeset cs) {
241 current = cs;
242 if (cs == null) {
243 clearView();
244 } else {
245 updateView(cs);
246 }
247 actDownloadChangesetContent.initProperties(current);
248 actUpdateChangesets.initProperties(current);
249 actRemoveFromCache.initProperties(current);
250 actSelectInCurrentLayer.updateEnabledState();
251 actZoomInCurrentLayerAction.updateEnabledState();
252 }
253
254 /* ---------------------------------------------------------------------------- */
255 /* interface PropertyChangeListener */
256 /* ---------------------------------------------------------------------------- */
257 public void propertyChange(PropertyChangeEvent evt) {
258 if (! evt.getPropertyName().equals(ChangesetCacheManagerModel.CHANGESET_IN_DETAIL_VIEW_PROP))
259 return;
260 Changeset cs = (Changeset)evt.getNewValue();
261 setCurrentChangeset(cs);
262 }
263
264 /**
265 * The action for removing the currently selected changeset from the changeset cache
266 */
267 class RemoveFromCacheAction extends AbstractAction {
268 public RemoveFromCacheAction() {
269 putValue(NAME, tr("Remove from cache"));
270 putValue(SMALL_ICON, ImageProvider.get("dialogs", "delete"));
271 putValue(SHORT_DESCRIPTION, tr("Remove the changeset in the detail view panel from the local cache"));
272 }
273
274 public void actionPerformed(ActionEvent evt) {
275 if (current == null)
276 return;
277 ChangesetCache.getInstance().remove(current);
278 }
279
280 public void initProperties(Changeset cs) {
281 setEnabled(cs != null);
282 }
283 }
284
285 /**
286 * Removes the selected changesets from the local changeset cache
287 *
288 */
289 class DonwloadChangesetContentAction extends AbstractAction{
290 public DonwloadChangesetContentAction() {
291 putValue(NAME, tr("Download content"));
292 putValue(SMALL_ICON, ImageProvider.get("dialogs/changeset","downloadchangesetcontent"));
293 putValue(SHORT_DESCRIPTION, tr("Download the changeset content from the OSM server"));
294 }
295
296 public void actionPerformed(ActionEvent evt) {
297 if (current == null) return;
298 ChangesetContentDownloadTask task = new ChangesetContentDownloadTask(ChangesetDetailPanel.this,current.getId());
299 ChangesetCacheManager.getInstance().runDownloadTask(task);
300 }
301
302 public void initProperties(Changeset cs) {
303 if (cs == null) {
304 setEnabled(false);
305 return;
306 } else {
307 setEnabled(true);
308 }
309 if (cs.getContent() == null) {
310 putValue(NAME, tr("Download content"));
311 putValue(SMALL_ICON, ImageProvider.get("dialogs/changeset","downloadchangesetcontent"));
312 putValue(SHORT_DESCRIPTION, tr("Download the changeset content from the OSM server"));
313 } else {
314 putValue(NAME, tr("Update content"));
315 putValue(SMALL_ICON, ImageProvider.get("dialogs/changeset","updatechangesetcontent"));
316 putValue(SHORT_DESCRIPTION, tr("Update the changeset content from the OSM server"));
317 }
318 }
319 }
320
321 /**
322 * Updates the current changeset from the OSM server
323 *
324 */
325 class UpdateChangesetAction extends AbstractAction{
326 public UpdateChangesetAction() {
327 putValue(NAME, tr("Update changeset"));
328 putValue(SMALL_ICON,ImageProvider.get("dialogs/changeset","updatechangeset"));
329 putValue(SHORT_DESCRIPTION, tr("Update the changeset from the OSM server"));
330 }
331
332 public void actionPerformed(ActionEvent evt) {
333 if (current == null) return;
334 Main.worker.submit(
335 new ChangesetHeaderDownloadTask(
336 ChangesetDetailPanel.this,
337 Collections.singleton(current.getId())
338 )
339 );
340 }
341
342 public void initProperties(Changeset cs) {
343 if (cs == null) {
344 setEnabled(false);
345 return;
346 } else {
347 setEnabled(true);
348 }
349 }
350 }
351
352 /**
353 * Selects the primitives in the content of this changeset in the current
354 * data layer.
355 *
356 */
357 class SelectInCurrentLayerAction extends AbstractAction implements EditLayerChangeListener{
358
359 public SelectInCurrentLayerAction() {
360 putValue(NAME, tr("Select in layer"));
361 putValue(SMALL_ICON, ImageProvider.get("dialogs", "select"));
362 putValue(SHORT_DESCRIPTION, tr("Select the primitives in the content of this changeset in the current data layer"));
363 updateEnabledState();
364 }
365
366 protected void alertNoPrimitivesToSelect(Collection<OsmPrimitive> primitives) {
367 HelpAwareOptionPane.showOptionDialog(
368 ChangesetDetailPanel.this,
369 tr("<html>None of the objects in the content of changeset {0} is available in the current<br>"
370 + "edit layer ''{1}''.</html>",
371 current.getId(),
372 Main.main.getEditLayer().getName()
373 ),
374 tr("Nothing to select"),
375 JOptionPane.WARNING_MESSAGE,
376 HelpUtil.ht("/Dialog/ChangesetCacheManager#NothingToSelectInLayer")
377 );
378 }
379
380 public void actionPerformed(ActionEvent arg0) {
381 if (!isEnabled())
382 return;
383 if (Main.main == null || Main.main.getEditLayer() == null) return;
384 OsmDataLayer layer = Main.main.getEditLayer();
385 Set<OsmPrimitive> target = new HashSet<OsmPrimitive>();
386 for (OsmPrimitive p: layer.data.allPrimitives()) {
387 if (p.isUsable() && p.getChangesetId() == current.getId()) {
388 target.add(p);
389 }
390 }
391 if (target.isEmpty()) {
392 alertNoPrimitivesToSelect(target);
393 return;
394 }
395 layer.data.setSelected(target);
396 }
397
398 public void updateEnabledState() {
399 if (Main.main == null || Main.main.getEditLayer() == null){
400 setEnabled(false);
401 return;
402 }
403 setEnabled(current != null);
404 }
405
406 public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
407 updateEnabledState();
408 }
409 }
410
411 /**
412 * Zooms to the primitives in the content of this changeset in the current
413 * data layer.
414 *
415 */
416 class ZoomInCurrentLayerAction extends AbstractAction implements EditLayerChangeListener{
417
418 public ZoomInCurrentLayerAction() {
419 putValue(NAME, tr("Zoom to in layer"));
420 putValue(SMALL_ICON, ImageProvider.get("dialogs/autoscale", "selection"));
421 putValue(SHORT_DESCRIPTION, tr("Zoom to the objects in the content of this changeset in the current data layer"));
422 updateEnabledState();
423 }
424
425 protected void alertNoPrimitivesToZoomTo() {
426 HelpAwareOptionPane.showOptionDialog(
427 ChangesetDetailPanel.this,
428 tr("<html>None of the objects in the content of changeset {0} is available in the current<br>"
429 + "edit layer ''{1}''.</html>",
430 current.getId(),
431 Main.main.getEditLayer().getName()
432 ),
433 tr("Nothing to zoom to"),
434 JOptionPane.WARNING_MESSAGE,
435 HelpUtil.ht("/Dialog/ChangesetCacheManager#NothingToZoomTo")
436 );
437 }
438
439 public void actionPerformed(ActionEvent arg0) {
440 if (!isEnabled())
441 return;
442 if (Main.main == null || Main.main.getEditLayer() == null) return;
443 OsmDataLayer layer = Main.main.getEditLayer();
444 Set<OsmPrimitive> target = new HashSet<OsmPrimitive>();
445 for (OsmPrimitive p: layer.data.allPrimitives()) {
446 if (p.isUsable() && p.getChangesetId() == current.getId()) {
447 target.add(p);
448 }
449 }
450 if (target.isEmpty()) {
451 alertNoPrimitivesToZoomTo();
452 return;
453 }
454 layer.data.setSelected(target);
455 AutoScaleAction.zoomToSelection();
456 }
457
458 public void updateEnabledState() {
459 if (Main.main == null || Main.main.getEditLayer() == null){
460 setEnabled(false);
461 return;
462 }
463 setEnabled(current != null);
464 }
465
466 public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
467 updateEnabledState();
468 }
469 }
470}
Note: See TracBrowser for help on using the repository browser.