1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package triptracker.client.gps.ui;
21
22 import java.awt.Dimension;
23 import java.awt.GridLayout;
24 import java.awt.event.ActionListener;
25 import java.awt.event.KeyEvent;
26 import java.io.IOException;
27
28 import javax.swing.AbstractButton;
29 import javax.swing.BorderFactory;
30 import javax.swing.ImageIcon;
31 import javax.swing.JButton;
32 import javax.swing.JComponent;
33 import javax.swing.JLabel;
34 import javax.swing.JOptionPane;
35 import javax.swing.JPanel;
36 import javax.swing.JSpinner;
37 import javax.swing.JTextField;
38 import javax.swing.SpinnerListModel;
39 import javax.swing.Timer;
40 import javax.swing.event.ChangeListener;
41
42 import triptracker.client.gps.core.GPSClientModel;
43 import triptracker.client.gps.core.GPSListener;
44 import triptracker.client.gps.core.GPSStatusState;
45 import triptracker.client.net.GPSSocketAdapter;
46 import triptracker.client.ui.Form;
47 import se.datadosen.component.RiverLayout;
48 import triptracker.core.ConnectionState;
49 import triptracker.core.Coordinate;
50 import triptracker.core.Utils;
51 import static triptracker.core.Utils.*;
52
53 public class MainForm extends GPSSocketAdapter implements Form, GPSListener {
54 protected final String name;
55 protected static int nameCount = 1;
56
57 private final GPSGui view;
58 private final GPSClientModel model;
59
60 private int numRecieved = 1;
61 private Timer timer;
62 private double distance;
63
64 private final JPanel mainPanel, centerPanel, centerBorderPanel,
65 buttonPanel, routePanel, routeBorderPanel;
66 protected final JButton gpsButton, serverButton;
67 private JTextField numCoordsField, coordLatField, coordLonField,
68 updateField, distField;
69 protected JSpinner intervalSpinner;
70 private JLabel activeRouteLabel;
71
72 private ImageIcon imgGPSOff = getImageIcon("gps_notRecieving_icon.gif");
73 private ImageIcon imgGPSOn = getImageIcon("gps_recieving_icon.gif");
74 private ImageIcon imgServer = getImageIcon("serverIcon.gif");
75 private ImageIcon imgBuffer = getImageIcon("bufferIcon.gif");
76
77 public MainForm(GPSGui view, GPSClientModel model) {
78 this(view, model, MainForm.class.getClass().getName() + "-"
79 + nameCount++);
80 }
81
82 public MainForm(GPSGui view, GPSClientModel model, String name) {
83 this.view = view;
84 this.model = model;
85 this.name = name;
86
87 numCoordsField = new JTextField("0 Coordinates", 10);
88 numCoordsField.setEditable(false);
89 coordLatField = new JTextField("None", 11);
90 coordLatField.setEditable(false);
91 coordLonField = new JTextField("None", 11);
92 coordLonField.setEditable(false);
93 updateField = new JTextField("None yet");
94 updateField.setEditable(false);
95 distField = new JTextField("Not started");
96 distField.setEditable(false);
97
98 String[] intervalList = { "2", "4", "6", "8", "10", "15", "20", "30",
99 "45", "60", "120", "180", "240", "300", "600", "900", "1800",
100 "3600", "7200"};
101 SpinnerListModel intervalModel = new SpinnerListModel(intervalList);
102 intervalSpinner = new JSpinner(intervalModel);
103
104 gpsButton = new JButton("Not started", imgGPSOff);
105 gpsButton.setVerticalTextPosition(AbstractButton.CENTER);
106 gpsButton.setHorizontalTextPosition(AbstractButton.LEFT);
107 gpsButton.setMnemonic(KeyEvent.VK_M);
108 gpsButton.setPreferredSize(new Dimension(150, 50));
109
110 serverButton = new JButton("Buffering", imgBuffer);
111 serverButton.setVerticalTextPosition(AbstractButton.CENTER);
112 serverButton.setHorizontalTextPosition(AbstractButton.RIGHT);
113 serverButton.setMnemonic(KeyEvent.VK_M);
114 serverButton.setPreferredSize(new Dimension(150, 50));
115
116 activeRouteLabel = new JLabel("No active route is set");
117
118 centerPanel = new JPanel();
119 centerPanel.setLayout(new GridLayout(0, 2));
120 centerPanel.setBorder(BorderFactory.createTitledBorder(null,
121 "Info from GPS-unit"));
122 centerPanel.add(new JLabel("Recieved: "));
123 centerPanel.add(numCoordsField);
124 centerPanel.add(new JLabel("Latitude: "));
125 centerPanel.add(coordLatField);
126 centerPanel.add(new JLabel("Longitude: "));
127 centerPanel.add(coordLonField);
128 centerPanel.add(new JLabel("Last update "));
129 centerPanel.add(updateField);
130 centerPanel.add(new JLabel("Total dist. "));
131 centerPanel.add(distField);
132
133 centerBorderPanel = new JPanel();
134 centerBorderPanel.setBorder(
135 BorderFactory.createEmptyBorder(10, 10, 10, 10));
136 centerBorderPanel.add(centerPanel);
137
138 routePanel = new JPanel();
139 routePanel.setBorder(BorderFactory.createTitledBorder(null,
140 "Active route and GPS-unit recieve interval"));
141 routePanel.setLayout(new GridLayout(2, 1));
142 routePanel.add(new JLabel("Active route: "));
143 routePanel.add(activeRouteLabel);
144 routePanel.add(new JLabel("Interval: "));
145 routePanel.add(intervalSpinner);
146
147 routeBorderPanel = new JPanel();
148 routeBorderPanel.setBorder(
149 BorderFactory.createEmptyBorder(10, 10, 10, 10));
150 routeBorderPanel.add(routePanel);
151
152 buttonPanel = new JPanel();
153 buttonPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 20, 0));
154 buttonPanel.add(gpsButton);
155 buttonPanel.add(serverButton);
156
157 mainPanel = new JPanel();
158 mainPanel.setLayout(new RiverLayout());
159 mainPanel.add("center", centerBorderPanel);
160 mainPanel.add("p center", routeBorderPanel);
161 mainPanel.add("p center", buttonPanel);
162
163 new MainFormController(model, this);
164 view.register(this);
165
166 model.addSocketListener(this);
167 model.addGPSListener(this);
168 }
169
170 /***
171 * Register a listener on the GPS button.
172 *
173 * @param listener
174 */
175 public void addGPSBtnListener(ActionListener listener) {
176 gpsButton.addActionListener(listener);
177 }
178
179 /***
180 * Adds an changelistener for the intervalspinner.
181 *
182 * @param listener
183 */
184 public void addSpinnerListener(ChangeListener listener) {
185 intervalSpinner.addChangeListener(listener);
186 }
187
188 /***
189 * Adds an actionlistener for the timer.
190 *
191 * @param listener
192 */
193 public void addTimerListener(ActionListener listener) {
194 timer.addActionListener(listener);
195 }
196
197 /***
198 * Register a listener on the Server button.
199 *
200 * @param listener
201 */
202 public void addServerBtnListener(ActionListener listener) {
203 serverButton.addActionListener(listener);
204 }
205
206 /***
207 * Gets the form's component
208 */
209 public JComponent getFormComponent() {
210 return mainPanel;
211 }
212
213 /***
214 * Gets the form name
215 */
216 public String getName() {
217 return name;
218 }
219
220 public void coordReceived(Coordinate coord) { }
221
222 /***
223 * Refreshes the form
224 */
225 public void refreshView() {
226
227 String r = model.getActiveRoute().getDescription();
228 int rLen = 20;
229
230 if (r != null) {
231 if (r.length() >= rLen) {
232 r = r.substring(0, rLen) + "..";
233 setActiveRoute(r);
234 }
235 setActiveRoute(r);
236 }
237
238
239 if (model.isLoggedIn()) {
240 view.enableLogOnItem(false);
241 view.enableRouteItem(true);
242 view.enableLogOffItem(true);
243 } else {
244 view.enableLogOffItem(false);
245 view.enableRouteItem(false);
246 view.enableLogOnItem(true);
247 }
248
249 if (model.getPort() == null || model.getPort().contains("NONE")) {
250 gpsButton.setEnabled(false);
251 setStatusMsg("No COM-ports found. Please restart.");
252 showErrorDialog("No COM ports found", "No COM ports was found.\n\n"
253 + "Please install COM-port,\nthen restart the application.",
254 getImageIcon("portIcon.gif"));
255 } else {
256 gpsButton.setEnabled(true);
257 setStatusMsg("Default port is set to " + model.getPort());
258 }
259
260 view.enableMenu(true);
261 if (model.hasActiveRoute()) {
262 System.out.println("transferring to server");
263 }
264
265 }
266
267 /***
268 * Shows an error dialog
269 *
270 * @param heading heading for the error
271 * @param error the error itself
272 * @param icon the icon for the error
273 */
274 private void showErrorDialog(String heading, String error, ImageIcon icon) {
275 view.showErrorDialog(heading, error, icon);
276 }
277
278 /***
279 * Gets the interval to get data from the GPS-unit
280 *
281 * @return interval to recieve data in secounds
282 */
283 public int getInterval() {
284 int interval = Integer.parseInt((String)intervalSpinner.getValue());
285 StringBuilder msg = new StringBuilder();
286 msg.append("Interval changed to ");
287
288 if ((interval % 60) == 0) {
289 msg.append(interval / 60);
290 if ((interval / 60) != 1 ) {
291 msg.append(" minutes.");
292 } else {
293 msg.append(" minute.");
294 }
295 } else {
296 msg.append(interval + " secounds.");
297 }
298 setStatusMsg(msg.toString());
299
300 return interval;
301 }
302
303 /***
304 * Set the status message on the status bar.
305 *
306 * @param status status message
307 */
308 public void setStatusMsg(String status) {
309 view.setStatusMsg(status);
310 }
311
312 /***
313 * Increases the number of recieved coordinates
314 *
315 */
316 public void increaseRecievedField() {
317 numCoordsField.setText(numRecieved++ + " Coordinates");
318 }
319
320 /***
321 * Sets the latitude / logitude fields
322 *
323 * @param lat the coordinate's latitude
324 * @param lon the coordinate's logitude
325 */
326 public void setLatLonFields(String lat, String lon) {
327 coordLatField.setText(lat);
328 coordLonField.setText(lon);
329 }
330
331 /***
332 * Sets the last updated field
333 *
334 * @param update last updated
335 */
336 public void setLastUpdateField(String update) {
337 updateField.setText(update);
338 }
339
340 public void statusUpdate(GPSStatusState state) {
341 switch (state) {
342 case CONNECTED:
343 timer.start();
344 System.out.println("Connected to GPS");
345 break;
346 case NOFIXEDPOS:
347 System.out.println("No fixed pos");
348 setLatLonFields("* No fixed pos *", "* No fixed pos *");
349 break;
350 case HASFIXEDPOS:
351 System.out.println("Has Fixed Pos");
352 break;
353 case NOTCONNECTED:
354 timer.stop();
355 System.out.println("Not connected");
356 break;
357 }
358 }
359
360 public void connected(boolean connected) { }
361
362 /***
363 * Creates a new timer
364 *
365 * @param listener the listener
366 */
367 public void createTimer(ActionListener listener) {
368 timer = new Timer(getInterval() * 1000, listener);
369 }
370
371 /***
372 * Changes the text on the serverButton.
373 *
374 * @param text the new text on the button
375 */
376 public void setServerBtnTxt(String text) {
377 serverButton.setText(text);
378 }
379
380 /***
381 * Changes the text on the gpsButton.
382 *
383 * @param text the new text on the button
384 */
385 public void setGPSBtnTxt(String text) {
386 gpsButton.setText(text);
387 }
388
389 /***
390 * Show main form.
391 */
392 public void showMain() {
393 view.showMainForm();
394 }
395
396 /***
397 * Shows an error dialog.
398 *
399 * @param heading heading of the error dialog
400 * @param error the error itself
401 */
402 public void showErrorDialog(String heading, String error) {
403 view.showErrorDialog(heading, error);
404 }
405
406 /***
407 * Get the current timer
408 *
409 * @return Returns the timer.
410 */
411 public Timer getTimer() {
412 return timer;
413 }
414
415 /***
416 * Shows the loginform.
417 */
418 public void showLogin() {
419 view.showLoginForm();
420 }
421
422 /***
423 * Stops the timer.
424 */
425 public void stopTimer() {
426 timer.stop();
427 }
428
429 /***
430 * Starts the timer.
431 */
432 public void startTimer() {
433 timer.start();
434 }
435
436 /***
437 * Checks wether the timer is running or not
438 *
439 * @return true if running
440 */
441 public boolean timerIsRunning() {
442 return timer.isRunning();
443 }
444
445 /***
446 * Show route form
447 */
448 public void showRoutes() {
449 view.showRoutesForm();
450
451 }
452
453 /***
454 * Creates a dialog for transfer buffered coordinates or not
455 *
456 * @return true if transfer
457 */
458 public boolean transferBufferedDialog() {
459 Object[] options = { "Continiue buffering", "Transfer buffered" };
460 int n = JOptionPane.showOptionDialog(null,
461 "Buffered coordinates exists, what would you like to do?",
462 "Buffered coordinates exists", JOptionPane.YES_NO_CANCEL_OPTION,
463 JOptionPane.QUESTION_MESSAGE, null, options, options[1]);
464 return (n == 0);
465 }
466
467 /***
468 * Sets the activeroute label
469 *
470 * @param route the active route
471 */
472 public void setActiveRoute(String route) {
473 activeRouteLabel.setText(route);
474 }
475
476 @Override
477 public void connectionUpdate(ConnectionState state) {
478 switch (state) {
479 case DISCONNECTED:
480 bufferToFile();
481 model.changeTransferState();
482 setStatusMsg("!!: Connection to server is lost.");
483 break;
484 case CONNECTED:
485 if (model.getActiveRoute().getRouteId() != -1
486 && model.isLoggedIn()) {
487 model.setActiveRoute(model.getActiveRoute());
488 setStatusMsg("Setting active route to "
489 + model.getActiveRoute().getRouteId() + " on server");
490 }
491 break;
492 }
493 }
494
495 /***
496 * Transferring to server, changes status message,
497 * text on server button and the server button icon
498 * to transfer mode.
499 */
500 public void transferToServer() {
501 setStatusMsg("Transferring to server ..");
502 setServerBtnTxt("Transferring");
503 serverButton.setIcon(imgServer);
504 }
505
506 /***
507 * Changes the text and icon on the GPS button to recieve mode, also changes
508 * the status msg.
509 */
510 public void recieveFromGPS() {
511 setGPSBtnTxt("Recieving");
512 gpsButton.setIcon(imgGPSOn);
513 setStatusMsg("Recieving from GPS-unit.");
514 }
515
516 /***
517 * Changes the text and icon on the GPS button to pause mode, also changes
518 * the status msg.
519 */
520 public void pauseFromGPS() {
521 stopTimer();
522 setStatusMsg("Recieving from GPS-unit is paused.");
523 setGPSBtnTxt("Paused");
524 gpsButton.setIcon(imgGPSOff);
525 }
526
527 /***
528 * Changes the text and icon on the server
529 * button to buffer mode, also changes the
530 * status msg.
531 */
532 public void bufferToFile() {
533 setStatusMsg("Buffering to file ..");
534 setServerBtnTxt("Buffering");
535 serverButton.setIcon(imgBuffer);
536 }
537
538 /***
539 * Handles an read exception when trying to read
540 * data from the GPS-unit
541 */
542 public void readExcepion(IOException e) {
543 view.setStatusMsg("!!: Problems reading from the GPS");
544 System.out.println("readException: " + e);
545 }
546
547 /***
548 * Sets the distance field.
549 *
550 * @param dist traveled distance
551 */
552 public void setDistField(double dist) {
553 distance += dist;
554 if (distance > 1) {
555 distField.setText(Utils.round(distance, 3) + " km");
556 } else {
557 distField.setText(Utils.round(distance * 1000, 0) + " m");
558 }
559 }
560 }