source: josm/trunk/src/org/openstreetmap/josm/gui/layer/gpx/ChooseTrackVisibilityAction.java@ 6070

Last change on this file since 6070 was 6070, checked in by stoecker, 11 years ago

see #8853 remove tabs, trailing spaces, windows line ends, strange characters

File size: 9.7 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.layer.gpx;
3
4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
5import static org.openstreetmap.josm.tools.I18n.tr;
6
7import java.awt.Component;
8import java.awt.Dimension;
9import java.awt.GridBagLayout;
10import java.awt.event.ActionEvent;
11import java.awt.event.ActionListener;
12import java.awt.event.MouseAdapter;
13import java.awt.event.MouseEvent;
14import java.awt.event.MouseListener;
15import java.util.Map;
16
17import javax.swing.AbstractAction;
18import javax.swing.JComponent;
19import javax.swing.JLabel;
20import javax.swing.JPanel;
21import javax.swing.JScrollPane;
22import javax.swing.JTable;
23import javax.swing.JToggleButton;
24import javax.swing.ListSelectionModel;
25import javax.swing.event.ListSelectionEvent;
26import javax.swing.event.ListSelectionListener;
27import javax.swing.table.TableCellRenderer;
28
29import org.openstreetmap.josm.Main;
30import org.openstreetmap.josm.data.gpx.GpxTrack;
31import org.openstreetmap.josm.gui.ExtendedDialog;
32import org.openstreetmap.josm.gui.NavigatableComponent;
33import org.openstreetmap.josm.gui.layer.GpxLayer;
34import org.openstreetmap.josm.tools.GBC;
35import org.openstreetmap.josm.tools.ImageProvider;
36import org.openstreetmap.josm.tools.OpenBrowser;
37import org.openstreetmap.josm.tools.WindowGeometry;
38
39/**
40 * allows the user to choose which of the downloaded tracks should be displayed.
41 * they can be chosen from the gpx layer context menu.
42 */
43public class ChooseTrackVisibilityAction extends AbstractAction {
44 private final GpxLayer layer;
45
46 DateFilterPanel dateFilter;
47 JTable table;
48
49 public ChooseTrackVisibilityAction(final GpxLayer layer) {
50 super(tr("Choose visible tracks"), ImageProvider.get("dialogs/filter"));
51 this.layer = layer;
52 putValue("help", ht("/Action/ChooseTrackVisibility"));
53 }
54
55 /**
56 * gathers all available data for the tracks and returns them as array of arrays
57 * in the expected column order */
58 private Object[][] buildTableContents() {
59 Object[][] tracks = new Object[layer.data.tracks.size()][5];
60 int i = 0;
61 for (GpxTrack trk : layer.data.tracks) {
62 Map<String, Object> attr = trk.getAttributes();
63 String name = (String) (attr.containsKey("name") ? attr.get("name") : "");
64 String desc = (String) (attr.containsKey("desc") ? attr.get("desc") : "");
65 String time = GpxLayer.getTimespanForTrack(trk);
66 String length = NavigatableComponent.getSystemOfMeasurement().getDistText(trk.length());
67 String url = (String) (attr.containsKey("url") ? attr.get("url") : "");
68 tracks[i] = new String[]{name, desc, time, length, url};
69 i++;
70 }
71 return tracks;
72 }
73
74 /**
75 * Builds an non-editable table whose 5th column will open a browser when double clicked.
76 * The table will fill its parent. */
77 private JTable buildTable(Object[][] content) {
78 final String[] headers = {tr("Name"), tr("Description"), tr("Timespan"), tr("Length"), tr("URL")};
79 final JTable t = new JTable(content, headers) {
80 @Override
81 public Component prepareRenderer(TableCellRenderer renderer, int row, int col) {
82 Component c = super.prepareRenderer(renderer, row, col);
83 if (c instanceof JComponent) {
84 JComponent jc = (JComponent) c;
85 jc.setToolTipText((String) getValueAt(row, col));
86 }
87 return c;
88 }
89
90 @Override
91 public boolean isCellEditable(int rowIndex, int colIndex) {
92 return false;
93 }
94 };
95 // default column widths
96 t.getColumnModel().getColumn(0).setPreferredWidth(220);
97 t.getColumnModel().getColumn(1).setPreferredWidth(300);
98 t.getColumnModel().getColumn(2).setPreferredWidth(200);
99 t.getColumnModel().getColumn(3).setPreferredWidth(50);
100 t.getColumnModel().getColumn(4).setPreferredWidth(100);
101 // make the link clickable
102 final MouseListener urlOpener = new MouseAdapter() {
103 @Override
104 public void mouseClicked(MouseEvent e) {
105 if (e.getClickCount() != 2) {
106 return;
107 }
108 JTable t = (JTable) e.getSource();
109 int col = t.convertColumnIndexToModel(t.columnAtPoint(e.getPoint()));
110 if (col != 4) {
111 return;
112 }
113 int row = t.rowAtPoint(e.getPoint());
114 String url = (String) t.getValueAt(row, col);
115 if (url == null || url.isEmpty()) {
116 return;
117 }
118 OpenBrowser.displayUrl(url);
119 }
120 };
121 t.setAutoCreateRowSorter(true);
122 t.addMouseListener(urlOpener);
123 t.setFillsViewportHeight(true);
124 return t;
125 }
126
127 boolean noUpdates=false;
128
129 /** selects all rows (=tracks) in the table that are currently visible on the layer*/
130 private void selectVisibleTracksInTable() {
131 // don't select any tracks if the layer is not visible
132 if (!layer.isVisible()) {
133 return;
134 }
135 ListSelectionModel s = table.getSelectionModel();
136 s.clearSelection();
137 for (int i = 0; i < layer.trackVisibility.length; i++) {
138 if (layer.trackVisibility[i]) {
139 s.addSelectionInterval(i, i);
140 }
141 }
142 }
143
144 /** listens to selection changes in the table and redraws the map */
145 private void listenToSelectionChanges() {
146 table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
147 @Override
148 public void valueChanged(ListSelectionEvent e) {
149 if (noUpdates || !(e.getSource() instanceof ListSelectionModel)) {
150 return;
151 }
152 updateVisibilityFromTable();
153 }
154 });
155 }
156
157 private void updateVisibilityFromTable() {
158 ListSelectionModel s = (ListSelectionModel) table.getSelectionModel();
159 for (int i = 0; i < layer.trackVisibility.length; i++) {
160 layer.trackVisibility[table.convertRowIndexToModel(i)] = s.isSelectedIndex(i);
161 }
162 Main.map.mapView.preferenceChanged(null);
163 Main.map.repaint(100);
164 }
165
166 @Override
167 public void actionPerformed(ActionEvent arg0) {
168 final JPanel msg = new JPanel(new GridBagLayout());
169
170 dateFilter = new DateFilterPanel(layer, "gpx.traces", false);
171 dateFilter.setFilterAppliedListener(new ActionListener(){
172 @Override public void actionPerformed(ActionEvent e) {
173 noUpdates = true;
174 selectVisibleTracksInTable();
175 noUpdates = false;
176 Main.map.mapView.preferenceChanged(null);
177 Main.map.repaint(100);
178 }
179 });
180 dateFilter.loadFromPrefs();
181
182 final JToggleButton b = new JToggleButton(new AbstractAction(tr("Select by date")) {
183 @Override public void actionPerformed(ActionEvent e) {
184 if (((JToggleButton) e.getSource()).isSelected()) {
185 dateFilter.setEnabled(true);
186 dateFilter.applyFilter();
187 } else {
188 dateFilter.setEnabled(false);
189 }
190 }
191 });
192 dateFilter.setEnabled(false);
193 msg.add(b, GBC.std().insets(0,0,5,0));
194 msg.add(dateFilter, GBC.eol().insets(0,0,10,0).fill(GBC.HORIZONTAL));
195
196 msg.add(new JLabel(tr("<html>Select all tracks that you want to be displayed. You can drag select a " + "range of tracks or use CTRL+Click to select specific ones. The map is updated live in the " + "background. Open the URLs by double clicking them.</html>")), GBC.eop().fill(GBC.HORIZONTAL));
197 // build table
198 final boolean[] trackVisibilityBackup = layer.trackVisibility.clone();
199 table = buildTable(buildTableContents());
200 selectVisibleTracksInTable();
201 listenToSelectionChanges();
202 // make the table scrollable
203 JScrollPane scrollPane = new JScrollPane(table);
204 msg.add(scrollPane, GBC.eol().fill(GBC.BOTH));
205
206 // build dialog
207 ExtendedDialog ed = new ExtendedDialog(Main.parent, tr("Set track visibility for {0}", layer.getName()), new String[]{tr("Show all"), tr("Show selected only"), tr("Cancel")});
208 ed.setButtonIcons(new String[]{"dialogs/layerlist/eye", "dialogs/filter", "cancel"});
209 ed.setContent(msg, false);
210 ed.setDefaultButton(2);
211 ed.setCancelButton(3);
212 ed.configureContextsensitiveHelp("/Action/ChooseTrackVisibility", true);
213 ed.setRememberWindowGeometry(getClass().getName() + ".geometry", WindowGeometry.centerInWindow(Main.parent, new Dimension(1000, 500)));
214 ed.showDialog();
215 dateFilter.saveInPrefs();
216 int v = ed.getValue();
217 // cancel for unknown buttons and copy back original settings
218 if (v != 1 && v != 2) {
219 for (int i = 0; i < layer.trackVisibility.length; i++) {
220 layer.trackVisibility[i] = trackVisibilityBackup[i];
221 }
222 Main.map.repaint();
223 return;
224 }
225 // set visibility (1 = show all, 2 = filter). If no tracks are selected
226 // set all of them visible and...
227 ListSelectionModel s = table.getSelectionModel();
228 final boolean all = v == 1 || s.isSelectionEmpty();
229 for (int i = 0; i < layer.trackVisibility.length; i++) {
230 layer.trackVisibility[table.convertRowIndexToModel(i)] = all || s.isSelectedIndex(i);
231 }
232 // ...sync with layer visibility instead to avoid having two ways to hide everything
233 layer.setVisible(v == 1 || !s.isSelectionEmpty());
234
235 Main.map.mapView.preferenceChanged(null);
236 Main.map.repaint();
237 }
238
239}
Note: See TracBrowser for help on using the repository browser.