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

Last change on this file since 5715 was 5715, checked in by akks, 11 years ago

see #8416. GpxLayer refactoring: inner classes goes to org.openstreetmap.josm.gui.layer.gpx
Any change of behavior is a bug!

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