com.kunze.androidlocaltodo.TaskListActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.kunze.androidlocaltodo.TaskListActivity.java

Source

/* Copyright (c) 2013 Aaron Kunze (boilerpdx@gmail.com)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
    
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
    
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.kunze.androidlocaltodo;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Locale;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import android.media.MediaScannerConnection;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Color;
import android.support.v4.widget.CursorAdapter;
import android.support.v4.widget.SimpleCursorAdapter;
import android.support.v4.widget.SimpleCursorAdapter.ViewBinder;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.RadioButton;
import android.widget.Spinner;
import android.widget.TextView;

public class TaskListActivity extends Activity implements OnItemClickListener, OnItemLongClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_task_list);
        InitializeView();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.task_list, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == R.id.action_load_astrid) {
            LoadAstrid();
        } else if (item.getItemId() == R.id.action_delete_database) {
            DeleteDatabase();
        } else if (item.getItemId() == R.id.action_backup_database) {
            BackupDatabase();
        } else if (item.getItemId() == R.id.action_manage_tasks) {
            Intent intent = new Intent(this, TaskActivity.class);
            intent.putExtra(TaskActivity.TASK_ID, mDB.LoadTask(mDB.GetCursor()).mID);

            startActivity(intent);
        } else if (item.getItemId() == R.id.action_new_task) {
            final Task task = new Task();
            ShowTaskDialog(task, new OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    mDB.AddTask(task);
                    RefreshView();
                }
            });
        }
        return true;
    }

    private void BackupDatabase() {
        String loc = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
                + "/AndroidLocalTodoBackup.db";
        try {
            mDB.BackupDatabase(loc);
            String[] paths = { loc };
            MediaScannerConnection.scanFile(this, paths, null, null);
            AlertDialog.Builder builder = new AlertDialog.Builder(TaskListActivity.this);
            AlertDialog dlg = builder.setTitle("Success!").setMessage("Database backed up!").create();
            dlg.show();
        } catch (java.io.IOException e) {
            AlertDialog.Builder builder = new AlertDialog.Builder(TaskListActivity.this);
            AlertDialog dlg = builder.setTitle("File I/O error!").setMessage(e.getMessage()).create();
            dlg.show();
        }
    }

    private void RefreshView() {
        // Get a cursor to populate the UI
        Cursor cursor = mDB.GetCursor();
        mAdapter.changeCursor(cursor);
    }

    private void InitializeView() {
        // Set up event handlers for the task list
        ListView listView = (ListView) findViewById(R.id.task_list);
        listView.setOnItemClickListener(this);
        listView.setOnItemLongClickListener(this);
        listView.setLongClickable(true);

        // Get a cursor to populate the UI
        Cursor cursor = mDB.GetCursor();
        String from[] = { "NAME", "DUE_DATE" };
        int to[] = { R.id.task_name_edit, R.id.task_due_date };

        mAdapter = new SimpleCursorAdapter(this, R.layout.task_list_element, cursor, from, to,
                CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);

        // Set up a ViewBinder to convert the due date to something more human-friendly
        mAdapter.setViewBinder(new ViewBinder() {
            @Override
            public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
                try {
                    if (columnIndex == 2) {
                        Calendar dueDate = TaskDatabase.ConvertIntToDate(cursor.getInt(columnIndex));
                        TextView dueDateView = (TextView) view;
                        SetFriendlyDueDateText(dueDateView, dueDate);
                        return true;
                    }
                } catch (Exception e) {
                    AlertDialog.Builder builder = new AlertDialog.Builder(TaskListActivity.this);
                    AlertDialog dlg = builder.setTitle("Database error!").setMessage(e.getMessage()).create();
                    dlg.show();
                }
                return false;
            }
        });
        listView.setAdapter(mAdapter);
    }

    private void DeleteDatabase() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("WARNING!");
        builder.setMessage("This will delete all of your data!  Are you sure?");
        builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {
                mDB.Remove();
                RefreshView();
            }
        });
        builder.setNegativeButton("No", new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {
                // Nothing
            }
        });
        builder.show();
    }

    private void LoadAstrid() {
        // Look for a zip file in the proper location
        String loc = Environment.getExternalStorageDirectory() + "/AstridImport/";
        AlertDialog.Builder errorBuilder = new AlertDialog.Builder(this);
        errorBuilder.setTitle("Error reading Astrid Import!");
        ZipInputStream zipStream = null;
        InputStream stream = null;
        try {
            // Try to safely open the file
            String errText = "Cannot find Astrid file in " + loc;
            File astridDir = new File(loc);
            if (!astridDir.isDirectory()) {
                throw new Exception(errText);
            }

            File[] files = astridDir.listFiles();
            if (files.length != 1) {
                throw new Exception(errText);
            }

            File astridFile = files[0];
            if (!astridFile.isFile()) {
                throw new Exception(errText);
            }

            // Try to unzip the file and unpack the tasks
            errText = "Could not unzip file " + astridFile.getAbsolutePath();
            stream = new FileInputStream(astridFile);
            zipStream = new ZipInputStream(stream);

            ZipEntry tasksEntry = null;
            while ((tasksEntry = zipStream.getNextEntry()) != null) {
                if (tasksEntry.getName().equals("tasks.csv")) {
                    break;
                }
            }
            if (tasksEntry == null) {
                throw new Exception(errText);
            }

            int size = (int) tasksEntry.getSize();
            byte tasksContent[] = new byte[size];
            int offset = 0;
            while (size != 0) {
                int read = zipStream.read(tasksContent, offset, size);
                if (read == 0) {
                    throw new Exception(errText);
                }
                offset += read;
                size -= read;
            }

            String tasksString = new String(tasksContent, "UTF-8");

            // Parse the tasks in the task list
            errText = "Could not parse task list";
            List<String> taskLines = new LinkedList<String>(Arrays.asList(tasksString.split("\n")));
            // Remove the header row
            taskLines.remove(0);
            // Some tasks have newlines in quotes, so we have to adjust for that.
            ListIterator<String> it = taskLines.listIterator();
            while (it.hasNext()) {
                String task = it.next();
                while (CountQuotes(task) % 2 == 1) {
                    it.remove();
                    task += it.next();
                }
                it.set(task);
            }
            for (String taskLine : taskLines) {
                List<String> taskFields = new LinkedList<String>(Arrays.asList(taskLine.split(",", -1)));
                // Some tasks have commas in quotes, so we have to adjust for that.
                it = taskFields.listIterator();
                while (it.hasNext()) {
                    String field = it.next();
                    while (CountQuotes(field) % 2 == 1) {
                        it.remove();
                        field += it.next();
                    }
                    it.set(field);
                }

                Task taskElement = new Task();
                taskElement.mName = taskFields.get(0);
                taskElement.mDescription = taskFields.get(8);

                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);

                taskElement.mDueDate = Calendar.getInstance();
                taskElement.mDueDate.setTime(dateFormat.parse(taskFields.get(4)));
                String completedString = taskFields.get(9);
                taskElement.mCompletedDate = Calendar.getInstance();
                if (completedString.equals("")) {
                    taskElement.mCompletedDate.setTimeInMillis(0);
                } else {
                    taskElement.mCompletedDate.setTime(dateFormat.parse(completedString));
                }
                taskElement.mRepeatUnit = Task.RepeatUnit.NONE;
                taskElement.mRepeatTime = 0;
                taskElement.mRepeatFromComplete = false;
                String repeatString = taskFields.get(6);
                String repeatFields[] = repeatString.split(":");
                if (repeatFields[0].equals("RRULE")) {
                    repeatFields = repeatFields[1].split(";");
                    String freqFields[] = repeatFields[0].split("=");
                    if (freqFields[0].equals("FREQ")) {
                        if (freqFields[1].equals("YEARLY")) {
                            taskElement.mRepeatUnit = Task.RepeatUnit.YEARS;
                        } else if (freqFields[1].equals("MONTHLY")) {
                            taskElement.mRepeatUnit = Task.RepeatUnit.MONTHS;
                        } else if (freqFields[1].equals("WEEKLY")) {
                            taskElement.mRepeatUnit = Task.RepeatUnit.WEEKS;
                        } else if (freqFields[1].equals("DAILY")) {
                            taskElement.mRepeatUnit = Task.RepeatUnit.DAYS;
                        }
                    }
                    freqFields = repeatFields[1].split("=");
                    if (freqFields[0].equals("INTERVAL")) {
                        taskElement.mRepeatTime = Integer.valueOf(freqFields[1]);
                    }
                    if (repeatFields.length > 2 && repeatFields[2] != null) {
                        freqFields = repeatFields[2].split("=");
                        if (freqFields[0].equals("FROM") && freqFields[1].equals("COMPLETION")) {
                            taskElement.mRepeatFromComplete = true;
                        }
                    }
                }
                mDB.AddTask(taskElement);
            }

            RefreshView();
        } catch (Exception e) {
            AlertDialog dlg = errorBuilder.setMessage(e.getMessage()).create();
            dlg.show();
        } finally {

            try {
                if (zipStream != null) {
                    zipStream.close();
                }
                if (stream != null) {
                    stream.close();
                }
            } catch (Exception e) {
                AlertDialog dlg = errorBuilder.setMessage(e.getMessage()).create();
                dlg.show();
            }
        }
    }

    static private int CountQuotes(String string) {
        int count = 0;
        for (int i = 0; i < string.length(); ++i) {
            switch (string.charAt(i)) {
            case '\\':
                ++i;
                break;
            case '\"':
                ++count;
                break;
            default:
                // Nothing
            }
        }
        return count;
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        Cursor cursor = (Cursor) parent.getItemAtPosition(position);
        final Task task = mDB.LoadTask(cursor);
        ShowTaskDialog(task, new OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                mDB.SaveTask(task);
                RefreshView();
            }
        });
    }

    @Override
    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
        Cursor cursor = (Cursor) parent.getItemAtPosition(position);
        final Task task = mDB.LoadTask(cursor);
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("Done?");
        builder.setMessage("Mark task \"" + task.mName + "\" as done?");
        builder.setNegativeButton("No", null);
        builder.setPositiveButton("Yes", new OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                if (task.mRepeatUnit == Task.RepeatUnit.NONE) {
                    task.mCompletedDate = Calendar.getInstance();
                } else {
                    Calendar repeatBase = Calendar.getInstance();
                    if (!task.mRepeatFromComplete) {
                        repeatBase = task.mDueDate;
                    }
                    int calUnit;
                    int calNumber = 1;
                    switch (task.mRepeatUnit) {
                    case DAYS:
                        calUnit = Calendar.DATE;
                        break;
                    case WEEKS:
                        calUnit = Calendar.DATE;
                        calNumber = 7;
                        break;
                    case MONTHS:
                        calUnit = Calendar.MONTH;
                        break;
                    case YEARS:
                        calUnit = Calendar.YEAR;
                        break;
                    default:
                        calUnit = Calendar.DATE;
                        calNumber = 0;
                        break;
                    }
                    calNumber *= task.mRepeatTime;
                    task.mDueDate = repeatBase;
                    task.mDueDate.add(calUnit, calNumber);
                }
                mDB.SaveTask(task);
                RefreshView();
            }
        });
        builder.show();
        return true;
    }

    private void ShowTaskDialog(Task task, OnClickListener okListener) {
        LayoutInflater inflater = this.getLayoutInflater();
        View dlgView = inflater.inflate(R.layout.dialog_task, null);
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setView(dlgView);
        builder.setTitle("Task");

        final TextView nameEdit = (TextView) dlgView.findViewById(R.id.task_name_edit);
        nameEdit.setText(task.mName);
        final TextView descriptionEdit = (TextView) dlgView.findViewById(R.id.task_description_edit);
        descriptionEdit.setText(task.mDescription);
        final TextView dueDateView = (TextView) dlgView.findViewById(R.id.task_due_date);
        SetFriendlyDueDateText(dueDateView, task.mDueDate);
        Button dueDateButton = (Button) dlgView.findViewById(R.id.task_due_date_choose);
        final Calendar dueDate = task.mDueDate;
        final Task thisTask = task;
        dueDateButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ShowDueDateDialog(dueDate, new OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int id) {
                        Dialog dlg = (Dialog) dialogInterface;
                        DatePicker datePicker = (DatePicker) dlg.findViewById(R.id.due_date_calendar);
                        Calendar calendar = Calendar.getInstance();
                        calendar.set(datePicker.getYear(), datePicker.getMonth(), datePicker.getDayOfMonth());
                        thisTask.mDueDate = calendar;
                        SetFriendlyDueDateText(dueDateView, thisTask.mDueDate);
                    }
                });
            }
        });

        final CheckBox repeatCheck = (CheckBox) dlgView.findViewById(R.id.repeat);
        repeatCheck.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                View dialog = (View) buttonView.getParent();
                SetRepeatVisibility(dialog, isChecked);
            }
        });

        Boolean repeat = task.mRepeatUnit != Task.RepeatUnit.NONE;
        repeatCheck.setChecked(repeat);
        SetRepeatVisibility(dlgView, repeat);

        final EditText repeatTimeEdit = (EditText) dlgView.findViewById(R.id.repeat_time);
        repeatTimeEdit.setText(Integer.toString(task.mRepeatTime));

        final Spinner repeatUnitSpinner = (Spinner) dlgView.findViewById(R.id.repeat_unit);
        String[] repeatUnits = { "Days", "Weeks", "Months", "Years" };
        repeatUnitSpinner
                .setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, repeatUnits));
        int repeatUnitPos = 0;
        switch (task.mRepeatUnit) {
        case DAYS:
            repeatUnitPos = 0;
            break;
        case WEEKS:
            repeatUnitPos = 1;
            break;
        case MONTHS:
            repeatUnitPos = 2;
            break;
        case YEARS:
            repeatUnitPos = 3;
            break;
        case NONE:
            repeatUnitPos = 0;
        }
        repeatUnitSpinner.setSelection(repeatUnitPos);

        final RadioButton repeatFromComplete = (RadioButton) dlgView.findViewById(R.id.repeat_from_complete);
        final RadioButton repeatFromDue = (RadioButton) dlgView.findViewById(R.id.repeat_from_due);
        if (task.mRepeatFromComplete) {
            repeatFromComplete.setChecked(true);
        } else {
            repeatFromDue.setChecked(true);
        }

        // Here's a trick:  We cascade the OnClick listeners so we can extract
        // the dialog contents into the task before calling the second listener.
        final OnClickListener userListener = okListener;
        final Task myTask = task;
        OnClickListener cascadedListener = new OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                myTask.mName = nameEdit.getText().toString();
                myTask.mDescription = descriptionEdit.getText().toString();

                myTask.mRepeatUnit = Task.RepeatUnit.NONE;
                if (repeatCheck.isChecked()) {
                    switch (repeatUnitSpinner.getSelectedItemPosition()) {
                    case 0:
                        myTask.mRepeatUnit = Task.RepeatUnit.DAYS;
                        break;
                    case 1:
                        myTask.mRepeatUnit = Task.RepeatUnit.WEEKS;
                        break;
                    case 2:
                        myTask.mRepeatUnit = Task.RepeatUnit.MONTHS;
                        break;
                    case 3:
                        myTask.mRepeatUnit = Task.RepeatUnit.YEARS;
                        break;
                    }

                    myTask.mRepeatTime = Integer.parseInt(repeatTimeEdit.getText().toString());
                    myTask.mRepeatFromComplete = repeatFromComplete.isChecked();
                }

                userListener.onClick(dialog, which);
            }
        };

        builder.setNegativeButton("Cancel", null);
        builder.setPositiveButton("OK", cascadedListener);

        builder.show();
    }

    private void ShowDueDateDialog(Calendar dueDate, OnClickListener okListener) {
        LayoutInflater inflater = this.getLayoutInflater();
        View dlgView = inflater.inflate(R.layout.dialog_due_date, null);
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setView(dlgView);
        builder.setTitle("Due Date");
        builder.setNegativeButton("Cancel", null);
        builder.setPositiveButton("OK", okListener);

        final TextView dateText = (TextView) dlgView.findViewById(R.id.due_date_text);
        SetFriendlyDueDateText(dateText, dueDate);

        final DatePicker datePicker = (DatePicker) dlgView.findViewById(R.id.due_date_calendar);
        //datePicker.setMinDate(Math.min(now.getTimeInMillis(), dueDate.getTimeInMillis()));
        datePicker.init(dueDate.get(Calendar.YEAR), dueDate.get(Calendar.MONTH), dueDate.get(Calendar.DAY_OF_MONTH),
                new DatePicker.OnDateChangedListener() {
                    @Override
                    public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
                        Calendar calendar = Calendar.getInstance();
                        calendar.set(year, monthOfYear, dayOfMonth, 0, 0, 0);
                        SetFriendlyDueDateText(dateText, calendar);

                    }
                });
        datePicker.setCalendarViewShown(false);

        Button todayButton = (Button) dlgView.findViewById(R.id.today_button);
        todayButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Calendar now = Calendar.getInstance();
                datePicker.updateDate(now.get(Calendar.YEAR), now.get(Calendar.MONTH),
                        now.get(Calendar.DAY_OF_MONTH));
                SetFriendlyDueDateText(dateText, now);
            }
        });
        Button plusDayButton = (Button) dlgView.findViewById(R.id.plus_day_button);
        plusDayButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Calendar calendar = Calendar.getInstance();
                calendar.set(datePicker.getYear(), datePicker.getMonth(), datePicker.getDayOfMonth());
                calendar.add(Calendar.DATE, 1);
                datePicker.updateDate(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
                        calendar.get(Calendar.DAY_OF_MONTH));
                SetFriendlyDueDateText(dateText, calendar);
            }
        });
        Button thisWeekendButton = (Button) dlgView.findViewById(R.id.this_weekend_button);
        thisWeekendButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Calendar weekend = Calendar.getInstance();
                while (weekend.get(Calendar.DAY_OF_WEEK) != Calendar.SATURDAY) {
                    weekend.add(Calendar.DATE, 1);
                }
                datePicker.updateDate(weekend.get(Calendar.YEAR), weekend.get(Calendar.MONTH),
                        weekend.get(Calendar.DAY_OF_MONTH));
                SetFriendlyDueDateText(dateText, weekend);
            }
        });
        Button plusWeekButton = (Button) dlgView.findViewById(R.id.plus_week_button);
        plusWeekButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Calendar calendar = Calendar.getInstance();
                calendar.set(datePicker.getYear(), datePicker.getMonth(), datePicker.getDayOfMonth());
                calendar.add(Calendar.DATE, 7);
                datePicker.updateDate(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
                        calendar.get(Calendar.DAY_OF_MONTH));
                SetFriendlyDueDateText(dateText, calendar);
            }
        });

        builder.show();
    }

    private void SetRepeatVisibility(View dialog, Boolean visible) {
        View[] repeatViews = { dialog.findViewById(R.id.repeat_label), dialog.findViewById(R.id.repeat_time),
                dialog.findViewById(R.id.repeat_unit), dialog.findViewById(R.id.repeat_from_label),
                dialog.findViewById(R.id.repeat_from), dialog.findViewById(R.id.repeat_from_complete),
                dialog.findViewById(R.id.repeat_from_due), dialog.findViewById(R.id.repeat_top_divider),
                dialog.findViewById(R.id.repeat_bottom_divider), };
        if (visible) {
            for (View view : repeatViews) {
                view.setVisibility(View.VISIBLE);
            }
        } else {
            for (View view : repeatViews) {
                view.setVisibility(View.GONE);
            }
        }
    }

    private void SetFriendlyDueDateText(TextView dueDateView, Calendar dueDate) {
        SimpleDateFormat dateFormatDisplay = new SimpleDateFormat("MM-dd-yyyy", Locale.US);
        Calendar now = Calendar.getInstance();
        int nowDay = TaskDatabase.ConvertDateToInt(now);
        int dueDay = TaskDatabase.ConvertDateToInt(dueDate);
        int dayDiff = nowDay - dueDay;
        if (dayDiff == 0) {
            dueDateView.setText("Today");
            dueDateView.setTextColor(Color.RED);
        } else if (dueDate.before(now)) {
            dueDateView.setText("+ " + dayDiff + " days!");
            dueDateView.setTextColor(Color.RED);
        } else if (dayDiff > -7) {
            dueDateView.setText(dueDate.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.SHORT, Locale.US));
            dueDateView.setTextColor(Color.BLACK);
        } else if (dayDiff > -14) {
            dueDateView.setText("Next " + dueDate.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.SHORT, Locale.US));
            dueDateView.setTextColor(Color.BLACK);
        } else {
            dueDateView.setText(dateFormatDisplay.format(dueDate.getTime()));
            dueDateView.setTextColor(Color.BLACK);
        }
    }

    private TaskDatabase mDB = new TaskDatabase(this);
    private SimpleCursorAdapter mAdapter = null;
}