mirror of https://github.com/tasks/tasks
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
417 lines
15 KiB
Java
417 lines
15 KiB
Java
/*
|
|
* ASTRID: Android's Simple Task Recording Dame
|
|
*
|
|
* Copyright (c) 2009 Tim Su
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
package com.timsu.astrid.activities;
|
|
import java.util.Date;
|
|
import java.util.List;
|
|
|
|
import android.app.Activity;
|
|
import android.app.AlertDialog;
|
|
import android.content.Context;
|
|
import android.content.DialogInterface;
|
|
import android.content.Intent;
|
|
import android.content.res.Resources;
|
|
import android.database.Cursor;
|
|
import android.os.Bundle;
|
|
import android.view.ContextMenu;
|
|
import android.view.LayoutInflater;
|
|
import android.view.Menu;
|
|
import android.view.MenuItem;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.view.ContextMenu.ContextMenuInfo;
|
|
import android.view.View.OnCreateContextMenuListener;
|
|
import android.widget.AdapterView;
|
|
import android.widget.ArrayAdapter;
|
|
import android.widget.Button;
|
|
import android.widget.CheckBox;
|
|
import android.widget.CompoundButton;
|
|
import android.widget.ImageView;
|
|
import android.widget.ListView;
|
|
import android.widget.TextView;
|
|
import android.widget.AdapterView.OnItemClickListener;
|
|
import android.widget.CompoundButton.OnCheckedChangeListener;
|
|
|
|
import com.timsu.astrid.R;
|
|
import com.timsu.astrid.data.task.TaskController;
|
|
import com.timsu.astrid.data.task.TaskIdentifier;
|
|
import com.timsu.astrid.data.task.TaskModelForList;
|
|
|
|
|
|
/** Primary view for the Astrid Application. Lists all of the tasks in the
|
|
* system, and allows users to edit them.
|
|
*
|
|
* @author Tim Su (timsu@stanfordalumni.org)
|
|
*
|
|
*/
|
|
public class TaskList extends Activity {
|
|
private static final int ACTIVITY_CREATE = 0;
|
|
private static final int ACTIVITY_VIEW = 1;
|
|
private static final int ACTIVITY_EDIT = 2;
|
|
|
|
private static final int INSERT_ID = Menu.FIRST;
|
|
private static final int FILTERS_ID = Menu.FIRST + 1;
|
|
private static final int TAGS_ID = Menu.FIRST + 2;
|
|
|
|
private static final int CONTEXT_EDIT_ID = Menu.FIRST + 10;
|
|
private static final int CONTEXT_DELETE_ID = Menu.FIRST + 11;
|
|
private static final int CONTEXT_TIMER_ID = Menu.FIRST + 12;
|
|
|
|
private static final int CONTEXT_FILTER_HIDDEN = Menu.FIRST + 20;
|
|
private static final int CONTEXT_FILTER_DONE = Menu.FIRST + 21;
|
|
|
|
private TaskController controller;
|
|
private ListView listView;
|
|
private Button addButton;
|
|
|
|
private List<TaskModelForList> taskArray;
|
|
private boolean filterShowHidden = false;
|
|
private boolean filterShowDone = false;
|
|
|
|
/** Called when loading up the activity for the first time */
|
|
private void onLoad() {
|
|
controller = new TaskController(this);
|
|
controller.open();
|
|
|
|
listView = (ListView)findViewById(R.id.tasklist);
|
|
|
|
addButton = (Button)findViewById(R.id.addtask);
|
|
addButton.setOnClickListener(new
|
|
View.OnClickListener() {
|
|
@Override
|
|
public void onClick(View v) {
|
|
createTask();
|
|
}
|
|
});
|
|
|
|
fillData();
|
|
|
|
// filters context menu
|
|
listView.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
|
|
@Override
|
|
public void onCreateContextMenu(ContextMenu menu, View v,
|
|
ContextMenuInfo menuInfo) {
|
|
if(menu.hasVisibleItems())
|
|
return;
|
|
|
|
MenuItem item = menu.add(Menu.NONE, CONTEXT_FILTER_HIDDEN, Menu.NONE,
|
|
R.string.taskList_filter_hidden);
|
|
item.setCheckable(true);
|
|
item.setChecked(filterShowHidden);
|
|
|
|
item = menu.add(Menu.NONE, CONTEXT_FILTER_DONE, Menu.NONE,
|
|
R.string.taskList_filter_done);
|
|
item.setCheckable(true);
|
|
item.setChecked(filterShowDone);
|
|
|
|
menu.setHeaderTitle(R.string.taskList_filter_title);
|
|
}
|
|
});
|
|
}
|
|
|
|
/** Fill in the Task List with our tasks */
|
|
private void fillData() {
|
|
Resources r = getResources();
|
|
|
|
// get the database cursor
|
|
Cursor tasksCursor;
|
|
if(filterShowDone)
|
|
tasksCursor = controller.getAllTaskListCursor();
|
|
else
|
|
tasksCursor = controller.getActiveTaskListCursor();
|
|
|
|
startManagingCursor(tasksCursor);
|
|
int totalTasks = tasksCursor.getCount();
|
|
taskArray = controller.createTaskListFromCursor(tasksCursor, !filterShowHidden);
|
|
int hiddenTasks = totalTasks - taskArray.size();
|
|
|
|
// hide "add" button if we have a few tasks
|
|
if(taskArray.size() > 2)
|
|
addButton.setVisibility(View.GONE);
|
|
|
|
// set up the title
|
|
StringBuilder title = new StringBuilder().
|
|
append(r.getString(R.string.taskList_titlePrefix)).
|
|
append(" ").append(r.getQuantityString(R.plurals.Ntasks,
|
|
taskArray.size(), taskArray.size()));
|
|
if(hiddenTasks > 0)
|
|
title.append(" (").append(hiddenTasks).append(" ").
|
|
append(r.getString(R.string.taskList_hiddenSuffix)).append(")");
|
|
setTitle(title);
|
|
|
|
// set up our adapter
|
|
TaskListAdapter tasks = new TaskListAdapter(this,
|
|
R.layout.task_list_row, taskArray);
|
|
listView.setAdapter(tasks);
|
|
listView.setItemsCanFocus(true);
|
|
|
|
// list view listener
|
|
listView.setOnItemClickListener(new OnItemClickListener() {
|
|
@Override
|
|
public void onItemClick(AdapterView<?> parent, View view,
|
|
int position, long id) {
|
|
TaskModelForList task = (TaskModelForList)view.getTag();
|
|
|
|
Intent intent = new Intent(TaskList.this, TaskView.class);
|
|
intent.putExtra(TaskEdit.LOAD_INSTANCE_TOKEN, task.
|
|
getTaskIdentifier().getId());
|
|
startActivityForResult(intent, ACTIVITY_VIEW);
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
protected void onActivityResult(int requestCode, int resultCode,
|
|
Intent intent) {
|
|
fillData();
|
|
}
|
|
|
|
// --- list adapter
|
|
|
|
private class TaskListAdapter extends ArrayAdapter<TaskModelForList> {
|
|
|
|
private List<TaskModelForList> objects;
|
|
private int resource;
|
|
private LayoutInflater inflater;
|
|
|
|
public TaskListAdapter(Context context, int resource,
|
|
List<TaskModelForList> objects) {
|
|
super(context, resource, objects);
|
|
|
|
inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
|
this.objects = objects;
|
|
this.resource = resource;
|
|
}
|
|
|
|
@Override
|
|
public View getView(int position, View convertView, ViewGroup parent) {
|
|
View view;
|
|
|
|
view = inflater.inflate(resource, parent, false);
|
|
setupView(view, objects.get(position));
|
|
addListeners(position, view);
|
|
|
|
return view;
|
|
}
|
|
|
|
public void setupView(View view, final TaskModelForList task) {
|
|
Resources r = getResources();
|
|
|
|
// set up basic properties
|
|
final TextView name = ((TextView)view.findViewById(R.id.text1));
|
|
final CheckBox progress = ((CheckBox)view.findViewById(R.id.cb1));
|
|
final ImageView timer = ((ImageView)view.findViewById(R.id.image1));
|
|
|
|
view.setTag(task);
|
|
progress.setTag(task);
|
|
|
|
name.setText(task.getName());
|
|
|
|
if(task.getTimerStart() != null)
|
|
timer.setImageDrawable(r.getDrawable(R.drawable.ic_dialog_time));
|
|
progress.setChecked(task.isTaskCompleted());
|
|
setTaskAppearance(name, task);
|
|
}
|
|
|
|
public void addListeners(final int position, final View view) {
|
|
final CheckBox progress = ((CheckBox)view.findViewById(R.id.cb1));
|
|
final TextView name = ((TextView)view.findViewById(R.id.text1));
|
|
|
|
// clicking the check box
|
|
progress.setOnCheckedChangeListener(new OnCheckedChangeListener() {
|
|
@Override
|
|
public void onCheckedChanged(CompoundButton buttonView,
|
|
boolean isChecked) {
|
|
TaskModelForList task = (TaskModelForList)buttonView.getTag();
|
|
|
|
int newProgressPercentage;
|
|
if(isChecked)
|
|
newProgressPercentage = TaskModelForList.getCompletedPercentage();
|
|
else
|
|
newProgressPercentage = 0;
|
|
|
|
// this takes care of initial checked change
|
|
if(newProgressPercentage != task.getProgressPercentage()) {
|
|
task.setProgressPercentage(newProgressPercentage);
|
|
controller.saveTask(task);
|
|
setTaskAppearance(name, task);
|
|
}
|
|
}
|
|
});
|
|
|
|
// interacting with the text field
|
|
view.setOnClickListener(new View.OnClickListener() {
|
|
@Override
|
|
public void onClick(View v) {
|
|
listView.performItemClick(view, position, 0);
|
|
}
|
|
});
|
|
|
|
view.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
|
|
@Override
|
|
public void onCreateContextMenu(ContextMenu menu, View v,
|
|
ContextMenuInfo menuInfo) {
|
|
TaskModelForList task = (TaskModelForList)v.getTag();
|
|
|
|
menu.add(position, CONTEXT_EDIT_ID, Menu.NONE,
|
|
R.string.taskList_context_edit);
|
|
menu.add(position, CONTEXT_DELETE_ID, Menu.NONE,
|
|
R.string.taskList_context_delete);
|
|
|
|
int timerTitle;
|
|
if(task.getTimerStart() == null)
|
|
timerTitle = R.string.taskList_context_startTimer;
|
|
else
|
|
timerTitle = R.string.taskList_context_stopTimer;
|
|
menu.add(position, CONTEXT_TIMER_ID, Menu.NONE, timerTitle);
|
|
|
|
menu.setHeaderTitle(task.getName());
|
|
}
|
|
});
|
|
}
|
|
|
|
public void setTaskAppearance(TextView name, TaskModelForList task) {
|
|
Resources r = getResources();
|
|
|
|
if(task.isTaskCompleted()) {
|
|
name.setBackgroundDrawable(r.getDrawable(R.drawable.strikeout));
|
|
name.setTextColor(r.getColor(R.color.task_list_done));
|
|
} else {
|
|
name.setBackgroundDrawable(null);
|
|
name.setTextColor(r.getColor(task.getTaskColorResource()));
|
|
}
|
|
}
|
|
}
|
|
|
|
// --- ui control handlers
|
|
|
|
private void createTask() {
|
|
Intent i = new Intent(this, TaskEdit.class);
|
|
startActivityForResult(i, ACTIVITY_CREATE);
|
|
}
|
|
|
|
private void deleteTask(final TaskIdentifier taskId) {
|
|
new AlertDialog.Builder(this)
|
|
.setTitle(R.string.delete_title)
|
|
.setMessage(R.string.delete_this_task_title)
|
|
.setIcon(android.R.drawable.ic_dialog_alert)
|
|
.setPositiveButton(android.R.string.ok,
|
|
new DialogInterface.OnClickListener() {
|
|
@Override
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
controller.deleteTask(taskId);
|
|
fillData();
|
|
}
|
|
})
|
|
.setNegativeButton(android.R.string.cancel, null)
|
|
.show();
|
|
}
|
|
|
|
@Override
|
|
public boolean onMenuItemSelected(int featureId, MenuItem item) {
|
|
switch(item.getItemId()) {
|
|
case INSERT_ID:
|
|
createTask();
|
|
return true;
|
|
case FILTERS_ID:
|
|
listView.showContextMenu();
|
|
return true;
|
|
case TAGS_ID:
|
|
// TODO
|
|
return true;
|
|
|
|
case CONTEXT_EDIT_ID:
|
|
TaskModelForList task = taskArray.get(item.getGroupId());
|
|
Intent intent = new Intent(TaskList.this, TaskEdit.class);
|
|
intent.putExtra(TaskEdit.LOAD_INSTANCE_TOKEN, task.getTaskIdentifier().getId());
|
|
startActivityForResult(intent, ACTIVITY_EDIT);
|
|
return true;
|
|
case CONTEXT_DELETE_ID:
|
|
task = taskArray.get(item.getGroupId());
|
|
deleteTask(task.getTaskIdentifier());
|
|
return true;
|
|
case CONTEXT_TIMER_ID:
|
|
task = taskArray.get(item.getGroupId());
|
|
if(task.getTimerStart() == null)
|
|
task.setTimerStart(new Date());
|
|
else {
|
|
task.stopTimerAndUpdateElapsedTime();
|
|
}
|
|
controller.saveTask(task);
|
|
fillData();
|
|
return true;
|
|
|
|
case CONTEXT_FILTER_HIDDEN:
|
|
filterShowHidden = !filterShowHidden;
|
|
fillData();
|
|
return true;
|
|
case CONTEXT_FILTER_DONE:
|
|
filterShowDone = !filterShowDone;
|
|
fillData();
|
|
return true;
|
|
}
|
|
|
|
return super.onMenuItemSelected(featureId, item);
|
|
}
|
|
|
|
// --- creating stuff
|
|
|
|
@Override
|
|
public void onCreate(Bundle savedInstanceState) {
|
|
super.onCreate(savedInstanceState);
|
|
setContentView(R.layout.task_list);
|
|
|
|
onLoad();
|
|
}
|
|
|
|
@Override
|
|
public boolean onCreateOptionsMenu(Menu menu) {
|
|
super.onCreateOptionsMenu(menu);
|
|
|
|
MenuItem item;
|
|
|
|
item = menu.add(Menu.NONE, INSERT_ID, Menu.NONE,
|
|
R.string.taskList_menu_insert);
|
|
item.setIcon(android.R.drawable.ic_menu_add);
|
|
item.setAlphabeticShortcut('n');
|
|
|
|
item = menu.add(Menu.NONE, FILTERS_ID, Menu.NONE,
|
|
R.string.taskList_menu_filters);
|
|
item.setIcon(android.R.drawable.ic_menu_view);
|
|
item.setAlphabeticShortcut('f');
|
|
|
|
/*item = menu.add(Menu.NONE, TAGS_ID, Menu.NONE,
|
|
R.string.taskList_menu_tags);
|
|
item.setIcon(android.R.drawable.ic_menu_myplaces);
|
|
item.setAlphabeticShortcut('t');*/
|
|
|
|
/*item = menu.add(Menu.NONE, SETTINGS_ID, Menu.NONE,
|
|
R.string.taskList_menu_settings);
|
|
item.setIcon(android.R.drawable.ic_menu_preferences);
|
|
item.setAlphabeticShortcut('p');*/
|
|
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
protected void onDestroy() {
|
|
super.onDestroy();
|
|
controller.close();
|
|
}
|
|
} |