/[projects]/android/TrainInfo/src/dk/thoerup/traininfo/DepartureList.java
ViewVC logotype

Contents of /android/TrainInfo/src/dk/thoerup/traininfo/DepartureList.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1562 - (show annotations) (download)
Fri Jul 8 16:26:09 2011 UTC (12 years, 10 months ago) by torben
File size: 19808 byte(s)
Flesh out all logic from TrainInfoCommon so it just contains simple beans
1 package dk.thoerup.traininfo;
2
3 import static dk.thoerup.traininfo.R.string.departurelist_fetcharrivals;
4 import static dk.thoerup.traininfo.R.string.departurelist_fetchdepartures;
5 import static dk.thoerup.traininfo.R.string.generic_cancel;
6 import static dk.thoerup.traininfo.R.string.generic_retry;
7
8 import java.text.NumberFormat;
9
10 import android.app.AlertDialog;
11 import android.app.Dialog;
12 import android.app.ListActivity;
13 import android.app.ProgressDialog;
14 import android.content.ActivityNotFoundException;
15 import android.content.DialogInterface;
16 import android.content.Intent;
17 import android.content.SharedPreferences;
18 import android.graphics.Typeface;
19 import android.net.Uri;
20 import android.os.AsyncTask;
21 import android.os.Bundle;
22 import android.preference.PreferenceManager;
23 import android.util.Log;
24 import android.view.Menu;
25 import android.view.MenuItem;
26 import android.view.View;
27 import android.view.View.OnClickListener;
28 import android.widget.Button;
29 import android.widget.ListView;
30 import android.widget.TableLayout;
31 import android.widget.TableRow;
32 import android.widget.TextView;
33 import android.widget.Toast;
34 import dk.thoerup.android.traininfo.common.DepartureBean;
35 import dk.thoerup.android.traininfo.common.DepartureEntry;
36 import dk.thoerup.android.traininfo.common.MetroBean;
37 import dk.thoerup.android.traininfo.common.MetroBean.MetroEntry;
38 import dk.thoerup.android.traininfo.common.StationEntry;
39 import dk.thoerup.traininfo.provider.DepartureProvider;
40 import dk.thoerup.traininfo.provider.MetroProvider;
41 import dk.thoerup.traininfo.provider.ProviderFactory;
42 import dk.thoerup.traininfo.util.MessageBox;
43 import dk.thoerup.traininfo.util.StationEntryCsv;
44
45 public class DepartureList extends ListActivity {
46
47 public static final int DLG_PROGRESS = 1;
48 static final int MENU_MAP = 100;
49 static final int MENU_NOTIFICATIONS = 101;
50 static final int MENU_METROMAP = 102;
51 static final int MENU_TOGGLEDETAILS= 103;
52
53
54 DepartureListAdapter adapter;
55 DepartureProvider provider;
56 DepartureBean departures;
57
58 MetroBean metroBean;
59 MetroProvider metro;
60
61 int selectedItemId;
62 //DepartureBean currentDeparture;
63
64 ProgressDialog pgDialog;
65
66 DepartureFetcher fetcher;
67 MetroFetcher metroFetcher;
68
69 StationEntry station;
70
71 String trainType = "REGIONAL";
72
73 boolean arrival = false;
74
75 int commFailCounter = 0;
76
77 @Override
78 protected void onCreate(Bundle savedInstanceState) {
79 super.onCreate(savedInstanceState);
80 setContentView(R.layout.departurelist);
81
82 adapter = new DepartureListAdapter(this);
83 setListAdapter(adapter);
84
85 Intent launchedBy = getIntent();
86
87 station = (StationEntry) launchedBy.getSerializableExtra("stationbean");
88
89 ((TextView) findViewById(R.id.stationName)).setText( station.getName() );
90
91
92 ((TextView) findViewById(R.id.stationAddr)).setText( station.getAddress() );
93
94 final Button departureBtn = (Button) findViewById(R.id.departurebtn);
95 final Button arrivalBtn = (Button) findViewById(R.id.arrivalbtn);
96 final Button metroBtn = (Button) findViewById(R.id.metrobtn);
97 final Button regionalBtn = (Button) findViewById(R.id.regionalbtn);
98 final Button stogBtn = (Button) findViewById(R.id.stogbtn);
99
100 final View metroView = findViewById(R.id.metroonly);
101
102 departureBtn.setOnClickListener( new OnClickListener() {
103 @Override
104 public void onClick(View arg0) {
105 arrivalBtn.setBackgroundResource(R.drawable.custom_button);
106 departureBtn.setBackgroundResource(R.drawable.custom_button_hilight);
107 metroBtn.setBackgroundResource(R.drawable.custom_button);
108
109 getListView().setVisibility( View.VISIBLE );
110 metroView.setVisibility( View.GONE );
111 arrival = false;
112 startDepartureFetcher();
113 }
114 });
115 arrivalBtn.setOnClickListener( new OnClickListener() {
116 @Override
117 public void onClick(View arg0) {
118 arrivalBtn.setBackgroundResource(R.drawable.custom_button_hilight);
119 departureBtn.setBackgroundResource(R.drawable.custom_button);
120 metroBtn.setBackgroundResource(R.drawable.custom_button);
121
122 getListView().setVisibility( View.VISIBLE );
123 metroView.setVisibility( View.GONE );
124 arrival = true;
125 startDepartureFetcher();
126 }
127 });
128
129 regionalBtn.setOnClickListener( new OnClickListener() {
130 @Override
131 public void onClick(View arg0) {
132 regionalBtn.setBackgroundResource(R.drawable.custom_button_hilight);
133 stogBtn.setBackgroundResource(R.drawable.custom_button);
134 metroBtn.setBackgroundResource(R.drawable.custom_button);
135
136 departureBtn.setVisibility( View.VISIBLE );
137 arrivalBtn.setVisibility( View.VISIBLE );
138
139 getListView().setVisibility( View.VISIBLE );
140 metroView.setVisibility( View.GONE );
141 trainType = "REGIONAL";
142 startDepartureFetcher();
143 }
144 });
145 stogBtn.setOnClickListener( new OnClickListener() {
146 @Override
147 public void onClick(View arg0) {
148 regionalBtn.setBackgroundResource(R.drawable.custom_button);
149 stogBtn.setBackgroundResource(R.drawable.custom_button_hilight);
150 metroBtn.setBackgroundResource(R.drawable.custom_button);
151
152
153 departureBtn.setVisibility( View.VISIBLE );
154 arrivalBtn.setVisibility( View.VISIBLE );
155
156 getListView().setVisibility( View.VISIBLE );
157 metroView.setVisibility( View.GONE );
158 trainType = "STOG";
159 startDepartureFetcher();
160 }
161 });
162
163
164
165 metroBtn.setOnClickListener( new OnClickListener() {
166 @Override
167 public void onClick(View v) {
168 regionalBtn.setBackgroundResource(R.drawable.custom_button);
169 stogBtn.setBackgroundResource(R.drawable.custom_button);
170 metroBtn.setBackgroundResource(R.drawable.custom_button_hilight);
171
172 departureBtn.setVisibility( View.GONE );
173 arrivalBtn.setVisibility( View.GONE );
174
175 getListView().setVisibility( View.GONE );
176 metroView.setVisibility( View.VISIBLE );
177 startMetroFetcher();
178 }
179 });
180
181
182
183
184 // findViewById(R.id.header).setOnClickListener( mapLauncher );
185
186 int distance = station.getCalcdist();
187 if (distance != 0) {
188 NumberFormat format = NumberFormat.getNumberInstance();
189 format.setMaximumFractionDigits(1);
190 format.setMinimumFractionDigits(1);
191
192 ((TextView) findViewById(R.id.stationDistance)).setText( format.format((double)distance/1000.0) + " km." );
193 } else {
194 ((TextView) findViewById(R.id.stationDistance)).setVisibility(View.GONE);
195 }
196
197 ProviderFactory.purgeOldEntries(); //cleanup before fetching more data
198
199 Log.e("Station", StationEntryCsv.toCSV(station) );
200
201
202
203 if (station.isMetro() == false) {
204 metroBtn.setVisibility( View.GONE );
205 }
206
207 metro = ProviderFactory.getMetroProvider();
208
209 if (station.isRegional() == false ) {
210 regionalBtn.setVisibility(View.GONE);
211 }
212
213 if (station.isStrain() == false ) {
214 stogBtn.setVisibility(View.GONE);
215 }
216
217 if (station.isRegional() == true && station.isStrain() == false ) {
218 if ( station.isMetro() == false )
219 regionalBtn.setVisibility(View.GONE);
220 trainType = "REGIONAL";
221 }
222
223 if (station.isRegional() == false && station.isStrain() == true) {
224 if (station.isMetro() == false)
225 stogBtn.setVisibility(View.GONE);
226
227 stogBtn.setBackgroundResource(R.drawable.custom_button_hilight);
228 trainType = "STOG";
229
230 }
231 //Both enabled - use preferred from preferences
232 if (station.isRegional() == true && station.isStrain() == true ) {
233 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
234 trainType = prefs.getString("traintype", "REGIONAL"); //default value is gps
235
236 if (trainType.equals("STOG") ) {
237 stogBtn.setBackgroundResource(R.drawable.custom_button_hilight);
238 regionalBtn.setBackgroundResource(R.drawable.custom_button);
239 }
240 }
241
242
243 if (station.isRegional() == false && station.isStrain() == false) {
244 getListView().setVisibility( View.GONE );
245 metroView.setVisibility( View.VISIBLE );
246
247 departureBtn.setVisibility( View.GONE );
248 arrivalBtn.setVisibility(View.GONE);
249 metroBtn.setVisibility( View.GONE );
250
251
252
253 if (savedInstanceState == null) {
254 startMetroFetcher();
255 } else {
256 metroBean = (MetroBean) savedInstanceState.getSerializable("metro");
257 loadMetroData();
258 }
259
260 } else {
261 provider = ProviderFactory.getDepartureProvider();
262
263 if (savedInstanceState == null) {
264 startDepartureFetcher();
265 } else {
266 departures = (DepartureBean) savedInstanceState.getSerializable("departures");
267
268 if ( (departures != null) && (departures.entries != null) ) {
269 adapter.setDepartures(departures.entries);
270 }
271 selectedItemId = savedInstanceState.getInt("selectedItemId");
272
273 if ( hasNotifications() ) {
274 findViewById(R.id.notifIcon).setVisibility(View.VISIBLE);
275 }
276
277 }
278 }
279 }
280
281
282
283 boolean hasNotifications() {
284 return (departures != null && departures.notifications.size() > 0);
285 }
286
287 @Override
288 public void onSaveInstanceState(Bundle outState)
289 {
290 if (pgDialog != null && pgDialog.isShowing())
291 dismissDialog(DLG_PROGRESS);
292
293 outState.putInt("selectedItemId", selectedItemId);
294
295 outState.putSerializable("departures", departures);
296 outState.putSerializable("metro", metroBean);
297 }
298
299
300
301 @Override
302 protected void onDestroy() {
303 super.onDestroy();
304
305 if (fetcher != null) {
306 fetcher.cancel(true);
307 }
308
309 if (metroFetcher != null) {
310 metroFetcher.cancel(true);
311 }
312 }
313
314 @Override
315 protected void onListItemClick(ListView l, View v, int position, long id) {
316 super.onListItemClick(l, v, position, id);
317
318 //how can this happen ??
319 if (departures == null || departures.entries == null || departures.entries.size() == 0) {
320 Toast.makeText(this, "No departures in list ?!?", Toast.LENGTH_LONG).show(); //TODO: translate
321 return;
322 }
323
324 selectedItemId = position;
325
326 DepartureEntry dep = departures.entries.get(selectedItemId);
327
328 Intent intent = new Intent(this, TimetableList.class);
329 intent.putExtra("departure", dep);
330
331 startActivity(intent);
332
333 }
334
335
336 @Override
337 protected void onPrepareDialog(int id, Dialog dialog) {
338 super.onPrepareDialog(id, dialog);
339
340 switch (id) {
341 case DLG_PROGRESS:
342 pgDialog = (ProgressDialog) dialog;
343 int messageId = arrival == false ? departurelist_fetchdepartures : departurelist_fetcharrivals;
344 pgDialog.setMessage( getString(messageId) );
345 break;
346 }
347 }
348
349 @Override
350 protected Dialog onCreateDialog(int id) {
351 switch (id) {
352 case DLG_PROGRESS:
353
354 ProgressDialog dlg = new ProgressDialog(this);
355 dlg.setCancelable(true);
356 return dlg;
357 default:
358 return super.onCreateDialog(id);
359 }
360 }
361
362
363
364 @Override
365 public boolean onPrepareOptionsMenu(Menu menu) {
366 super.onPrepareOptionsMenu(menu);
367
368 MenuItem item = menu.findItem( MENU_NOTIFICATIONS );
369 boolean notifEnabled = hasNotifications();
370 item.setEnabled(notifEnabled);
371
372 return true;
373 }
374
375 @Override
376 public boolean onCreateOptionsMenu(Menu menu) {
377 MenuItem item;
378
379
380 item = menu.add(0, MENU_TOGGLEDETAILS, 0, getString(R.string.departurelist_toggledetails));
381 item.setIcon(android.R.drawable.ic_menu_view);
382
383 item = menu.add(0, MENU_MAP, 0, getString(R.string.departurelist_showonmap) );
384 item.setIcon(android.R.drawable.ic_menu_mapmode);
385
386 item = menu.add(0, MENU_NOTIFICATIONS, 0, getString(R.string.departurelist_notifications) );
387 item.setIcon(android.R.drawable.ic_menu_info_details);
388
389 boolean notifEnabled = hasNotifications();
390 item.setEnabled(notifEnabled);
391
392 if (station.isMetro()) {
393 item = menu.add(0, MENU_METROMAP, 0, "Metro" ); //TODO:translate!?!
394 item.setIcon(android.R.drawable.ic_menu_mapmode);
395 }
396
397 return true;
398 }
399
400 @Override
401 public boolean onOptionsItemSelected(MenuItem item) {
402 boolean res = true;
403 switch(item.getItemId()) {
404 case MENU_MAP:
405 Uri uri = Uri.parse("geo:" + station.getLatitude() + "," + station.getLongitude() + "?z=16");
406
407 try {
408 startActivity( new Intent(Intent.ACTION_VIEW, uri));
409 } catch (ActivityNotFoundException anfe) {
410 Toast.makeText(this, "Could not launch google maps", Toast.LENGTH_LONG).show();
411 }
412
413 break;
414 case MENU_NOTIFICATIONS:
415 Intent i = new Intent(this,dk.thoerup.traininfo.NotificationList.class);
416 i.putExtra(NotificationList.EXTRA_NOTIFICATIONS, departures.notifications);
417 startActivity(i);
418 break;
419 case MENU_METROMAP:
420 Intent metroMap = new Intent(this,dk.thoerup.traininfo.MetroMap.class);
421 startActivity(metroMap);
422 break;
423 case MENU_TOGGLEDETAILS:
424 adapter.toggleShowDetails();
425 break;
426 default:
427 res = super.onOptionsItemSelected(item);
428 }
429 return res;
430 }
431
432 void startDepartureFetcher() {
433 showDialog(DLG_PROGRESS);
434 fetcher = new DepartureFetcher();
435 fetcher.execute(station.getId());
436 }
437
438 void startMetroFetcher() {
439 showDialog(DLG_PROGRESS);
440 metroFetcher = new MetroFetcher();
441 metroFetcher.execute(station.getId());
442 }
443
444 class DialogDismisser implements View.OnClickListener {
445
446 Dialog dlg;
447 public DialogDismisser(Dialog d) {
448 dlg = d;
449 }
450
451 @Override
452 public void onClick(View v) {
453 if (dlg.isShowing())
454 dlg.dismiss();
455 }
456 }
457
458 /*View.OnClickListener mapLauncher = new View.OnClickListener() {
459 @Override
460 public void onClick(View v) {
461 Uri uri = Uri.parse("geo:" + station.getLatitude() + "," + station.getLongitude());
462 startActivity( new Intent(Intent.ACTION_VIEW, uri));
463 }
464 };*/
465
466
467
468 class DepartureFetcher extends AsyncTask<Integer, Void, Void> {
469
470 @Override
471 protected void onPostExecute(Void result) {
472 super.onPostExecute(result);
473
474
475 pgDialog.dismiss();
476
477 if (departures != null && departures.errorCode == null) {
478 commFailCounter = 0;
479 DepartureList.this.getListView().setVisibility(View.GONE); //Experimental, inspired by http://osdir.com/ml/Android-Developers/2010-04/msg01198.html
480 adapter.setDepartures(departures.entries);
481 DepartureList.this.getListView().setVisibility(View.VISIBLE);
482
483
484 // handle notification icon.
485 View notifIcon = findViewById(R.id.notifIcon);
486 if ( hasNotifications() ) {
487 notifIcon.setVisibility(View.VISIBLE);
488 notifIcon.setClickable(true);
489 notifIcon.setOnClickListener( new View.OnClickListener() {
490 @Override
491 public void onClick(View v) {
492 Intent i = new Intent(DepartureList.this, dk.thoerup.traininfo.NotificationList.class);
493 i.putExtra(NotificationList.EXTRA_NOTIFICATIONS, departures.notifications);
494 startActivity(i);
495 }
496 });
497 } else {
498 notifIcon.setVisibility(View.INVISIBLE);
499 }
500
501 if (departures.entries.size() == 0) {
502 int msgId = (arrival==false) ? R.string.departurelist_nodepartures : R.string.departurelist_noarrivals;
503 MessageBox.showMessage(DepartureList.this, getString(msgId), false);
504 }
505 } else { // communication or parse error
506 commFailCounter++;
507 AlertDialog.Builder builder = new AlertDialog.Builder(DepartureList.this);
508
509 if (departures != null && departures.errorCode != null ) { //got an error xml back
510 commFailCounter = 10;
511 builder.setMessage( getString(R.string.no_backend) );
512 } else {
513 builder.setMessage( getString(R.string.departurelist_fetcherror) );
514 }
515 builder.setCancelable(true);
516
517 if (commFailCounter < 3) {
518 builder.setPositiveButton(getString(generic_retry), new DialogInterface.OnClickListener() {
519 public void onClick(DialogInterface dialog, int id) {
520 dialog.dismiss();
521 startDepartureFetcher();
522
523 }
524 });
525 }
526 builder.setNegativeButton(getString(generic_cancel), new DialogInterface.OnClickListener() {
527 public void onClick(DialogInterface dialog, int id) {
528 dialog.dismiss();
529 DepartureList.this.finish();
530 }
531 });
532
533 try { //TODO: is this still necessary after the 0.9.4.1 fix ?
534 builder.show();
535 } catch (android.view.WindowManager.BadTokenException e) {
536 Log.i("DepartureList", "BadTokenException"); // this can happen if the user switched away from this activity, while doInBackground was running
537 }
538 }
539 }
540
541 @Override
542 protected Void doInBackground(Integer... params) {
543 departures = provider.lookupDepartures(params[0], DepartureList.this.arrival, trainType);
544 return null;
545 }
546
547 }
548
549 public void loadMetroData() {
550 ((TextView) findViewById(R.id.operations)).setText( metroBean.operationInfo );
551 ((TextView) findViewById(R.id.plan)).setText( metroBean.plan );
552
553
554 TableLayout table = (TableLayout) findViewById(R.id.metrotable);
555 table.removeAllViews();
556
557 TableRow head = new TableRow(this);
558
559 TextView h1 = new TextView(this);
560 h1.setText("Metro");
561 h1.setTextSize(16);
562 h1.setTypeface( Typeface.defaultFromStyle(Typeface.BOLD));
563
564
565 TableRow.LayoutParams params = new TableRow.LayoutParams();
566 params.span = 2;
567 head.addView(h1, params);
568
569
570
571 TextView h2 = new TextView(this);
572 h2.setTextSize(16);
573 h2.setTypeface( Typeface.defaultFromStyle(Typeface.BOLD));
574 h2.setText("Om minutter");
575
576 params = new TableRow.LayoutParams();
577 params.weight = 2;
578 head.addView(h2,params);
579
580
581
582 table.addView(head);
583
584 for (MetroEntry entry : metroBean.entries) {
585 TableRow row = new TableRow(this);
586
587 Log.e("Test", "" + entry.destination);
588
589 TextView v1 = new TextView(this);
590 v1.setTextSize(16);
591 v1.setText( entry.metro );
592 row.addView(v1);
593
594 TextView v2 = new TextView(this);
595 v2.setTextSize(16);
596 v2.setText( entry.destination );
597 row.addView(v2);
598
599 TextView v3 = new TextView(this);
600 v3.setTextSize(16);
601 v3.setText( entry.minutes );
602 row.addView(v3);
603
604 table.addView(row);
605
606 }
607 findViewById(R.id.rootView).requestLayout();
608 }
609
610 class MetroFetcher extends AsyncTask<Integer, Void, Void> {
611
612 @Override
613 protected void onPostExecute(Void result) {
614 super.onPostExecute(result);
615
616
617
618 pgDialog.dismiss();
619
620 if (metroBean != null) {
621 loadMetroData();
622 } else { // communication or parse error
623 commFailCounter++;
624 AlertDialog.Builder builder = new AlertDialog.Builder(DepartureList.this);
625 builder.setMessage("Error finding metro data");
626 builder.setCancelable(true);
627 if (commFailCounter < 3) {
628 builder.setPositiveButton(getString(generic_retry), new DialogInterface.OnClickListener() {
629 public void onClick(DialogInterface dialog, int id) {
630 dialog.dismiss();
631 startMetroFetcher();
632
633 }
634 });
635 }
636 builder.setNegativeButton(getString(generic_cancel), new DialogInterface.OnClickListener() {
637 public void onClick(DialogInterface dialog, int id) {
638 dialog.dismiss();
639 DepartureList.this.finish(); //TODO: should we really close the activity ??
640 }
641 });
642
643 try { //TODO: is this still necessary after the 0.9.4.1 fix ?
644 builder.show();
645 } catch (android.view.WindowManager.BadTokenException e) {
646 Log.i("DepartureList", "BadTokenException"); // this can happen if the user switched away from this activity, while doInBackground was running
647 }
648 }
649 }
650
651 @Override
652 protected Void doInBackground(Integer... params) {
653 metroBean = metro.lookupMetroInfo(params[0]);
654 return null;
655 }
656
657 }
658
659 }

  ViewVC Help
Powered by ViewVC 1.1.20