]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/function/gpsies/GetGpsiesFunction.java
Version 8, September 2009
[GpsPrune.git] / tim / prune / function / gpsies / GetGpsiesFunction.java
1 package tim.prune.function.gpsies;
2
3 import java.awt.BorderLayout;
4 import java.awt.Component;
5 import java.awt.Dimension;
6 import java.awt.FlowLayout;
7 import java.awt.event.ActionEvent;
8 import java.awt.event.ActionListener;
9 import java.awt.event.WindowAdapter;
10 import java.awt.event.WindowEvent;
11 import java.io.IOException;
12 import java.net.URL;
13 import java.util.ArrayList;
14
15 import javax.swing.BorderFactory;
16 import javax.swing.JButton;
17 import javax.swing.JDialog;
18 import javax.swing.JLabel;
19 import javax.swing.JPanel;
20 import javax.swing.JScrollPane;
21 import javax.swing.JSplitPane;
22 import javax.swing.JTable;
23 import javax.swing.JTextArea;
24 import javax.swing.event.ListSelectionEvent;
25 import javax.swing.event.ListSelectionListener;
26 import javax.xml.parsers.SAXParser;
27 import javax.xml.parsers.SAXParserFactory;
28
29 import tim.prune.App;
30 import tim.prune.GenericFunction;
31 import tim.prune.I18nManager;
32 import tim.prune.function.browser.BrowserLauncher;
33 import tim.prune.load.xml.XmlFileLoader;
34 import tim.prune.load.xml.ZipFileLoader;
35
36 /**
37  * Function to load track information from Gpsies.com
38  * according to the currently viewed area
39  */
40 public class GetGpsiesFunction extends GenericFunction implements Runnable
41 {
42         /** Dialog object */
43         private JDialog _dialog = null;
44         /** list model */
45         private TrackListModel _trackListModel = null;
46         /** track table */
47         private JTable _trackTable = null;
48         /** Cancelled flag */
49         private boolean _cancelled = false;
50         /** Status label */
51         private JLabel _statusLabel = null;
52         /** Description box */
53         private JTextArea _descriptionBox = null;
54         /** Load button */
55         private JButton _loadButton = null;
56         /** Show button */
57         private JButton _showButton = null;
58         /** Number of results per page */
59         private static final int RESULTS_PER_PAGE = 20;
60         /** Maximum number of results to get */
61         private static final int MAX_RESULTS = 60;
62
63
64         /**
65          * Constructor
66          * @param inApp App object
67          */
68         public GetGpsiesFunction(App inApp)
69         {
70                 super(inApp);
71         }
72
73         /**
74          * @return name key
75          */
76         public String getNameKey() {
77                 return "function.getgpsies";
78         }
79
80         /**
81          * Begin the function
82          */
83         public void begin()
84         {
85                 // Initialise dialog, show empty list
86                 if (_dialog == null)
87                 {
88                         _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true);
89                         _dialog.setLocationRelativeTo(_parentFrame);
90                         _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
91                         // add closing listener
92                         _dialog.addWindowListener(new WindowAdapter() {
93                                 public void windowClosing(WindowEvent e) {
94                                         _cancelled = true;
95                                 }
96                         });
97                         _dialog.getContentPane().add(makeDialogComponents());
98                         _dialog.pack();
99                 }
100                 // Clear list
101                 _trackListModel.clear();
102                 _loadButton.setEnabled(false);
103                 _showButton.setEnabled(false);
104                 _cancelled = false;
105                 _descriptionBox.setText("");
106                 // Start new thread to load list asynchronously
107                 new Thread(this).start();
108
109                 // Show dialog
110                 _dialog.setVisible(true);
111         }
112
113
114         /**
115          * Create dialog components
116          * @return Panel containing all gui elements in dialog
117          */
118         private Component makeDialogComponents()
119         {
120                 JPanel dialogPanel = new JPanel();
121                 dialogPanel.setLayout(new BorderLayout());
122
123                 // Status label
124                 _statusLabel = new JLabel(I18nManager.getText("confirm.running"));
125                 dialogPanel.add(_statusLabel, BorderLayout.NORTH);
126                 // Main panel with track list
127                 _trackListModel = new TrackListModel();
128                 _trackTable = new JTable(_trackListModel);
129                 _trackTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
130                         public void valueChanged(ListSelectionEvent e) {
131                                 if (!e.getValueIsAdjusting())
132                                 {
133                                         if (_trackTable.getSelectedRow() >= 0
134                                          && _trackTable.getSelectedRow() < _trackListModel.getRowCount())
135                                         {
136                                                 _loadButton.setEnabled(true);
137                                                 _showButton.setEnabled(true);
138                                                 setDescription(_trackListModel.getTrack(_trackTable.getSelectedRow()).getDescription());
139                                                 _descriptionBox.setCaretPosition(0);
140                                         }
141                                         else {
142                                                 _descriptionBox.setText("");
143                                         }
144                                 }
145                         }
146                 });
147                 _trackTable.getColumnModel().getColumn(0).setPreferredWidth(300);
148                 _trackTable.getColumnModel().getColumn(1).setPreferredWidth(70);
149                 JScrollPane tablePane = new JScrollPane(_trackTable);
150                 tablePane.setPreferredSize(new Dimension(450, 200));
151                 // Panel to hold description label and box
152                 JPanel descPanel = new JPanel();
153                 descPanel.setLayout(new BorderLayout());
154                 JLabel descLabel = new JLabel(I18nManager.getText("dialog.gpsies.description") + " :");
155                 descPanel.add(descLabel, BorderLayout.NORTH);
156                 _descriptionBox = new JTextArea(5, 20);
157                 _descriptionBox.setEditable(false);
158                 _descriptionBox.setLineWrap(true);
159                 _descriptionBox.setWrapStyleWord(true);
160                 JScrollPane descPane = new JScrollPane(_descriptionBox);
161                 descPane.setPreferredSize(new Dimension(400, 80));
162                 descPanel.add(descPane, BorderLayout.CENTER);
163                 // Use split pane to split table from description
164                 JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, tablePane, descPanel);
165                 splitPane.setResizeWeight(1.0);
166                 dialogPanel.add(splitPane, BorderLayout.CENTER);
167
168                 // button panel at bottom
169                 JPanel buttonPanel = new JPanel();
170                 buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
171                 _loadButton = new JButton(I18nManager.getText("button.load"));
172                 _loadButton.setEnabled(false);
173                 _loadButton.addActionListener(new ActionListener() {
174                         public void actionPerformed(ActionEvent e)
175                         {
176                                 loadSelectedTrack();
177                         }
178                 });
179                 buttonPanel.add(_loadButton);
180                 _showButton = new JButton(I18nManager.getText("button.showwebpage"));
181                 _showButton.setEnabled(false);
182                 _showButton.addActionListener(new ActionListener() {
183                         public void actionPerformed(ActionEvent e)
184                         {
185                                 showSelectedTrack();
186                         }
187                 });
188                 buttonPanel.add(_showButton);
189                 JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
190                 cancelButton.addActionListener(new ActionListener() {
191                         public void actionPerformed(ActionEvent e)
192                         {
193                                 _cancelled = true;
194                                 _dialog.dispose();
195                         }
196                 });
197                 buttonPanel.add(cancelButton);
198                 dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
199                 dialogPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 15));
200                 return dialogPanel;
201         }
202
203         /**
204          * Set the description in the box
205          * @param inDesc description to set, or null for no description
206          */
207         private void setDescription(String inDesc)
208         {
209                 String text = inDesc;
210                 if (inDesc == null || inDesc.length() < 2) {
211                         text = I18nManager.getText("dialog.gpsies.nodescription");
212                 }
213                 _descriptionBox.setText(text);
214         }
215
216         /**
217          * Run method to call gpsies.com in separate thread
218          */
219         public void run()
220         {
221                 _statusLabel.setText(I18nManager.getText("confirm.running"));
222                 // Act on callback to update list and send another request if necessary
223                 double[] coords = _app.getViewport().getBounds();
224                 // Example http://www.gpsies.com/api.do?BBOX=10,51,12,53&limit=20&trackTypes=jogging&filetype=kml&device=Run.GPS
225                 int currPage = 1;
226
227                 ArrayList<GpsiesTrack> trackList = null;
228                 URL url = null;
229                 String descMessage = "";
230                 // Loop for each page of the results
231                 do
232                 {
233                         String urlString = "http://www.gpsies.com/api.do?BBOX=" +
234                                 coords[1] + "," + coords[0] + "," + coords[3] + "," + coords[2] +
235                                 "&limit=" + RESULTS_PER_PAGE + "&resultPage=" + currPage;
236                         // System.out.println(urlString);
237                         // Parse the returned XML with a special handler
238                         GpsiesXmlHandler xmlHandler = new GpsiesXmlHandler();
239                         try
240                         {
241                                 url = new URL(urlString);
242                                 SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
243                                 saxParser.parse(url.openStream(), xmlHandler);
244                         }
245                         catch (Exception e) {
246                                 descMessage = e.getClass().getName() + " - " + e.getMessage();
247                         }
248                         // TODO: Close streams somehow?  Haven't got a reference to the input stream to close it!
249                         // Add track list to model
250                         trackList = xmlHandler.getTrackList();
251                         _trackListModel.addTracks(trackList);
252
253                         // Compare number of results with results per page and call again if necessary
254                         currPage++;
255                 }
256                 while (trackList != null && trackList.size() == RESULTS_PER_PAGE
257                  && _trackListModel.getRowCount() < MAX_RESULTS && !_cancelled);
258                 // Set status label according to error or "none found", leave blank if ok
259                 if (descMessage.equals("") && (trackList == null || trackList.size() == 0)) {
260                         descMessage = I18nManager.getText("dialog.gpsies.nonefound");
261                 }
262                 _statusLabel.setText(descMessage);
263         }
264
265
266         /**
267          * Load the selected track
268          */
269         private void loadSelectedTrack()
270         {
271                 // Find the row selected in the table and get the corresponding track
272                 int rowNum = _trackTable.getSelectedRow();
273                 if (rowNum >= 0 && rowNum < _trackListModel.getRowCount())
274                 {
275                         String url = _trackListModel.getTrack(rowNum).getDownloadLink();
276                         XmlFileLoader xmlLoader = new XmlFileLoader(_app);
277                         ZipFileLoader loader = new ZipFileLoader(_app, xmlLoader);
278                         try
279                         {
280                                 loader.openStream(new URL(url).openStream());
281                         }
282                         catch (IOException ioe) {
283                                 System.err.println("IO Exception : " + ioe.getMessage());
284                         }
285                 }
286                 // Close the dialog
287                 _cancelled = true;
288                 _dialog.dispose();
289         }
290
291
292         /**
293          * Show the webpage for the selected track
294          */
295         private void showSelectedTrack()
296         {
297                 // Find the row selected in the table and show the corresponding url
298                 int rowNum = _trackTable.getSelectedRow();
299                 if (rowNum >= 0 && rowNum < _trackListModel.getRowCount())
300                 {
301                         String id = _trackListModel.getTrack(rowNum).getFileId();
302                         BrowserLauncher.launchBrowser("http://gpsies.com/map.do?fileId=" + id);
303                 }
304                 // Close the dialog
305                 _cancelled = true;
306                 _dialog.dispose();
307         }
308 }