package com.evancharlton.mileage;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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.binders.VehicleBinder;
import com.evancharlton.mileage.calculators.CalculationEngine;
import com.evancharlton.mileage.models.FillUp;
import com.evancharlton.mileage.models.Vehicle;
public class HistoryView extends TabChildActivity 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";
private Map<Long, String> m_vehicleTitles = new HashMap<Long, String>();
private double m_avgMpg;
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 Map<Long, FillUp> m_fillupMap;
private int COL_AMOUNT;
private int COL_PRICE;
private int COL_ODOMETER;
private int COL_VEHICLEID;
private int COL_TIMESTAMP;
@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);
}
});
buildVehicleSpinner();
}
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);
}
private void buildVehicleSpinner() {
m_vehicles = (Spinner) findViewById(R.id.vehicles);
Cursor vehicleCursor = managedQuery(Vehicle.CONTENT_URI, Vehicle.getProjection(), null, null, Vehicle.DEFAULT_SORT_ORDER);
SimpleCursorAdapter vehicleAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_spinner_item, vehicleCursor, new String[] {
Vehicle.TITLE
}, new int[] {
android.R.id.text1
});
vehicleAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
vehicleAdapter.setViewBinder(new VehicleBinder());
m_vehicles.setAdapter(vehicleAdapter);
setVehicleSelection(m_vehicles);
m_vehicles.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> adapter, View view, int position, long id) {
updateVehicleSelection(position);
onResume();
}
public void onNothingSelected(AdapterView<?> arg0) {
}
});
// populate the vehicle title mapping
vehicleCursor.moveToFirst();
final int col_id = Vehicle.PROJECTION.indexOf(Vehicle._ID);
final int col_title = Vehicle.PROJECTION.indexOf(Vehicle.TITLE);
while (vehicleCursor.isAfterLast() == false) {
m_vehicleTitles.put(vehicleCursor.getLong(col_id), vehicleCursor.getString(col_title));
vehicleCursor.moveToNext();
}
if (vehicleAdapter.getCount() == 1) {
m_vehicles.setVisibility(View.GONE);
}
}
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(FillUp.CONTENT_URI);
}
String[] from = new String[] {
FillUp.AMOUNT,
FillUp.PRICE,
FillUp.DATE,
FillUp.COMMENT,
FillUp.ODOMETER
};
int[] to = new int[] {
R.id.history_amount,
R.id.history_price,
R.id.history_date,
R.id.history_comment,
R.id.history_mileage
};
String selection;
String[] selectionArgs;
long vehicle_id;
if (m_vehicles.getVisibility() != View.GONE) {
selection = FillUp.VEHICLE_ID + " = ?";
vehicle_id = m_vehicles.getSelectedItemId();
selectionArgs = new String[] {
String.valueOf(vehicle_id)
};
} else {
Cursor vehicleCursor = managedQuery(Vehicle.CONTENT_URI, new String[] {
Vehicle._ID
}, null, null, Vehicle.DEFAULT + " desc");
vehicleCursor.moveToFirst();
vehicle_id = vehicleCursor.getLong(0);
selection = FillUp.VEHICLE_ID + " = (select " + Vehicle._ID + " from " + FillUpsProvider.VEHICLES_TABLE_NAME + " order by " + Vehicle.DEFAULT + " desc limit 1)";
selectionArgs = null;
}
final String[] PROJECTION = FillUp.getProjection();
Cursor historyCursor = managedQuery(FillUp.CONTENT_URI, PROJECTION, selection, selectionArgs, FillUp.DEFAULT_SORT_ORDER);
if (historyCursor.getCount() > 0) {
historyCursor.moveToFirst();
double total_distance = 0D;
double total_fuel = 0D;
COL_AMOUNT = historyCursor.getColumnIndex(FillUp.AMOUNT);
COL_PRICE = historyCursor.getColumnIndex(FillUp.PRICE);
COL_ODOMETER = historyCursor.getColumnIndex(FillUp.ODOMETER);
COL_VEHICLEID = historyCursor.getColumnIndex(FillUp.VEHICLE_ID);
COL_TIMESTAMP = historyCursor.getColumnIndex(FillUp.DATE);
List<FillUp> fillups = new ArrayList<FillUp>();
m_fillupMap = new HashMap<Long, FillUp>();
while (historyCursor.isAfterLast() == false) {
FillUp f = new FillUp(m_calcEngine, historyCursor);
Map<String, String> vehicleData = new HashMap<String, String>();
long vehicleId = historyCursor.getLong(COL_VEHICLEID);
vehicleData.put(Vehicle._ID, String.valueOf(vehicleId));
vehicleData.put(Vehicle.TITLE, m_vehicleTitles.get(vehicleId));
fillups.add(0, f);
m_fillupMap.put(f.getId(), f);
if (fillups.size() > 1) {
total_fuel += f.getAmount();
}
historyCursor.moveToNext();
}
// linkage, to avoid many look-ups
for (int i = 0; i < fillups.size() - 1; i++) {
FillUp current = fillups.get(i);
FillUp next = fillups.get(i + 1);
current.setNext(next);
next.setPrevious(current);
}
total_distance = fillups.get(fillups.size() - 1).getOdometer() - fillups.get(0).getOdometer();
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(FillUp.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 text = null;
FillUp fillup;
TextView textview = (TextView) view;
if (columnIndex == COL_AMOUNT) {
double gallons = cursor.getDouble(columnIndex);
text = m_prefs.format(gallons) + m_calcEngine.getVolumeUnitsAbbr();
} else if (columnIndex == COL_PRICE) {
double price = cursor.getDouble(columnIndex);
text = m_prefs.getCurrency() + m_prefs.format(price) + "/" + m_calcEngine.getVolumeUnitsAbbr().trim();
} else if (columnIndex == COL_TIMESTAMP) {
long time = cursor.getLong(columnIndex);
Date date = new Date(time);
text = m_prefs.format(date);
} else if (columnIndex == COL_ODOMETER) {
if (!cursor.isLast()) {
fillup = m_fillupMap.get(cursor.getLong(FillUp.PROJECTION.indexOf(FillUp._ID)));
if (fillup == null) {
return true;
}
if (fillup.isPartial()) {
text = getString(R.string.partial_fillup_economy);
textview.setTextColor(0xFF666666);
} else {
double mpg = fillup.calcEconomy();
int color = 0xFF666666;
if (m_calcEngine.better(mpg, m_avgMpg)) {
color = 0xFF0AB807;
} else if (mpg == m_avgMpg) {
color = 0xFF2469FF;
} else {
color = 0xFFD90000;
}
textview.setTextColor(color);
text = m_prefs.format(mpg) + m_calcEngine.getEconomyUnits();
}
} else {
text = "";
}
}
if (text != null) {
textview.setText(text);
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();
}
}
};
}