TripInfoActivity.java :  » App » seattle-bus-bot » com » joulespersecond » seattlebusbot » Android Open Source

Android Open Source » App » seattle bus bot 
seattle bus bot » com » joulespersecond » seattlebusbot » TripInfoActivity.java
/*
 * Copyright (C) 2010 Paul Watts (paulcwatts@gmail.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.joulespersecond.seattlebusbot;

import java.util.List;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.joulespersecond.oba.provider.ObaContract;

public class TripInfoActivity extends Activity {
    private static final String TAG = "TripInfoActivity";

    private static final int DELETE_DIALOG = 2;

    private static final String TRIP_ID = ".TripId";
    private static final String ROUTE_ID = ".RouteId";
    private static final String ROUTE_NAME = ".RouteName";
    private static final String STOP_ID = ".StopId";
    private static final String STOP_NAME = ".StopName";
    private static final String HEADSIGN = ".Headsign";
    private static final String DEPARTURE_TIME = ".Depart";
    // Save/restore values
    private static final String TRIP_NAME = ".TripName";
    private static final String REMINDER_TIME = ".ReminderTime";
    private static final String REMINDER_DAYS = ".ReminderDays";

    private static final String[] PROJECTION = {
        ObaContract.Trips.NAME,
        ObaContract.Trips.REMINDER,
        ObaContract.Trips.DAYS,
        ObaContract.Trips.ROUTE_ID,
        ObaContract.Trips.HEADSIGN,
        ObaContract.Trips.DEPARTURE
    };
    private static final int COL_NAME = 0;
    private static final int COL_REMINDER = 1;
    private static final int COL_DAYS = 2;
    private static final int COL_ROUTE_ID = 3;
    private static final int COL_HEADSIGN = 4;
    private static final int COL_DEPARTURE = 5;

    private Uri mTripUri;
    private String mTripId;
    private String mRouteId;
    private String mRouteName;
    private String mStopId;
    private String mStopName;
    private String mHeadsign;
    private String mTripName;
    private long mDepartTime;
    private int mReminderTime; // DB Value, not selection value
    private int mReminderDays;

    public static void start(Context context, String tripId, String stopId) {
        Intent myIntent = new Intent(context, TripInfoActivity.class);
        myIntent.setData(ObaContract.Trips.buildUri(tripId, stopId));
        context.startActivity(myIntent);
    }

    public static void start(Context context,
            String tripId,
            String stopId,
            String routeId,
            String routeName,
            String stopName,
            long departureTime,
            String headsign) {
        Intent myIntent = new Intent(context, TripInfoActivity.class);
        myIntent.setData(ObaContract.Trips.buildUri(tripId, stopId));
        myIntent.putExtra(ROUTE_ID, routeId);
        myIntent.putExtra(ROUTE_NAME, routeName);
        myIntent.putExtra(STOP_NAME, stopName);
        myIntent.putExtra(DEPARTURE_TIME, departureTime);
        myIntent.putExtra(HEADSIGN, headsign);
        context.startActivity(myIntent);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.trip_info);

        if (!initFromIntent(getIntent())) {
            Log.e(TAG, "Information missing from intent");
            finish();
            return;
        }

        boolean newTrip = !initFromDB();
        initForm(newTrip);
    }

    private boolean initFromIntent(Intent intent) {
        final Bundle bundle = intent.getExtras();
        final Uri data = intent.getData();
        if (data != null) {
            List<String> segments = data.getPathSegments();
            mTripId = segments.get(1);
            mStopId = segments.get(2);
            mTripUri = data;
        } else if (bundle != null) {
            // Backward compatibility
            mTripId = bundle.getString(TRIP_ID);
            mStopId = bundle.getString(STOP_ID);
            mTripUri = ObaContract.Trips.buildUri(mTripId, mStopId);
        }
        if (mTripId == null || mStopId == null) {
            return false;
        }
        if (bundle != null) {
            mRouteId = bundle.getString(ROUTE_ID);
            mHeadsign = bundle.getString(HEADSIGN);
            mDepartTime = bundle.getLong(DEPARTURE_TIME);

            mStopName = bundle.getString(STOP_NAME);
            mRouteName = bundle.getString(ROUTE_NAME);
            // If we get this, update it in the DB.
            if (mRouteName != null) {
                ContentValues values = new ContentValues();
                values.put(ObaContract.Routes.SHORTNAME, mRouteName);
                ObaContract.Routes
                        .insertOrUpdate(this, mRouteId, values, false);
            }
        }
        return true;
    }

    private boolean initFromDB() {
        // Look up the trip in the database.
        ContentResolver cr = getContentResolver();
        Cursor cursor = cr.query(mTripUri, PROJECTION, null, null, null);
        if (cursor == null || cursor.getCount() < 1) {
            // Reminder defaults to 10 in the UI
            mReminderTime = 10;
            if (cursor != null) {
                cursor.close();
            }
            return false;
        }
        cursor.moveToFirst();
        mTripName = cursor.getString(COL_NAME);
        mReminderTime = cursor.getInt(COL_REMINDER);
        mReminderDays = cursor.getInt(COL_DAYS);

        // If some values weren't set in the bundle, assign them the
        // values in the db.
        if (mRouteId == null) {
            mRouteId = cursor.getString(COL_ROUTE_ID);
        }
        if (mHeadsign == null) {
            mHeadsign = cursor.getString(COL_HEADSIGN);
        }
        if (mDepartTime == 0) {
            mDepartTime = ObaContract.Trips.convertDBToTime(cursor
                    .getInt(COL_DEPARTURE));
        }

        // If we don't have the route name, look it up in the DB
        if (mRouteName == null) {
            mRouteName = TripService.getRouteShortName(this, mRouteId);
        }
        if (mStopName == null) {
            mStopName = UIHelp.stringForQuery(this, Uri.withAppendedPath(
                    ObaContract.Stops.CONTENT_URI, mStopId),
                    ObaContract.Stops.NAME);
        }
        cursor.close();
        return true;
    }

    private void initForm(boolean newTrip) {
        Spinner s = (Spinner) findViewById(R.id.trip_info_reminder_time);
        ArrayAdapter<?> adapter = ArrayAdapter.createFromResource(
                this, R.array.reminder_time, android.R.layout.simple_spinner_item);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        s.setAdapter(adapter);

        //
        // Static (header values)
        //
        final TextView stopName = (TextView)findViewById(R.id.stop_name);
        stopName.setText(MyTextUtils.toTitleCase(mStopName));

        final TextView routeName = (TextView)findViewById(R.id.route_name);
        routeName.setText(getString(R.string.trip_info_route, mRouteName));

        final TextView headsign = (TextView)findViewById(R.id.headsign);
        headsign.setText(MyTextUtils.toTitleCase(mHeadsign));

        final TextView departText = (TextView)findViewById(R.id.departure_time);
        departText.setText(getDepartureTime(this, mDepartTime));

        setUserValues();

        //
        // Buttons
        //
        final Button repeats = (Button)findViewById(R.id.trip_info_reminder_days);
        repeats.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                showReminderDaysDialog();
            }
        });

        // Listen to the buttons:
        final Button save = (Button)findViewById(R.id.trip_info_save);
        save.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                saveTrip();
            }
        });
        final Button discard = (Button)findViewById(R.id.trip_info_cancel);
        discard.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                finish();
            }
        });

        final Button delete = (Button)findViewById(R.id.trip_info_delete);
        delete.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                showDialog(DELETE_DIALOG);
            }
        });

        if (newTrip) {
            // If this is a new trip, then hide the 'delete' button
            delete.setVisibility(View.GONE);
        }
    }

    private void setUserValues() {
        final TextView tripName = (TextView)findViewById(R.id.name);
        tripName.setText(mTripName);

        final Spinner reminder = (Spinner)findViewById(R.id.trip_info_reminder_time);
        reminder.setSelection(reminderToSelection(mReminderTime));

        final Button repeats = (Button)findViewById(R.id.trip_info_reminder_days);
        repeats.setText(getRepeatText(this, mReminderDays));
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        final Spinner reminderView = (Spinner)findViewById(R.id.trip_info_reminder_time);
        final TextView nameView = (TextView)findViewById(R.id.name);

        final int reminder = selectionToReminder(reminderView
                .getSelectedItemPosition());
        outState.putString(TRIP_NAME, nameView.getText().toString());
        outState.putInt(REMINDER_TIME, reminder);
        outState.putInt(REMINDER_DAYS, mReminderDays);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        String name = savedInstanceState.getString(TRIP_NAME);
        if (name != null) {
            mTripName = name;
        }

        mReminderTime = savedInstanceState.getInt(REMINDER_TIME, mReminderTime);
        mReminderDays = savedInstanceState.getInt(REMINDER_DAYS, mReminderDays);
        setUserValues();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.trip_info_options, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == R.id.show_route) {
            RouteInfoActivity.start(this, mRouteId);
            return true;
        } else if (item.getItemId() == R.id.show_stop) {
            StopInfoActivity.start(this, mStopId, mStopName);
            return true;
        }
        return false;
    }

    //
    // Buttons (1.6 only)
    //
    /*
    public final void onRepeatClick(View v) {
        showDialog(REMINDER_DAYS_DIALOG);
    }
    public final void onSaveClick(View v) {
        saveTrip();
    }
    public final void onCancelClick(View v) {
        finish();
    }
    public final void onDeleteClick(View v) {
        showDialog(DELETE_DIALOG);
    }
    */

    public void saveTrip() {
        // Things that need updating:
        // Any constant values (trip info not editable by user)
        // Trip name
        // Reminder time
        // Repeats
        //
        final Spinner reminderView = (Spinner)findViewById(R.id.trip_info_reminder_time);
        final TextView nameView = (TextView)findViewById(R.id.name);

        final int reminder = selectionToReminder(reminderView
                .getSelectedItemPosition());

        ContentValues values = new ContentValues();
        values.put(ObaContract.Trips.ROUTE_ID, mRouteId);
        values.put(ObaContract.Trips.DEPARTURE, ObaContract.Trips
                .convertTimeToDB(mDepartTime));
        values.put(ObaContract.Trips.HEADSIGN, mHeadsign);
        values.put(ObaContract.Trips.NAME, nameView.getText().toString());
        values.put(ObaContract.Trips.REMINDER, reminder);
        values.put(ObaContract.Trips.DAYS, mReminderDays);

        // Insert or update?
        ContentResolver cr = getContentResolver();
        Cursor c = cr.query(mTripUri, new String[] { ObaContract.Trips._ID },
                null, null, null);
        if (c != null && c.getCount() > 0) {
            // Update
            cr.update(mTripUri, values, null, null);
        } else {
            values.put(ObaContract.Trips._ID, mTripId);
            values.put(ObaContract.Trips.STOP_ID, mStopId);
            cr.insert(ObaContract.Trips.CONTENT_URI, values);
        }
        if (c != null) {
            c.close();
        }
        TripService.scheduleAll(this);

        Toast.makeText(this, R.string.trip_info_saved, Toast.LENGTH_SHORT)
                .show();
        finish();
    }

    private void deleteTrip() {
        ContentResolver cr = getContentResolver();
        cr.delete(mTripUri, null, null);
        TripService.scheduleAll(this);
    }

    private static final int REMINDER_DAYS_DIALOG = 1;

    void showReminderDaysDialog() {
        final boolean[] checks = ObaContract.Trips.daysToArray(mReminderDays);

        new MultiChoiceActivity.Builder(this)
            .setTitle(R.string.trip_info_reminder_repeat)
            .setItems(R.array.reminder_days, checks)
            .setPositiveButton(R.string.trip_info_save)
            .setNegativeButton(R.string.trip_info_dismiss)
            .startForResult(REMINDER_DAYS_DIALOG);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
        case REMINDER_DAYS_DIALOG:
            if (resultCode == Activity.RESULT_OK) {
                setReminderDaysFromIntent(data);
            }
            break;
        default:
            super.onActivityResult(requestCode, resultCode, data);
        }
    }

    private void setReminderDaysFromIntent(Intent data) {
        final boolean checks[] =
            data.getBooleanArrayExtra(MultiChoiceActivity.CHECKED_ITEMS);
        if (checks == null) {
            return;
        }
        mReminderDays = ObaContract.Trips.arrayToDays(checks);
        final Button repeats = (Button)findViewById(R.id.trip_info_reminder_days);
        repeats.setText(getRepeatText(TripInfoActivity.this, mReminderDays));
    }

    @Override
    protected Dialog onCreateDialog(int id) {
        Dialog dialog;
        AlertDialog.Builder builder;

        switch (id) {
        case DELETE_DIALOG:
            builder = new AlertDialog.Builder(this);
            dialog = builder
                .setMessage(R.string.trip_info_delete_trip)
                .setTitle(R.string.trip_info_delete)
                .setIcon(android.R.drawable.ic_dialog_alert)
                .setPositiveButton(android.R.string.ok,
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                deleteTrip();
                                finish();
                            }
                })
                .setNegativeButton(android.R.string.cancel,
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                            }
                })
                .create();
            break;
        default:
            dialog = null;
            break;
        }
        return dialog;
    }

    // This converts what's in the database to what can be displayed in the spinner.
    private static int reminderToSelection(int reminder) {
        switch (reminder) {
        case 0:     return 0;
        case 1:     return 1;
        case 3:     return 2;
        case 5:     return 3;
        case 10:    return 4;
        case 15:    return 5;
        case 20:    return 6;
        case 25:    return 7;
        case 30:    return 8;
        default:
            Log.e(TAG, "Invalid reminder value in DB: " + reminder);
            return 0;
        }
    }

    private static int selectionToReminder(int selection) {
        switch (selection) {
        case 0:     return 0;
        case 1:     return 1;
        case 2:     return 3;
        case 3:     return 5;
        case 4:     return 10;
        case 5:     return 15;
        case 6:     return 20;
        case 7:     return 25;
        case 8:     return 30;
        default:
            Log.e(TAG, "Invalid selection: " + selection);
            return 0;
        }
    }

    static String getDepartureTime(Context ctx, long departure) {
        return ctx.getString(R.string.trip_info_depart,
                DateUtils.formatDateTime(ctx,
                    departure,
                    DateUtils.FORMAT_SHOW_TIME|
                    DateUtils.FORMAT_NO_NOON|
                    DateUtils.FORMAT_NO_MIDNIGHT));
    }

    static String getRepeatText(Context ctx, int days) {
        final Resources res = ctx.getResources();

        if ((days & ObaContract.Trips.DAY_ALL) == ObaContract.Trips.DAY_ALL) {
            return res.getString(R.string.trip_info_repeat_everyday);
        }
        if (((days & ObaContract.Trips.DAY_WEEKDAY) == ObaContract.Trips.DAY_WEEKDAY)
                && (days & ~ObaContract.Trips.DAY_WEEKDAY) == 0) {
            return res.getString(R.string.trip_info_repeat_weekdays);
        }
        if (days == 0) {
            return res.getString(R.string.trip_info_repeat_norepeat);
        }
        // Otherwise, it's not normal -- format a string
        final boolean[] array = ObaContract.Trips.daysToArray(days);
        final String[] dayNames = res.getStringArray(R.array.reminder_days);

        StringBuffer buf = new StringBuffer();

        // Find the first day
        int rangeStart = 0;
        while (rangeStart < 7) {
            for (; rangeStart < 7 && array[rangeStart] != true; ++rangeStart) {
            }

            if (rangeStart == 7) {
                break;
            }

            int rangeEnd = rangeStart + 1;
            for (; rangeEnd < 7 && array[rangeEnd] == true; ++rangeEnd) {
            }

            if (buf.length() != 0) {
                // TODO: Move to string table
                buf.append(", ");
            }

            // Single day?
            if ((rangeEnd - rangeStart) == 1) {
                buf.append(dayNames[rangeStart]);
            } else {
                buf.append(dayNames[rangeStart]);
                // TODO: Move to string table
                buf.append(" - ");
                buf.append(dayNames[rangeEnd - 1]);
            }
            rangeStart = rangeEnd;
        }

        return res.getString(R.string.trip_info_repeat_every, buf.toString());
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.