source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/layer/MergeGpxLayerDialog.java@ 14338

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

fix #16755 - Cut overlapping GPX layers when merging (patch by Bjoeni, modified)

  • Property svn:eol-style set to native
File size: 7.2 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.dialogs.layer;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Component;
7import java.awt.GridBagLayout;
8import java.awt.event.ActionEvent;
9import java.awt.event.ActionListener;
10import java.util.Collections;
11import java.util.List;
12
13import javax.swing.JButton;
14import javax.swing.JCheckBox;
15import javax.swing.JLabel;
16import javax.swing.JOptionPane;
17import javax.swing.JPanel;
18import javax.swing.JScrollPane;
19import javax.swing.JTable;
20import javax.swing.ListSelectionModel;
21import javax.swing.event.ListSelectionEvent;
22import javax.swing.event.ListSelectionListener;
23import javax.swing.table.AbstractTableModel;
24import javax.swing.table.TableColumnModel;
25
26import org.openstreetmap.josm.data.SystemOfMeasurement;
27import org.openstreetmap.josm.gui.ConditionalOptionPaneUtil;
28import org.openstreetmap.josm.gui.ExtendedDialog;
29import org.openstreetmap.josm.gui.layer.GpxLayer;
30import org.openstreetmap.josm.spi.preferences.Config;
31import org.openstreetmap.josm.tools.GBC;
32import org.openstreetmap.josm.tools.ImageProvider;
33import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
34
35/**
36 * The Dialog asking the user to prioritize GPX layers when cutting overlapping tracks.
37 * Shows a checkbox asking whether to combine the tracks on cuts.
38 * @since 14338
39 */
40public class MergeGpxLayerDialog extends ExtendedDialog {
41
42 private final GpxLayersTableModel model;
43 private final JTable t;
44 private final JCheckBox c;
45 private final Component parent;
46 private final JButton btnUp;
47 private final JButton btnDown;
48
49 /**
50 * Constructs a new {@code MergeGpxLayerDialog}
51 * @param parent the parent
52 * @param layers the GpxLayers to choose from
53 */
54 public MergeGpxLayerDialog(Component parent, List<GpxLayer> layers) {
55 super(parent, tr("Merge GPX layers"), tr("Merge"), tr("Cancel"));
56 setButtonIcons("dialogs/mergedown", "cancel");
57 this.parent = parent;
58
59 JPanel p = new JPanel(new GridBagLayout());
60 p.add(new JLabel("<html>" +
61 tr("Please select the order of the selected layers:<br>Tracks will be cut, when timestamps of higher layers are overlapping.") +
62 "</html>"), GBC.std(0, 0).fill(GBC.HORIZONTAL).span(2));
63
64 c = new JCheckBox(tr("Connect overlapping tracks on cuts"));
65 c.setSelected(Config.getPref().getBoolean("mergelayer.gpx.connect", true));
66 p.add(c, GBC.std(0, 1).fill(GBC.HORIZONTAL).span(2));
67
68 model = new GpxLayersTableModel(layers);
69 t = new JTable(model);
70 t.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
71 t.setRowSelectionInterval(0, 0);
72
73 JScrollPane sp = new JScrollPane(t);
74 p.add(sp, GBC.std(0, 2).fill().span(2));
75
76 t.getSelectionModel().addListSelectionListener(new RowSelectionChangedListener());
77 TableColumnModel cmodel = t.getColumnModel();
78 cmodel.getColumn(0).setPreferredWidth((int) (sp.getPreferredSize().getWidth() - 150));
79 cmodel.getColumn(1).setPreferredWidth(75);
80 cmodel.getColumn(2).setPreferredWidth(75);
81
82 btnUp = new JButton(tr("Move layer up"));
83 btnUp.setIcon(ImageProvider.get("dialogs", "up", ImageSizes.SMALLICON));
84 btnUp.setEnabled(false);
85
86 btnDown = new JButton(tr("Move layer down"));
87 btnDown.setIcon(ImageProvider.get("dialogs", "down", ImageSizes.SMALLICON));
88
89 p.add(btnUp, GBC.std(0, 3).fill(GBC.HORIZONTAL));
90 p.add(btnDown, GBC.std(1, 3).fill(GBC.HORIZONTAL));
91
92 btnUp.addActionListener(new MoveLayersActionListener(true));
93 btnDown.addActionListener(new MoveLayersActionListener(false));
94
95 setContent(p);
96 }
97
98 @Override
99 public MergeGpxLayerDialog showDialog() {
100 super.showDialog();
101 if (getValue() == 1) {
102 Config.getPref().putBoolean("mergelayer.gpx.connect", c.isSelected());
103 }
104 return this;
105 }
106
107 /**
108 * Whether the user chose to connect the tracks on cuts
109 * @return the checkbox state
110 */
111 public boolean connectCuts() {
112 return c.isSelected();
113 }
114
115 /**
116 * The {@code List<GpxLayer>} as sorted by the user
117 * @return the list
118 */
119 public List<GpxLayer> getSortedLayers() {
120 return model.getSortedLayers();
121 }
122
123 private class MoveLayersActionListener implements ActionListener {
124
125 private final boolean moveUp;
126
127 MoveLayersActionListener(boolean up) {
128 moveUp = up;
129 }
130
131 @Override
132 public void actionPerformed(ActionEvent e) {
133 int row = t.getSelectedRow();
134 int newRow = row + (moveUp ? -1 : 1);
135
136 if ((row == 0 || newRow == 0)
137 && (!ConditionalOptionPaneUtil.showConfirmationDialog(
138 "gpx_target_change",
139 parent,
140 new JLabel("<html>" +
141 tr("This will change the target layer to \"{0}\".<br>Would you like to continue?",
142 model.getValueAt(1, 0).toString()) + "</html>"),
143 tr("Information"),
144 JOptionPane.OK_CANCEL_OPTION,
145 JOptionPane.INFORMATION_MESSAGE,
146 JOptionPane.OK_OPTION))) {
147 return;
148 }
149
150 model.moveRow(row, newRow);
151 t.getSelectionModel().setSelectionInterval(newRow, newRow);
152 t.repaint();
153 }
154 }
155
156 private class RowSelectionChangedListener implements ListSelectionListener {
157
158 @Override
159 public void valueChanged(ListSelectionEvent e) {
160 btnUp.setEnabled(t.getSelectedRow() > 0);
161 btnDown.setEnabled(t.getSelectedRow() < model.getRowCount() - 1);
162 }
163 }
164
165 private static class GpxLayersTableModel extends AbstractTableModel {
166
167 private final String[] cols = {tr("GPX layer"), tr("Length"), tr("Segments")};
168 private final List<GpxLayer> layers;
169
170 GpxLayersTableModel(List<GpxLayer> l) {
171 layers = l;
172 }
173
174 @Override
175 public String getColumnName(int column) {
176 return cols[column];
177 }
178
179 @Override
180 public int getColumnCount() {
181 return cols.length;
182 }
183
184 @Override
185 public int getRowCount() {
186 return layers.size();
187
188 }
189
190 public void moveRow(int row, int newRow) {
191 Collections.swap(layers, row, newRow);
192 }
193
194 public List<GpxLayer> getSortedLayers() {
195 return layers;
196 }
197
198 @Override
199 public Object getValueAt(int row, int col) {
200 switch (col) {
201 case 0:
202 String n = layers.get(row).getName();
203 if (row == 0) {
204 return tr("{0} (target layer)", n);
205 } else {
206 return n;
207 }
208 case 1:
209 return SystemOfMeasurement.getSystemOfMeasurement().getDistText(layers.get(row).data.length());
210 case 2:
211 return layers.get(row).data.getTrackSegsCount();
212 }
213 throw new IndexOutOfBoundsException(Integer.toString(col));
214 }
215 }
216}
Note: See TracBrowser for help on using the repository browser.