package com.evancharlton.mileage; import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Set; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.content.ContentUris; import android.content.DialogInterface; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.view.ContextMenu; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ContextMenu.ContextMenuInfo; import android.widget.AdapterView; import android.widget.ListView; import android.widget.SimpleCursorAdapter; import android.widget.Spinner; import android.widget.TextView; import android.widget.AdapterView.AdapterContextMenuInfo; import com.evancharlton.mileage.calculators.CalculationEngine; public class HistoryView extends Activity implements View.OnCreateContextMenuListener { public static final int MENU_IMPORT_EXPORT = Menu.FIRST; public static final int MENU_EXPORT = Menu.FIRST; public static final int MENU_EXPORT_DB = Menu.FIRST + 1; public static final int MENU_EXPORT_SQL = Menu.FIRST + 2; public static final int MENU_EXPORT_CSV = Menu.FIRST + 3; public static final int MENU_IMPORT = Menu.FIRST + 4; public static final int MENU_IMPORT_DB = Menu.FIRST + 5; public static final int MENU_IMPORT_SQL = Menu.FIRST + 6; public static final int MENU_IMPORT_CSV = Menu.FIRST + 7; public static final int MENU_DELETE = Menu.FIRST; public static final int MENU_EDIT = Menu.FIRST + 1; public static final int DELETE_DIALOG_ID = 1; public static final String TAG = "HistoryList"; public static final int COL_ID = 0; public static final int COL_AMOUNT = 1; public static final int COL_COST = 2; public static final int COL_DATE = 3; public static final int COL_COMMENT = 4; public static final int COL_VEHICLEID = 5; public static final int COL_MILEAGE = 6; private Map<Integer, String> m_vehicleTitles = new HashMap<Integer, String>(); private double m_avgMpg; private HashMap<Double, Double> m_history; private AlertDialog m_deleteDialog; private long m_deleteId; private PreferencesProvider m_prefs; private CalculationEngine m_calcEngine; private ListView m_listView; private Spinner m_vehicles; private static final String[] PROJECTIONS = new String[] { FillUps._ID, FillUps.AMOUNT, FillUps.COST, FillUps.DATE, FillUps.COMMENT, FillUps.VEHICLE_ID, FillUps.MILEAGE }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.history); m_deleteDialog = new AlertDialog.Builder(this).create(); m_deleteDialog.setMessage(getString(R.string.confirm_delete)); m_deleteDialog.setCancelable(false); m_deleteDialog.setButton(getString(R.string.yes), m_deleteListener); m_deleteDialog.setButton2(getString(R.string.no), m_deleteListener); m_listView = (ListView) findViewById(android.R.id.list); m_listView.setOnCreateContextMenuListener(this); m_listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { HistoryView.this.onItemClick(arg2, arg3); } }); m_history = new HashMap<Double, Double>(); m_vehicles = (Spinner) findViewById(R.id.vehicles); String[] projection = new String[] { Vehicles._ID, Vehicles.TITLE }; Cursor vehicleCursor = managedQuery(Vehicles.CONTENT_URI, projection, null, null, Vehicles.DEFAULT_SORT_ORDER); SimpleCursorAdapter vehicleAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_spinner_item, vehicleCursor, new String[] { Vehicles.TITLE }, new int[] { android.R.id.text1 }); vehicleAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); m_vehicles.setAdapter(vehicleAdapter); m_vehicles.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) { onResume(); } public void onNothingSelected(AdapterView<?> arg0) { } }); if (vehicleAdapter.getCount() == 1) { m_vehicles.setVisibility(View.GONE); } } protected void onItemClick(int arg2, long arg3) { Uri uri = ContentUris.withAppendedId(getIntent().getData(), arg3); Intent intent = new Intent(); intent.setData(uri); intent.setClass(HistoryView.this, FillUpView.class); startActivity(intent); } public void onResume() { super.onResume(); m_prefs = PreferencesProvider.getInstance(this); m_calcEngine = m_prefs.getCalculator(); setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT); Intent intent = getIntent(); if (intent.getData() == null) { intent.setData(FillUps.CONTENT_URI); } String[] from = new String[] { FillUps.AMOUNT, FillUps.COST, FillUps.DATE, FillUps.COMMENT, FillUps.VEHICLE_ID, FillUps.MILEAGE }; int[] to = new int[] { R.id.history_amount, R.id.history_price, R.id.history_date, R.id.history_comment, R.id.history_vehicle, R.id.history_mileage }; String selection = FillUps.VEHICLE_ID + " = ?"; String[] selectionArgs = new String[] { String.valueOf(m_vehicles.getSelectedItemId()) }; Cursor historyCursor = managedQuery(FillUps.CONTENT_URI, PROJECTIONS, selection, selectionArgs, FillUps.DEFAULT_SORT_ORDER); if (historyCursor.getCount() > 0) { historyCursor.moveToFirst(); Map<Double, Double> milesToAmt = new HashMap<Double, Double>(); while (historyCursor.isAfterLast() == false) { milesToAmt.put(historyCursor.getDouble(COL_MILEAGE), historyCursor.getDouble(COL_AMOUNT)); historyCursor.moveToNext(); } Set<Double> keyset = milesToAmt.keySet(); Double[] keys = keyset.toArray(new Double[keyset.size()]); Arrays.sort(keys); double total_fuel = 0; for (int i = keys.length - 1; i > 0; i--) { double amount = milesToAmt.get(keys[i]); double prev_mileage = keys[i - 1]; double mileage = keys[i]; double diff = mileage - prev_mileage; double mpg = m_calcEngine.calculateEconomy(diff, amount); m_history.put(mileage, mpg); total_fuel += amount; } double total_distance = keys[keys.length - 1] - keys[0]; m_avgMpg = m_calcEngine.calculateEconomy(total_distance, total_fuel); } SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.history_row, historyCursor, from, to); adapter.setViewBinder(m_viewBinder); m_listView.setAdapter(adapter); } public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo info) { menu.setHeaderTitle(R.string.operations); menu.add(Menu.NONE, MENU_DELETE, Menu.NONE, R.string.delete); menu.add(Menu.NONE, MENU_EDIT, Menu.NONE, R.string.edit_fillup); } public boolean onContextItemSelected(MenuItem item) { AdapterView.AdapterContextMenuInfo info = null; try { info = (AdapterContextMenuInfo) item.getMenuInfo(); switch (item.getItemId()) { case MENU_DELETE: m_deleteId = m_listView.getAdapter().getItemId(info.position); showDialog(DELETE_DIALOG_ID); return true; case MENU_EDIT: long id = m_listView.getAdapter().getItemId(info.position); onItemClick(info.position, id); return true; } } catch (ClassCastException e) { // fail gracefully? } return super.onContextItemSelected(item); } public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); Mileage.createMenu(menu); HelpDialog.injectHelp(menu, 'h'); return true; } public boolean onOptionsItemSelected(MenuItem item) { boolean ret = Mileage.parseMenuItem(item, this); if (ret) { return true; } switch (item.getItemId()) { case HelpDialog.MENU_HELP: HelpDialog.create(this, R.string.help_title_history, R.string.help_history); return true; } return super.onOptionsItemSelected(item); } public Dialog onCreateDialog(int id) { switch (id) { case DELETE_DIALOG_ID: return m_deleteDialog; } return super.onCreateDialog(id); } private void delete() { Uri uri = ContentUris.withAppendedId(FillUps.CONTENT_URI, m_deleteId); getContentResolver().delete(uri, null, null); onResume(); } private SimpleCursorAdapter.ViewBinder m_viewBinder = new SimpleCursorAdapter.ViewBinder() { public boolean setViewValue(View view, Cursor cursor, int columnIndex) { String val; switch (columnIndex) { case 1: double gallons = cursor.getDouble(columnIndex); val = m_prefs.format(gallons) + m_calcEngine.getVolumeUnitsAbbr(); ((TextView) view).setText(val); return true; case 2: double price = cursor.getDouble(columnIndex); val = m_prefs.getCurrency() + m_prefs.format(price) + "/" + m_calcEngine.getVolumeUnitsAbbr().trim(); ((TextView) view).setText(val); return true; case 3: long time = cursor.getLong(columnIndex); Date date = new Date(time); String text = m_prefs.format(date); ((TextView) view).setText(text); return true; case 5: int id = cursor.getInt(columnIndex); val = m_vehicleTitles.get(id); boolean hide = true; if (m_vehicleTitles.size() == 1) { hide = true; } else { if (val != null) { ((TextView) view).setText(val); hide = false; } } if (hide) { view.setVisibility(View.GONE); } return true; case COL_MILEAGE: double mileage = cursor.getDouble(columnIndex); if (!cursor.isLast()) { Double mpg = m_history.get(mileage); if (mpg == null) { return true; } TextView tv = (TextView) view; int color = 0xFF666666; if (m_calcEngine.better(mpg, m_avgMpg)) { color = 0xFF0AB807; } else if (mpg == m_avgMpg) { color = 0xFF2469FF; } else { color = 0xFFD90000; } tv.setTextColor(color); tv.setText(m_prefs.format(mpg) + m_calcEngine.getEconomyUnits()); } return true; } return false; } }; private DialogInterface.OnClickListener m_deleteListener = new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); if (which == Dialog.BUTTON1) { delete(); } } }; }