mirror of https://github.com/tasks/tasks
Bug fixes to the chagnes made in Astrid.
parent
753ab8a23e
commit
5aa45b1dc6
Binary file not shown.
|
Before Width: | Height: | Size: 882 B After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 579 B After Width: | Height: | Size: 1.4 KiB |
@ -1,366 +0,0 @@
|
||||
package com.timsu.astrid.activities;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.GestureDetector.SimpleOnGestureListener;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.ViewFlipper;
|
||||
|
||||
import com.timsu.astrid.R;
|
||||
import com.timsu.astrid.data.tag.TagController;
|
||||
import com.timsu.astrid.data.task.TaskController;
|
||||
import com.timsu.astrid.sync.Synchronizer;
|
||||
import com.timsu.astrid.utilities.Constants;
|
||||
import com.timsu.astrid.utilities.Preferences;
|
||||
import com.timsu.astrid.utilities.StartupReceiver;
|
||||
|
||||
/**
|
||||
* Main activity uses a ViewFlipper to flip between child views.
|
||||
*
|
||||
* @author Tim Su (timsu@stanfordalumni.org)
|
||||
*/
|
||||
public class MainActivity extends Activity {
|
||||
|
||||
/**
|
||||
* Interface for views that are displayed from the main view page
|
||||
*
|
||||
* @author timsu
|
||||
*/
|
||||
abstract public static class SubActivity {
|
||||
private MainActivity parent;
|
||||
private SubActivities code;
|
||||
private View view;
|
||||
|
||||
public SubActivity(MainActivity parent, SubActivities code, View view) {
|
||||
this.parent = parent;
|
||||
this.code = code;
|
||||
this.view = view;
|
||||
view.setTag(this);
|
||||
}
|
||||
|
||||
// --- pass-through to activity listeners
|
||||
|
||||
abstract void onDisplay(Bundle variables);
|
||||
abstract boolean onPrepareOptionsMenu(Menu menu);
|
||||
abstract void onActivityResult(int requestCode, int resultCode, Intent data);
|
||||
abstract boolean onOptionsItemSelected(MenuItem item);
|
||||
|
||||
void onWindowFocusChanged(boolean hasFocus) {
|
||||
//
|
||||
}
|
||||
|
||||
// --- pass-through to activity methods
|
||||
|
||||
public Resources getResources() {
|
||||
return parent.getResources();
|
||||
}
|
||||
|
||||
public View findViewById(int id) {
|
||||
return view.findViewById(id);
|
||||
}
|
||||
|
||||
public void startManagingCursor(Cursor c) {
|
||||
parent.startManagingCursor(c);
|
||||
}
|
||||
|
||||
public void setTitle(CharSequence title) {
|
||||
parent.setTitle(title);
|
||||
}
|
||||
|
||||
public void closeActivity() {
|
||||
parent.finish();
|
||||
}
|
||||
|
||||
public void launchActivity(Intent intent, int requestCode) {
|
||||
parent.startActivityForResult(intent, requestCode);
|
||||
}
|
||||
|
||||
// --- helper methods
|
||||
|
||||
public Activity getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public TaskController getTaskController() {
|
||||
return parent.taskController;
|
||||
}
|
||||
|
||||
public TagController getTagController() {
|
||||
return parent.tagController;
|
||||
}
|
||||
|
||||
public View.OnTouchListener getGestureListener() {
|
||||
return parent.gestureListener;
|
||||
}
|
||||
|
||||
public void switchToActivity(SubActivities activity, Bundle state) {
|
||||
parent.switchToActivity(activity, state);
|
||||
}
|
||||
|
||||
// --- internal methods
|
||||
|
||||
public SubActivities getActivityCode() {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
/* ======================================================================
|
||||
* ======================================================= internal stuff
|
||||
* ====================================================================== */
|
||||
|
||||
public enum SubActivities {
|
||||
TASK_LIST,
|
||||
TAG_LIST,
|
||||
TASK_LIST_W_TAG
|
||||
};
|
||||
|
||||
public static final int FLING_DIST_THRESHOLD = 100;
|
||||
public static final int FLING_VEL_THRESHOLD = 300;
|
||||
|
||||
// view components
|
||||
private ViewFlipper viewFlipper;
|
||||
private GestureDetector gestureDetector;
|
||||
private View.OnTouchListener gestureListener;
|
||||
private SubActivity taskList;
|
||||
private SubActivity tagList;
|
||||
private SubActivity taskListWTag;
|
||||
|
||||
// animations
|
||||
private Animation mInAnimationForward;
|
||||
private Animation mOutAnimationForward;
|
||||
private Animation mInAnimationBackward;
|
||||
private Animation mOutAnimationBackward;
|
||||
|
||||
// data controllers
|
||||
private TaskController taskController;
|
||||
private TagController tagController;
|
||||
|
||||
// static variables
|
||||
static boolean shouldCloseInstance = false;
|
||||
|
||||
@Override
|
||||
/** Called when loading up the activity for the first time */
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.main);
|
||||
|
||||
// open controllers & perform application startup rituals
|
||||
StartupReceiver.onStartupApplication(this);
|
||||
shouldCloseInstance = false;
|
||||
taskController = new TaskController(this);
|
||||
taskController.open();
|
||||
tagController = new TagController(this);
|
||||
tagController.open();
|
||||
Synchronizer.setTagController(tagController);
|
||||
Synchronizer.setTaskController(taskController);
|
||||
|
||||
setupUIComponents();
|
||||
getCurrentSubActivity().onDisplay(savedInstanceState);
|
||||
|
||||
// auto sync if requested
|
||||
Integer autoSyncHours = Preferences.autoSyncFrequency(this);
|
||||
if(autoSyncHours != null) {
|
||||
final Date lastSync = Preferences.getSyncLastSync(this);
|
||||
|
||||
if(lastSync == null || lastSync.getTime() +
|
||||
1000L*3600*autoSyncHours < System.currentTimeMillis()) {
|
||||
Synchronizer.synchronize(this, true, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Set up user interface components */
|
||||
private void setupUIComponents() {
|
||||
gestureDetector = new GestureDetector(new AstridGestureDetector());
|
||||
viewFlipper = (ViewFlipper)findViewById(R.id.main);
|
||||
taskList = new TaskList(this, SubActivities.TASK_LIST,
|
||||
findViewById(R.id.tasklist_layout));
|
||||
tagList = new TagList(this, SubActivities.TAG_LIST,
|
||||
findViewById(R.id.taglist_layout));
|
||||
taskListWTag = new TaskList(this, SubActivities.TASK_LIST_W_TAG,
|
||||
findViewById(R.id.tasklistwtag_layout));
|
||||
|
||||
mInAnimationForward = AnimationUtils.loadAnimation(this, R.anim.slide_left_in);
|
||||
mOutAnimationForward = AnimationUtils.loadAnimation(this, R.anim.slide_left_out);
|
||||
mInAnimationBackward = AnimationUtils.loadAnimation(this, R.anim.slide_right_in);
|
||||
mOutAnimationBackward = AnimationUtils.loadAnimation(this, R.anim.slide_right_out);
|
||||
|
||||
gestureListener = new View.OnTouchListener() {
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
if (gestureDetector.onTouchEvent(event)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private class AstridGestureDetector extends SimpleOnGestureListener {
|
||||
@Override
|
||||
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
|
||||
try {
|
||||
Log.i("astrid", "Got fling. X: " + (e2.getX() - e1.getX()) +
|
||||
", vel: " + velocityX);
|
||||
|
||||
// flick R to L
|
||||
if(e1.getX() - e2.getX() > FLING_DIST_THRESHOLD &&
|
||||
Math.abs(velocityX) > FLING_VEL_THRESHOLD) {
|
||||
|
||||
switch(getCurrentSubActivity().getActivityCode()) {
|
||||
case TASK_LIST:
|
||||
switchToActivity(SubActivities.TAG_LIST, null);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// flick L to R
|
||||
else if(e2.getX() - e1.getX() > FLING_DIST_THRESHOLD &&
|
||||
Math.abs(velocityX) > FLING_VEL_THRESHOLD) {
|
||||
|
||||
switch(getCurrentSubActivity().getActivityCode()) {
|
||||
case TASK_LIST_W_TAG:
|
||||
switchToActivity(SubActivities.TAG_LIST, null);
|
||||
return true;
|
||||
case TAG_LIST:
|
||||
switchToActivity(SubActivities.TASK_LIST, null);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// ignore!
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* ======================================================================
|
||||
* ==================================================== subactivity stuff
|
||||
* ====================================================================== */
|
||||
|
||||
private void switchToActivity(SubActivities activity, Bundle variables) {
|
||||
// initialize the components
|
||||
switch(activity) {
|
||||
case TASK_LIST:
|
||||
taskList.onDisplay(variables);
|
||||
break;
|
||||
case TAG_LIST:
|
||||
tagList.onDisplay(variables);
|
||||
break;
|
||||
case TASK_LIST_W_TAG:
|
||||
taskListWTag.onDisplay(variables);
|
||||
}
|
||||
|
||||
// and flip to them
|
||||
switch(getCurrentSubActivity().getActivityCode()) {
|
||||
case TASK_LIST:
|
||||
viewFlipper.setInAnimation(mInAnimationForward);
|
||||
viewFlipper.setOutAnimation(mOutAnimationForward);
|
||||
viewFlipper.showNext();
|
||||
if(activity == SubActivities.TASK_LIST_W_TAG)
|
||||
viewFlipper.showNext();
|
||||
break;
|
||||
|
||||
case TAG_LIST:
|
||||
switch(activity) {
|
||||
case TASK_LIST:
|
||||
viewFlipper.setInAnimation(mInAnimationBackward);
|
||||
viewFlipper.setOutAnimation(mOutAnimationBackward);
|
||||
viewFlipper.showPrevious();
|
||||
break;
|
||||
case TASK_LIST_W_TAG:
|
||||
viewFlipper.setInAnimation(mInAnimationForward);
|
||||
viewFlipper.setOutAnimation(mOutAnimationForward);
|
||||
viewFlipper.showNext();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case TASK_LIST_W_TAG:
|
||||
viewFlipper.setInAnimation(mInAnimationBackward);
|
||||
viewFlipper.setOutAnimation(mOutAnimationBackward);
|
||||
viewFlipper.showPrevious();
|
||||
if(activity == SubActivities.TASK_LIST_W_TAG)
|
||||
viewFlipper.showPrevious();
|
||||
break;
|
||||
}
|
||||
|
||||
viewFlipper.getCurrentView().requestFocus();
|
||||
}
|
||||
|
||||
private SubActivity getCurrentSubActivity() {
|
||||
return (SubActivity)viewFlipper.getCurrentView().getTag();
|
||||
}
|
||||
|
||||
/* ======================================================================
|
||||
* ======================================================= event handling
|
||||
* ====================================================================== */
|
||||
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
return getCurrentSubActivity().onPrepareOptionsMenu(menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
if(resultCode == Constants.RESULT_GO_HOME) {
|
||||
switchToActivity(SubActivities.TASK_LIST, null);
|
||||
} else
|
||||
getCurrentSubActivity().onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasFocus) {
|
||||
super.onWindowFocusChanged(hasFocus);
|
||||
|
||||
if(hasFocus && shouldCloseInstance) { // user wants to quit
|
||||
finish();
|
||||
} else
|
||||
getCurrentSubActivity().onWindowFocusChanged(hasFocus);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if(getCurrentSubActivity().onOptionsItemSelected(item) == true)
|
||||
return true;
|
||||
else
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
if (gestureDetector.onTouchEvent(event))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if(taskController != null)
|
||||
taskController.close();
|
||||
if(tagController != null)
|
||||
tagController.close();
|
||||
Synchronizer.setTagController(null);
|
||||
Synchronizer.setTaskController(null);
|
||||
}
|
||||
}
|
||||
@ -1,694 +1,417 @@
|
||||
/*
|
||||
* ASTRID: Android's Simple Task Recording Dashboard
|
||||
*
|
||||
* 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.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ContextMenu.ContextMenuInfo;
|
||||
import android.view.View.OnCreateContextMenuListener;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.Button;
|
||||
import android.widget.ListView;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
import android.view.GestureDetector.SimpleOnGestureListener;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.ViewFlipper;
|
||||
|
||||
import com.timsu.astrid.R;
|
||||
import com.timsu.astrid.activities.MainActivity.SubActivities;
|
||||
import com.timsu.astrid.activities.MainActivity.SubActivity;
|
||||
import com.timsu.astrid.activities.TaskListAdapter.TaskListAdapterHooks;
|
||||
import com.timsu.astrid.data.tag.TagController;
|
||||
import com.timsu.astrid.data.tag.TagIdentifier;
|
||||
import com.timsu.astrid.data.tag.TagModelForView;
|
||||
import com.timsu.astrid.data.task.TaskController;
|
||||
import com.timsu.astrid.data.task.TaskIdentifier;
|
||||
import com.timsu.astrid.data.task.TaskModelForList;
|
||||
import com.timsu.astrid.sync.Synchronizer;
|
||||
import com.timsu.astrid.sync.Synchronizer.SynchronizerListener;
|
||||
import com.timsu.astrid.utilities.Constants;
|
||||
import com.timsu.astrid.utilities.DialogUtilities;
|
||||
import com.timsu.astrid.utilities.Preferences;
|
||||
import com.timsu.astrid.widget.NNumberPickerDialog.OnNNumberPickedListener;
|
||||
|
||||
import com.timsu.astrid.utilities.StartupReceiver;
|
||||
|
||||
/**
|
||||
* Primary view for the Astrid Application. Lists all of the tasks in the
|
||||
* system, and allows users to edit them.
|
||||
* Main activity uses a ViewFlipper to flip between child views.
|
||||
*
|
||||
* @author Tim Su (timsu@stanfordalumni.org)
|
||||
*
|
||||
*/
|
||||
public class TaskList extends SubActivity {
|
||||
|
||||
// bundle tokens
|
||||
public static final String TAG_TOKEN = "tag";
|
||||
|
||||
// activities
|
||||
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 ACTIVITY_TAGS = 3;
|
||||
private static final int ACTIVITY_SYNCHRONIZE = 4;
|
||||
|
||||
// menu codes
|
||||
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 SYNC_ID = Menu.FIRST + 3;
|
||||
private static final int MORE_ID = Menu.FIRST + 4;
|
||||
|
||||
private static final int OPTIONS_SYNC_ID = Menu.FIRST + 10;
|
||||
private static final int OPTIONS_SETTINGS_ID = Menu.FIRST + 11;
|
||||
private static final int OPTIONS_HELP_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 static final int CONTEXT_FILTER_TAG = Menu.FIRST + 22;
|
||||
private static final int CONTEXT_SORT_AUTO = Menu.FIRST + 23;
|
||||
private static final int CONTEXT_SORT_ALPHA = Menu.FIRST + 24;
|
||||
private static final int CONTEXT_SORT_DUEDATE = Menu.FIRST + 25;
|
||||
private static final int CONTEXT_SORT_REVERSE = Menu.FIRST + 26;
|
||||
private static final int CONTEXT_SORT_GROUP = Menu.FIRST;
|
||||
|
||||
private static final int SORTFLAG_FILTERDONE = (1 << 5);
|
||||
private static final int SORTFLAG_FILTERHIDDEN = (1 << 6);
|
||||
|
||||
// UI components
|
||||
private ListView listView;
|
||||
private Button addButton;
|
||||
private View layout;
|
||||
|
||||
// other instance variables
|
||||
private Map<TagIdentifier, TagModelForView> tagMap;
|
||||
private ArrayList<TaskModelForList> taskArray;
|
||||
private HashMap<TaskModelForList, LinkedList<TagModelForView>> taskTags;
|
||||
|
||||
// display filters
|
||||
private static boolean filterShowHidden = false;
|
||||
private static boolean filterShowDone = false;
|
||||
private static TagModelForView filterTag = null;
|
||||
private static SortMode sortMode = SortMode.AUTO;
|
||||
private static boolean sortReverse = false;
|
||||
public class TaskList extends Activity {
|
||||
|
||||
/* ======================================================================
|
||||
* ======================================================= initialization
|
||||
* ====================================================================== */
|
||||
/**
|
||||
* Interface for views that are displayed from the main view page
|
||||
*
|
||||
* @author timsu
|
||||
*/
|
||||
abstract public static class SubActivity {
|
||||
private TaskList parent;
|
||||
private ActivityCode code;
|
||||
private View view;
|
||||
|
||||
public TaskList(MainActivity parent, SubActivities code, View view) {
|
||||
super(parent, code, view);
|
||||
public SubActivity(TaskList parent, ActivityCode code, View view) {
|
||||
this.parent = parent;
|
||||
this.code = code;
|
||||
this.view = view;
|
||||
view.setTag(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
/** Called when loading up the activity */
|
||||
public void onDisplay(Bundle variables) {
|
||||
// load tag map
|
||||
tagMap = getTagController().getAllTagsAsMap(getParent());
|
||||
// --- pass-through to activity listeners
|
||||
|
||||
// process the tag to filter on, if any
|
||||
if(variables != null && variables.containsKey(TAG_TOKEN)) {
|
||||
TagIdentifier identifier = new TagIdentifier(variables.getLong(TAG_TOKEN));
|
||||
filterTag = tagMap.get(identifier);
|
||||
/** Called when this subactivity is displayed to the user */
|
||||
void onDisplay(Bundle variables) {
|
||||
//
|
||||
}
|
||||
|
||||
setupUIComponents();
|
||||
loadTaskListSort();
|
||||
fillData();
|
||||
boolean onPrepareOptionsMenu(Menu menu) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setupUIComponents() {
|
||||
listView = (ListView)findViewById(R.id.tasklist);
|
||||
addButton = (Button)findViewById(R.id.addtask);
|
||||
addButton.setOnClickListener(new
|
||||
View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
createTask();
|
||||
void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
//
|
||||
}
|
||||
});
|
||||
|
||||
layout = findViewById(R.id.tasklist_layout);
|
||||
layout.setOnCreateContextMenuListener(
|
||||
new OnCreateContextMenuListener() {
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View v,
|
||||
ContextMenuInfo menuInfo) {
|
||||
if(menu.hasVisibleItems())
|
||||
return;
|
||||
onCreateMoreOptionsMenu(menu);
|
||||
boolean onMenuItemSelected(int featureId, MenuItem item) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
void onWindowFocusChanged(boolean hasFocus) {
|
||||
//
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
MenuItem item;
|
||||
boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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');
|
||||
// --- pass-through to activity methods
|
||||
|
||||
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');
|
||||
public Resources getResources() {
|
||||
return parent.getResources();
|
||||
}
|
||||
|
||||
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');
|
||||
public View findViewById(int id) {
|
||||
return view.findViewById(id);
|
||||
}
|
||||
|
||||
if(Preferences.shouldDisplaySyncButton(getParent())){
|
||||
item = menu.add(Menu.NONE, SYNC_ID, Menu.NONE,
|
||||
R.string.taskList_menu_syncshortcut);
|
||||
item.setIcon(android.R.drawable.ic_menu_upload);
|
||||
item.setAlphabeticShortcut('s');
|
||||
public void startManagingCursor(Cursor c) {
|
||||
parent.startManagingCursor(c);
|
||||
}
|
||||
|
||||
item = menu.add(Menu.NONE, MORE_ID, Menu.NONE,
|
||||
R.string.taskList_menu_more);
|
||||
item.setIcon(android.R.drawable.ic_menu_more);
|
||||
item.setAlphabeticShortcut('m');
|
||||
public void setTitle(CharSequence title) {
|
||||
parent.setTitle(title);
|
||||
}
|
||||
|
||||
return true;
|
||||
public void closeActivity() {
|
||||
parent.finish();
|
||||
}
|
||||
|
||||
public boolean onCreateMoreOptionsMenu(Menu menu) {
|
||||
MenuItem item;
|
||||
public void launchActivity(Intent intent, int requestCode) {
|
||||
parent.startActivityForResult(intent, requestCode);
|
||||
}
|
||||
|
||||
item = menu.add(Menu.NONE, OPTIONS_SYNC_ID, Menu.NONE,
|
||||
R.string.taskList_menu_sync);
|
||||
item.setAlphabeticShortcut('s');
|
||||
// --- helper methods
|
||||
|
||||
item = menu.add(Menu.NONE, OPTIONS_SETTINGS_ID, Menu.NONE,
|
||||
R.string.taskList_menu_settings);
|
||||
item.setAlphabeticShortcut('p');
|
||||
public Activity getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
item = menu.add(Menu.NONE, OPTIONS_HELP_ID, Menu.NONE,
|
||||
R.string.taskList_menu_help);
|
||||
item.setAlphabeticShortcut('h');
|
||||
public TaskController getTaskController() {
|
||||
return parent.taskController;
|
||||
}
|
||||
|
||||
return true;
|
||||
public TagController getTagController() {
|
||||
return parent.tagController;
|
||||
}
|
||||
|
||||
private enum SortMode {
|
||||
ALPHA {
|
||||
@Override
|
||||
int compareTo(TaskModelForList arg0, TaskModelForList arg1) {
|
||||
return arg0.getName().compareTo(arg1.getName());
|
||||
}
|
||||
},
|
||||
DUEDATE {
|
||||
long getDueDate(TaskModelForList task) {
|
||||
Date definite = task.getDefiniteDueDate();
|
||||
Date preferred = task.getPreferredDueDate();
|
||||
if(definite != null && preferred != null) {
|
||||
if(preferred.before(new Date()))
|
||||
return definite.getTime();
|
||||
return preferred.getTime();
|
||||
} else if(definite != null)
|
||||
return definite.getTime();
|
||||
else if(preferred != null)
|
||||
return preferred.getTime();
|
||||
else
|
||||
return new Date(2020,1,1).getTime();
|
||||
public View.OnTouchListener getGestureListener() {
|
||||
return parent.gestureListener;
|
||||
}
|
||||
@Override
|
||||
int compareTo(TaskModelForList arg0, TaskModelForList arg1) {
|
||||
return (int)((getDueDate(arg0) - getDueDate(arg1))/1000);
|
||||
|
||||
public void switchToActivity(ActivityCode activity, Bundle state) {
|
||||
parent.switchToActivity(activity, state);
|
||||
}
|
||||
},
|
||||
AUTO {
|
||||
@Override
|
||||
int compareTo(TaskModelForList arg0, TaskModelForList arg1) {
|
||||
return arg0.getTaskWeight() - arg1.getTaskWeight();
|
||||
|
||||
// --- internal methods
|
||||
|
||||
protected ActivityCode getActivityCode() {
|
||||
return code;
|
||||
}
|
||||
};
|
||||
|
||||
abstract int compareTo(TaskModelForList arg0, TaskModelForList arg1);
|
||||
};
|
||||
protected View getView() {
|
||||
return view;
|
||||
}
|
||||
}
|
||||
|
||||
/* ======================================================================
|
||||
* ====================================================== populating list
|
||||
* ======================================================= internal stuff
|
||||
* ====================================================================== */
|
||||
|
||||
private boolean isTaskHidden(TaskModelForList task) {
|
||||
if(task.isHidden())
|
||||
return true;
|
||||
|
||||
if(filterTag == null) {
|
||||
for(TagModelForView tags : taskTags.get(task)) {
|
||||
if(tags.shouldHideFromMainList())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
public enum ActivityCode {
|
||||
TASK_LIST,
|
||||
TAG_LIST,
|
||||
TASK_LIST_W_TAG
|
||||
};
|
||||
|
||||
return false;
|
||||
}
|
||||
private static final String TAG_LAST_ACTIVITY = "l";
|
||||
private static final String TAG_LAST_BUNDLE = "b";
|
||||
private static final int FLING_DIST_THRESHOLD = 100;
|
||||
private static final int FLING_VEL_THRESHOLD = 300;
|
||||
|
||||
// view components
|
||||
private ViewFlipper viewFlipper;
|
||||
private GestureDetector gestureDetector;
|
||||
private View.OnTouchListener gestureListener;
|
||||
private SubActivity taskList;
|
||||
private SubActivity tagList;
|
||||
private SubActivity taskListWTag;
|
||||
private Bundle lastActivityBundle;
|
||||
|
||||
// animations
|
||||
private Animation mInAnimationForward;
|
||||
private Animation mOutAnimationForward;
|
||||
private Animation mInAnimationBackward;
|
||||
private Animation mOutAnimationBackward;
|
||||
|
||||
// data controllers
|
||||
private TaskController taskController;
|
||||
private TagController tagController;
|
||||
|
||||
// static variables
|
||||
static boolean shouldCloseInstance = false;
|
||||
|
||||
@Override
|
||||
/** Called when loading up the activity for the first time */
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.main);
|
||||
|
||||
// open controllers & perform application startup rituals
|
||||
StartupReceiver.onStartupApplication(this);
|
||||
shouldCloseInstance = false;
|
||||
taskController = new TaskController(this);
|
||||
taskController.open();
|
||||
tagController = new TagController(this);
|
||||
tagController.open();
|
||||
Synchronizer.setTagController(tagController);
|
||||
Synchronizer.setTaskController(taskController);
|
||||
|
||||
/** Fill in the Task List with our tasks */
|
||||
private void fillData() {
|
||||
Resources r = getResources();
|
||||
setupUIComponents();
|
||||
|
||||
// get a cursor to the task list
|
||||
Cursor tasksCursor;
|
||||
if(filterTag != null) {
|
||||
List<TaskIdentifier> tasks = getTagController().getTaggedTasks(getParent(),
|
||||
filterTag.getTagIdentifier());
|
||||
tasksCursor = getTaskController().getTaskListCursorById(tasks);
|
||||
if(savedInstanceState != null && savedInstanceState.containsKey(TAG_LAST_ACTIVITY)) {
|
||||
viewFlipper.setDisplayedChild(savedInstanceState.getInt(TAG_LAST_ACTIVITY));
|
||||
Bundle variables = savedInstanceState.getBundle(TAG_LAST_BUNDLE);
|
||||
getCurrentSubActivity().onDisplay(variables);
|
||||
} else {
|
||||
if(filterShowDone)
|
||||
tasksCursor = getTaskController().getAllTaskListCursor();
|
||||
else
|
||||
tasksCursor = getTaskController().getActiveTaskListCursor();
|
||||
getCurrentSubActivity().onDisplay(null);
|
||||
}
|
||||
startManagingCursor(tasksCursor);
|
||||
taskArray = getTaskController().createTaskListFromCursor(tasksCursor);
|
||||
|
||||
// read tags and apply filters
|
||||
int hiddenTasks = 0; // # of tasks hidden
|
||||
int completedTasks = 0; // # of tasks on list that are done
|
||||
taskTags = new HashMap<TaskModelForList, LinkedList<TagModelForView>>();
|
||||
for(Iterator<TaskModelForList> i = taskArray.iterator(); i.hasNext();) {
|
||||
TaskModelForList task = i.next();
|
||||
// auto sync if requested
|
||||
Integer autoSyncHours = Preferences.autoSyncFrequency(this);
|
||||
if(autoSyncHours != null) {
|
||||
final Date lastSync = Preferences.getSyncLastSync(this);
|
||||
|
||||
if(task.isTaskCompleted()) {
|
||||
if(!filterShowDone) {
|
||||
i.remove();
|
||||
continue;
|
||||
if(lastSync == null || lastSync.getTime() +
|
||||
1000L*3600*autoSyncHours < System.currentTimeMillis()) {
|
||||
Synchronizer.synchronize(this, true, null);
|
||||
}
|
||||
}
|
||||
|
||||
// get list of tags
|
||||
LinkedList<TagIdentifier> tagIds = getTagController().getTaskTags(getParent(),
|
||||
task.getTaskIdentifier());
|
||||
LinkedList<TagModelForView> tags = new LinkedList<TagModelForView>();
|
||||
for(TagIdentifier tagId : tagIds) {
|
||||
TagModelForView tag = tagMap.get(tagId);
|
||||
tags.add(tag);
|
||||
}
|
||||
taskTags.put(task, tags);
|
||||
|
||||
// hide hidden
|
||||
if(!filterShowHidden) {
|
||||
if(isTaskHidden(task)) {
|
||||
hiddenTasks++;
|
||||
i.remove();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/** Set up user interface components */
|
||||
private void setupUIComponents() {
|
||||
gestureDetector = new GestureDetector(new AstridGestureDetector());
|
||||
viewFlipper = (ViewFlipper)findViewById(R.id.main);
|
||||
taskList = new TaskListSubActivity(this, ActivityCode.TASK_LIST,
|
||||
findViewById(R.id.tasklist_layout));
|
||||
tagList = new TagListSubActivity(this, ActivityCode.TAG_LIST,
|
||||
findViewById(R.id.taglist_layout));
|
||||
taskListWTag = new TaskListSubActivity(this, ActivityCode.TASK_LIST_W_TAG,
|
||||
findViewById(R.id.tasklistwtag_layout));
|
||||
|
||||
if(task.isTaskCompleted())
|
||||
completedTasks++;
|
||||
}
|
||||
int activeTasks = taskArray.size() - completedTasks;
|
||||
mInAnimationForward = AnimationUtils.loadAnimation(this, R.anim.slide_left_in);
|
||||
mOutAnimationForward = AnimationUtils.loadAnimation(this, R.anim.slide_left_out);
|
||||
mInAnimationBackward = AnimationUtils.loadAnimation(this, R.anim.slide_right_in);
|
||||
mOutAnimationBackward = AnimationUtils.loadAnimation(this, R.anim.slide_right_out);
|
||||
|
||||
// sort task list
|
||||
// do sort
|
||||
Collections.sort(taskArray, new Comparator<TaskModelForList>() {
|
||||
@Override
|
||||
public int compare(TaskModelForList arg0, TaskModelForList arg1) {
|
||||
return sortMode.compareTo(arg0, arg1);
|
||||
gestureListener = new View.OnTouchListener() {
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
if (gestureDetector.onTouchEvent(event)) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if(sortReverse)
|
||||
Collections.reverse(taskArray);
|
||||
|
||||
// hide "add" button if we have a few tasks
|
||||
if(taskArray.size() > 4)
|
||||
addButton.setVisibility(View.GONE);
|
||||
else
|
||||
addButton.setVisibility(View.VISIBLE);
|
||||
|
||||
// set up the title
|
||||
StringBuilder title = new StringBuilder().
|
||||
append(r.getString(R.string.taskList_titlePrefix)).append(" ");
|
||||
if(filterTag != null) {
|
||||
title.append(r.getString(R.string.taskList_titleTagPrefix,
|
||||
filterTag.getName())).append(" ");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(completedTasks > 0)
|
||||
title.append(r.getQuantityString(R.plurals.NactiveTasks,
|
||||
activeTasks, activeTasks, taskArray.size()));
|
||||
else
|
||||
title.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);
|
||||
|
||||
setUpListUI();
|
||||
};
|
||||
}
|
||||
|
||||
private void setUpListUI() {
|
||||
// set up our adapter
|
||||
TaskListAdapter tasks = new TaskListAdapter(getParent(),
|
||||
R.layout.task_list_row, taskArray, new TaskListAdapterHooks() {
|
||||
private class AstridGestureDetector extends SimpleOnGestureListener {
|
||||
@Override
|
||||
public TagController getTagController() {
|
||||
return getTagController();
|
||||
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
|
||||
try {
|
||||
Log.i("astrid", "Got fling. X: " + (e2.getX() - e1.getX()) +
|
||||
", vel: " + velocityX);
|
||||
|
||||
// flick R to L
|
||||
if(e1.getX() - e2.getX() > FLING_DIST_THRESHOLD &&
|
||||
Math.abs(velocityX) > FLING_VEL_THRESHOLD) {
|
||||
|
||||
switch(getCurrentSubActivity().getActivityCode()) {
|
||||
case TASK_LIST:
|
||||
switchToActivity(ActivityCode.TAG_LIST, null);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TagModelForView> getTagsFor(
|
||||
TaskModelForList task) {
|
||||
return taskTags.get(task);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TaskModelForList> getTaskArray() {
|
||||
return taskArray;
|
||||
}
|
||||
// flick L to R
|
||||
else if(e2.getX() - e1.getX() > FLING_DIST_THRESHOLD &&
|
||||
Math.abs(velocityX) > FLING_VEL_THRESHOLD) {
|
||||
|
||||
@Override
|
||||
public TaskController getTaskController() {
|
||||
return getTaskController();
|
||||
switch(getCurrentSubActivity().getActivityCode()) {
|
||||
case TASK_LIST_W_TAG:
|
||||
switchToActivity(ActivityCode.TAG_LIST, null);
|
||||
return true;
|
||||
case TAG_LIST:
|
||||
switchToActivity(ActivityCode.TASK_LIST, null);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performItemClick(View v, int position) {
|
||||
listView.performItemClick(v, position, 0);
|
||||
}
|
||||
|
||||
public void onCreatedTaskListView(View v, TaskModelForList task) {
|
||||
v.setOnTouchListener(getGestureListener());
|
||||
} catch (Exception e) {
|
||||
// ignore!
|
||||
}
|
||||
});
|
||||
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(getParent(), TaskView.class);
|
||||
intent.putExtra(TaskEdit.LOAD_INSTANCE_TOKEN, task.
|
||||
getTaskIdentifier().getId());
|
||||
launchActivity(intent, ACTIVITY_VIEW);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// filters context menu
|
||||
listView.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View v,
|
||||
ContextMenuInfo menuInfo) {
|
||||
if(menu.hasVisibleItems())
|
||||
return;
|
||||
Resources r = getResources();
|
||||
menu.setHeaderTitle(R.string.taskList_filter_title);
|
||||
|
||||
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);
|
||||
|
||||
if(filterTag != null) {
|
||||
item = menu.add(Menu.NONE, CONTEXT_FILTER_TAG, Menu.NONE,
|
||||
r.getString(R.string.taskList_filter_tagged,
|
||||
filterTag.getName()));
|
||||
item.setCheckable(true);
|
||||
item.setChecked(true);
|
||||
}
|
||||
|
||||
item = menu.add(CONTEXT_SORT_GROUP, CONTEXT_SORT_AUTO, Menu.NONE,
|
||||
R.string.taskList_sort_auto);
|
||||
item.setChecked(sortMode == SortMode.AUTO);
|
||||
item = menu.add(CONTEXT_SORT_GROUP, CONTEXT_SORT_ALPHA, Menu.NONE,
|
||||
R.string.taskList_sort_alpha);
|
||||
item.setChecked(sortMode == SortMode.ALPHA);
|
||||
item = menu.add(CONTEXT_SORT_GROUP, CONTEXT_SORT_DUEDATE, Menu.NONE,
|
||||
R.string.taskList_sort_duedate);
|
||||
item.setChecked(sortMode == SortMode.DUEDATE);
|
||||
menu.setGroupCheckable(CONTEXT_SORT_GROUP, true, true);
|
||||
|
||||
item = menu.add(CONTEXT_SORT_GROUP, CONTEXT_SORT_REVERSE, Menu.NONE,
|
||||
R.string.taskList_sort_reverse);
|
||||
item.setCheckable(true);
|
||||
item.setChecked(sortReverse);
|
||||
}
|
||||
});
|
||||
|
||||
listView.setOnTouchListener(getGestureListener());
|
||||
}
|
||||
|
||||
/* ======================================================================
|
||||
* ======================================================= event handlers
|
||||
* ==================================================== subactivity stuff
|
||||
* ====================================================================== */
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if(resultCode == Constants.RESULT_SYNCHRONIZE) {
|
||||
Synchronizer.synchronize(getParent(), false, new SynchronizerListener() {
|
||||
@Override
|
||||
public void onSynchronizerFinished(int numServicesSynced) {
|
||||
if(numServicesSynced == 0)
|
||||
DialogUtilities.okDialog(getParent(), getResources().getString(
|
||||
R.string.sync_no_synchronizers), null);
|
||||
fillData();
|
||||
}
|
||||
});
|
||||
} else if(requestCode == ACTIVITY_TAGS)
|
||||
switchToActivity(SubActivities.TAG_LIST, null);
|
||||
private void switchToActivity(ActivityCode activity, Bundle variables) {
|
||||
closeOptionsMenu();
|
||||
|
||||
// and flip to them
|
||||
switch(getCurrentSubActivity().getActivityCode()) {
|
||||
case TASK_LIST:
|
||||
viewFlipper.setInAnimation(mInAnimationForward);
|
||||
viewFlipper.setOutAnimation(mOutAnimationForward);
|
||||
viewFlipper.showNext();
|
||||
if(activity == ActivityCode.TASK_LIST_W_TAG)
|
||||
viewFlipper.showNext();
|
||||
break;
|
||||
|
||||
case TAG_LIST:
|
||||
switch(activity) {
|
||||
case TASK_LIST:
|
||||
viewFlipper.setInAnimation(mInAnimationBackward);
|
||||
viewFlipper.setOutAnimation(mOutAnimationBackward);
|
||||
viewFlipper.showPrevious();
|
||||
break;
|
||||
case TASK_LIST_W_TAG:
|
||||
viewFlipper.setInAnimation(mInAnimationForward);
|
||||
viewFlipper.setOutAnimation(mOutAnimationForward);
|
||||
viewFlipper.showNext();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case TASK_LIST_W_TAG:
|
||||
viewFlipper.setInAnimation(mInAnimationBackward);
|
||||
viewFlipper.setOutAnimation(mOutAnimationBackward);
|
||||
viewFlipper.showPrevious();
|
||||
if(activity == ActivityCode.TASK_LIST_W_TAG)
|
||||
viewFlipper.showPrevious();
|
||||
break;
|
||||
}
|
||||
|
||||
// initialize the components
|
||||
switch(activity) {
|
||||
case TASK_LIST:
|
||||
taskList.onDisplay(variables);
|
||||
break;
|
||||
case TAG_LIST:
|
||||
tagList.onDisplay(variables);
|
||||
break;
|
||||
case TASK_LIST_W_TAG:
|
||||
taskListWTag.onDisplay(variables);
|
||||
}
|
||||
|
||||
lastActivityBundle = variables;
|
||||
}
|
||||
|
||||
private SubActivity getCurrentSubActivity() {
|
||||
return (SubActivity)viewFlipper.getCurrentView().getTag();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasFocus) {
|
||||
// refresh, since stuff might have changed...
|
||||
if(hasFocus) {
|
||||
fillData();
|
||||
}
|
||||
}
|
||||
/* ======================================================================
|
||||
* ======================================================= event handling
|
||||
* ====================================================================== */
|
||||
|
||||
private void createTask() {
|
||||
Intent intent = new Intent(getParent(), TaskEdit.class);
|
||||
if(filterTag != null)
|
||||
intent.putExtra(TaskEdit.TAG_NAME_TOKEN, filterTag.getName());
|
||||
launchActivity(intent, ACTIVITY_CREATE);
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putInt(TAG_LAST_ACTIVITY, getCurrentSubActivity().code.ordinal());
|
||||
outState.putBundle(TAG_LAST_BUNDLE, lastActivityBundle);
|
||||
}
|
||||
|
||||
private void deleteTask(final TaskIdentifier taskId) {
|
||||
new AlertDialog.Builder(getParent())
|
||||
.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) {
|
||||
getTaskController().deleteTask(taskId);
|
||||
fillData();
|
||||
}
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if(getCurrentSubActivity().onKeyDown(keyCode, event))
|
||||
return true;
|
||||
else
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
public void showTagsView() {
|
||||
switchToActivity(SubActivities.TAG_LIST, null);
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
menu.clear();
|
||||
return getCurrentSubActivity().onPrepareOptionsMenu(menu);
|
||||
}
|
||||
|
||||
/** Save the sorting mode to the preferences */
|
||||
private void saveTaskListSort() {
|
||||
int sortId = sortMode.ordinal() + 1;
|
||||
|
||||
if(filterShowDone)
|
||||
sortId |= SORTFLAG_FILTERDONE;
|
||||
if(filterShowHidden)
|
||||
sortId |= SORTFLAG_FILTERHIDDEN;
|
||||
|
||||
if(sortReverse)
|
||||
sortId *= -1;
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
Preferences.setTaskListSort(getParent(), sortId);
|
||||
if(resultCode == Constants.RESULT_GO_HOME) {
|
||||
switchToActivity(ActivityCode.TASK_LIST, null);
|
||||
} else
|
||||
getCurrentSubActivity().onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
/** Save the sorting mode to the preferences */
|
||||
private void loadTaskListSort() {
|
||||
int sortId = Preferences.getTaskListSort(getParent());
|
||||
if(sortId == 0)
|
||||
return;
|
||||
sortReverse = sortId < 0;
|
||||
sortId = Math.abs(sortId);
|
||||
|
||||
filterShowDone = (sortId & SORTFLAG_FILTERDONE) > 0;
|
||||
filterShowHidden = (sortId & SORTFLAG_FILTERHIDDEN) > 0;
|
||||
|
||||
sortId = sortId & ~(SORTFLAG_FILTERDONE | SORTFLAG_FILTERHIDDEN);
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasFocus) {
|
||||
super.onWindowFocusChanged(hasFocus);
|
||||
|
||||
sortMode = SortMode.values()[sortId - 1];
|
||||
if(hasFocus && shouldCloseInstance) { // user wants to quit
|
||||
finish();
|
||||
} else
|
||||
getCurrentSubActivity().onWindowFocusChanged(hasFocus);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
Intent intent;
|
||||
final TaskModelForList task;
|
||||
Resources r = getResources();
|
||||
|
||||
switch(item.getItemId()) {
|
||||
case INSERT_ID:
|
||||
createTask();
|
||||
return true;
|
||||
case FILTERS_ID:
|
||||
listView.showContextMenu();
|
||||
return true;
|
||||
case TAGS_ID:
|
||||
showTagsView();
|
||||
return true;
|
||||
case SYNC_ID:
|
||||
onActivityResult(ACTIVITY_SYNCHRONIZE, Constants.RESULT_SYNCHRONIZE, null);
|
||||
return true;
|
||||
case MORE_ID:
|
||||
layout.showContextMenu();
|
||||
return true;
|
||||
|
||||
case OPTIONS_SYNC_ID:
|
||||
launchActivity(new Intent(getParent(), SyncPreferences.class),
|
||||
ACTIVITY_SYNCHRONIZE);
|
||||
return true;
|
||||
case OPTIONS_SETTINGS_ID:
|
||||
launchActivity(new Intent(getParent(), EditPreferences.class), 0);
|
||||
return true;
|
||||
case OPTIONS_HELP_ID:
|
||||
Intent browserIntent = new Intent(Intent.ACTION_VIEW,
|
||||
Uri.parse(Constants.HELP_URL));
|
||||
launchActivity(browserIntent, 0);
|
||||
return true;
|
||||
|
||||
case TaskListAdapter.CONTEXT_EDIT_ID:
|
||||
task = taskArray.get(item.getGroupId());
|
||||
intent = new Intent(getParent(), TaskEdit.class);
|
||||
intent.putExtra(TaskEdit.LOAD_INSTANCE_TOKEN, task.getTaskIdentifier().getId());
|
||||
launchActivity(intent, ACTIVITY_EDIT);
|
||||
return true;
|
||||
case TaskListAdapter.CONTEXT_DELETE_ID:
|
||||
task = taskArray.get(item.getGroupId());
|
||||
deleteTask(task.getTaskIdentifier());
|
||||
return true;
|
||||
case TaskListAdapter.CONTEXT_TIMER_ID:
|
||||
task = taskArray.get(item.getGroupId());
|
||||
if(task.getTimerStart() == null)
|
||||
task.setTimerStart(new Date());
|
||||
else {
|
||||
task.stopTimerAndUpdateElapsedTime();
|
||||
}
|
||||
getTaskController().saveTask(task);
|
||||
fillData();
|
||||
return true;
|
||||
case TaskListAdapter.CONTEXT_POSTPONE_ID:
|
||||
task = taskArray.get(item.getGroupId());
|
||||
DialogUtilities.dayHourPicker(getParent(),
|
||||
r.getString(R.string.taskList_postpone_dialog),
|
||||
new OnNNumberPickedListener() {
|
||||
public void onNumbersPicked(int[] values) {
|
||||
long postponeMillis = (values[0] * 24 + values[1]) *
|
||||
3600L * 1000;
|
||||
Date preferred = task.getPreferredDueDate();
|
||||
if(preferred != null) {
|
||||
preferred = new Date(preferred.getTime() +
|
||||
postponeMillis);
|
||||
task.setPreferredDueDate(preferred);
|
||||
}
|
||||
Date definite = task.getDefiniteDueDate();
|
||||
if(definite != null) {
|
||||
definite = new Date(definite.getTime() +
|
||||
postponeMillis);
|
||||
task.setDefiniteDueDate(definite);
|
||||
}
|
||||
getTaskController().saveTask(task);
|
||||
fillData();
|
||||
}
|
||||
});
|
||||
public boolean onMenuItemSelected(int featureId, MenuItem item) {
|
||||
if(getCurrentSubActivity().onMenuItemSelected(featureId, item))
|
||||
return true;
|
||||
else
|
||||
return super.onMenuItemSelected(featureId, item);
|
||||
}
|
||||
|
||||
case CONTEXT_FILTER_HIDDEN:
|
||||
TaskList.filterShowHidden = !filterShowHidden;
|
||||
saveTaskListSort();
|
||||
fillData();
|
||||
return true;
|
||||
case CONTEXT_FILTER_DONE:
|
||||
TaskList.filterShowDone = !filterShowDone;
|
||||
saveTaskListSort();
|
||||
fillData();
|
||||
return true;
|
||||
case CONTEXT_FILTER_TAG:
|
||||
TaskList.filterTag = null;
|
||||
fillData();
|
||||
return true;
|
||||
case CONTEXT_SORT_AUTO:
|
||||
if(sortMode == SortMode.AUTO)
|
||||
return true;
|
||||
TaskList.sortReverse = false;
|
||||
TaskList.sortMode = SortMode.AUTO;
|
||||
saveTaskListSort();
|
||||
fillData();
|
||||
return true;
|
||||
case CONTEXT_SORT_ALPHA:
|
||||
if(sortMode == SortMode.ALPHA)
|
||||
return true;
|
||||
TaskList.sortReverse = false;
|
||||
TaskList.sortMode = SortMode.ALPHA;
|
||||
saveTaskListSort();
|
||||
fillData();
|
||||
return true;
|
||||
case CONTEXT_SORT_DUEDATE:
|
||||
if(sortMode == SortMode.DUEDATE)
|
||||
return true;
|
||||
TaskList.sortReverse = false;
|
||||
TaskList.sortMode = SortMode.DUEDATE;
|
||||
saveTaskListSort();
|
||||
fillData();
|
||||
return true;
|
||||
case CONTEXT_SORT_REVERSE:
|
||||
TaskList.sortReverse = !sortReverse;
|
||||
saveTaskListSort();
|
||||
fillData();
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
if (gestureDetector.onTouchEvent(event))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
taskController.close();
|
||||
tagController.close();
|
||||
Synchronizer.setTagController(null);
|
||||
Synchronizer.setTaskController(null);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,725 @@
|
||||
/*
|
||||
* ASTRID: Android's Simple Task Recording Dashboard
|
||||
*
|
||||
* 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.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
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.view.ContextMenu;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ContextMenu.ContextMenuInfo;
|
||||
import android.view.View.OnCreateContextMenuListener;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.Button;
|
||||
import android.widget.ListView;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
|
||||
import com.timsu.astrid.R;
|
||||
import com.timsu.astrid.activities.TaskList.ActivityCode;
|
||||
import com.timsu.astrid.activities.TaskList.SubActivity;
|
||||
import com.timsu.astrid.activities.TaskListAdapter.TaskListAdapterHooks;
|
||||
import com.timsu.astrid.data.tag.TagController;
|
||||
import com.timsu.astrid.data.tag.TagIdentifier;
|
||||
import com.timsu.astrid.data.tag.TagModelForView;
|
||||
import com.timsu.astrid.data.task.TaskController;
|
||||
import com.timsu.astrid.data.task.TaskIdentifier;
|
||||
import com.timsu.astrid.data.task.TaskModelForList;
|
||||
import com.timsu.astrid.sync.Synchronizer;
|
||||
import com.timsu.astrid.sync.Synchronizer.SynchronizerListener;
|
||||
import com.timsu.astrid.utilities.Constants;
|
||||
import com.timsu.astrid.utilities.DialogUtilities;
|
||||
import com.timsu.astrid.utilities.Preferences;
|
||||
import com.timsu.astrid.widget.NNumberPickerDialog.OnNNumberPickedListener;
|
||||
|
||||
|
||||
/**
|
||||
* 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 TaskListSubActivity extends SubActivity {
|
||||
|
||||
// bundle tokens
|
||||
public static final String TAG_TOKEN = "tag";
|
||||
|
||||
// activities
|
||||
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 ACTIVITY_TAGS = 3;
|
||||
private static final int ACTIVITY_SYNCHRONIZE = 4;
|
||||
|
||||
// menu codes
|
||||
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 SYNC_ID = Menu.FIRST + 3;
|
||||
private static final int MORE_ID = Menu.FIRST + 4;
|
||||
|
||||
private static final int OPTIONS_SYNC_ID = Menu.FIRST + 10;
|
||||
private static final int OPTIONS_SETTINGS_ID = Menu.FIRST + 11;
|
||||
private static final int OPTIONS_HELP_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 static final int CONTEXT_FILTER_TAG = Menu.FIRST + 22;
|
||||
private static final int CONTEXT_SORT_AUTO = Menu.FIRST + 23;
|
||||
private static final int CONTEXT_SORT_ALPHA = Menu.FIRST + 24;
|
||||
private static final int CONTEXT_SORT_DUEDATE = Menu.FIRST + 25;
|
||||
private static final int CONTEXT_SORT_REVERSE = Menu.FIRST + 26;
|
||||
private static final int CONTEXT_SORT_GROUP = Menu.FIRST;
|
||||
|
||||
private static final int SORTFLAG_FILTERDONE = (1 << 5);
|
||||
private static final int SORTFLAG_FILTERHIDDEN = (1 << 6);
|
||||
|
||||
// UI components
|
||||
private ListView listView;
|
||||
private Button addButton;
|
||||
private View layout;
|
||||
|
||||
// other instance variables
|
||||
private Map<TagIdentifier, TagModelForView> tagMap;
|
||||
private ArrayList<TaskModelForList> taskArray;
|
||||
private HashMap<TaskModelForList, LinkedList<TagModelForView>> taskTags;
|
||||
|
||||
// display filters
|
||||
private static boolean filterShowHidden = false;
|
||||
private static boolean filterShowDone = false;
|
||||
private static SortMode sortMode = SortMode.AUTO;
|
||||
private static boolean sortReverse = false;
|
||||
private TagModelForView filterTag = null;
|
||||
|
||||
/* ======================================================================
|
||||
* ======================================================= initialization
|
||||
* ====================================================================== */
|
||||
|
||||
public TaskListSubActivity(TaskList parent, ActivityCode code, View view) {
|
||||
super(parent, code, view);
|
||||
}
|
||||
|
||||
@Override
|
||||
/** Called when loading up the activity */
|
||||
public void onDisplay(Bundle variables) {
|
||||
// load tag map
|
||||
tagMap = getTagController().getAllTagsAsMap(getParent());
|
||||
|
||||
// process the tag to filter on, if any
|
||||
if(variables != null && variables.containsKey(TAG_TOKEN)) {
|
||||
TagIdentifier identifier = new TagIdentifier(variables.getLong(TAG_TOKEN));
|
||||
filterTag = tagMap.get(identifier);
|
||||
}
|
||||
|
||||
setupUIComponents();
|
||||
loadTaskListSort();
|
||||
fillData();
|
||||
}
|
||||
|
||||
/** Initialize UI components */
|
||||
public void setupUIComponents() {
|
||||
listView = (ListView)findViewById(R.id.tasklist);
|
||||
addButton = (Button)findViewById(R.id.addtask);
|
||||
addButton.setOnClickListener(new
|
||||
View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
createTask(null);
|
||||
}
|
||||
});
|
||||
|
||||
layout = getView();
|
||||
layout.setOnCreateContextMenuListener(
|
||||
new OnCreateContextMenuListener() {
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View v,
|
||||
ContextMenuInfo menuInfo) {
|
||||
if(menu.hasVisibleItems())
|
||||
return;
|
||||
onCreateMoreOptionsMenu(menu);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
/** Create options menu (displayed when user presses menu key) */
|
||||
public boolean onPrepareOptionsMenu(Menu 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');
|
||||
|
||||
if(Preferences.shouldDisplaySyncButton(getParent())){
|
||||
item = menu.add(Menu.NONE, SYNC_ID, Menu.NONE,
|
||||
R.string.taskList_menu_syncshortcut);
|
||||
item.setIcon(android.R.drawable.ic_menu_upload);
|
||||
item.setAlphabeticShortcut('s');
|
||||
}
|
||||
|
||||
item = menu.add(Menu.NONE, MORE_ID, Menu.NONE,
|
||||
R.string.taskList_menu_more);
|
||||
item.setIcon(android.R.drawable.ic_menu_more);
|
||||
item.setAlphabeticShortcut('m');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Create 'more options' menu */
|
||||
public boolean onCreateMoreOptionsMenu(Menu menu) {
|
||||
MenuItem item;
|
||||
|
||||
item = menu.add(Menu.NONE, OPTIONS_SYNC_ID, Menu.NONE,
|
||||
R.string.taskList_menu_sync);
|
||||
item.setAlphabeticShortcut('s');
|
||||
|
||||
item = menu.add(Menu.NONE, OPTIONS_SETTINGS_ID, Menu.NONE,
|
||||
R.string.taskList_menu_settings);
|
||||
item.setAlphabeticShortcut('p');
|
||||
|
||||
item = menu.add(Menu.NONE, OPTIONS_HELP_ID, Menu.NONE,
|
||||
R.string.taskList_menu_help);
|
||||
item.setAlphabeticShortcut('h');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private enum SortMode {
|
||||
ALPHA {
|
||||
@Override
|
||||
int compareTo(TaskModelForList arg0, TaskModelForList arg1) {
|
||||
return arg0.getName().compareTo(arg1.getName());
|
||||
}
|
||||
},
|
||||
DUEDATE {
|
||||
long getDueDate(TaskModelForList task) {
|
||||
Date definite = task.getDefiniteDueDate();
|
||||
Date preferred = task.getPreferredDueDate();
|
||||
if(definite != null && preferred != null) {
|
||||
if(preferred.before(new Date()))
|
||||
return definite.getTime();
|
||||
return preferred.getTime();
|
||||
} else if(definite != null)
|
||||
return definite.getTime();
|
||||
else if(preferred != null)
|
||||
return preferred.getTime();
|
||||
else
|
||||
return new Date(2020,1,1).getTime();
|
||||
}
|
||||
@Override
|
||||
int compareTo(TaskModelForList arg0, TaskModelForList arg1) {
|
||||
return (int)((getDueDate(arg0) - getDueDate(arg1))/1000);
|
||||
}
|
||||
},
|
||||
AUTO {
|
||||
@Override
|
||||
int compareTo(TaskModelForList arg0, TaskModelForList arg1) {
|
||||
return arg0.getTaskWeight() - arg1.getTaskWeight();
|
||||
}
|
||||
};
|
||||
|
||||
abstract int compareTo(TaskModelForList arg0, TaskModelForList arg1);
|
||||
};
|
||||
|
||||
/* ======================================================================
|
||||
* ====================================================== populating list
|
||||
* ====================================================================== */
|
||||
|
||||
/** Helper method returns true if the task is considered 'hidden' */
|
||||
private boolean isTaskHidden(TaskModelForList task) {
|
||||
if(task.isHidden())
|
||||
return true;
|
||||
|
||||
if(filterTag == null) {
|
||||
for(TagModelForView tags : taskTags.get(task)) {
|
||||
if(tags.shouldHideFromMainList())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Fill in the Task List with our tasks */
|
||||
private void fillData() {
|
||||
Resources r = getResources();
|
||||
|
||||
// get a cursor to the task list
|
||||
Cursor tasksCursor;
|
||||
if(filterTag != null) {
|
||||
List<TaskIdentifier> tasks = getTagController().getTaggedTasks(getParent(),
|
||||
filterTag.getTagIdentifier());
|
||||
tasksCursor = getTaskController().getTaskListCursorById(tasks);
|
||||
} else {
|
||||
if(filterShowDone)
|
||||
tasksCursor = getTaskController().getAllTaskListCursor();
|
||||
else
|
||||
tasksCursor = getTaskController().getActiveTaskListCursor();
|
||||
}
|
||||
startManagingCursor(tasksCursor);
|
||||
taskArray = getTaskController().createTaskListFromCursor(tasksCursor);
|
||||
|
||||
// read tags and apply filters
|
||||
int hiddenTasks = 0; // # of tasks hidden
|
||||
int completedTasks = 0; // # of tasks on list that are done
|
||||
taskTags = new HashMap<TaskModelForList, LinkedList<TagModelForView>>();
|
||||
for(Iterator<TaskModelForList> i = taskArray.iterator(); i.hasNext();) {
|
||||
TaskModelForList task = i.next();
|
||||
|
||||
if(task.isTaskCompleted()) {
|
||||
if(!filterShowDone) {
|
||||
i.remove();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// get list of tags
|
||||
LinkedList<TagIdentifier> tagIds = getTagController().getTaskTags(getParent(),
|
||||
task.getTaskIdentifier());
|
||||
LinkedList<TagModelForView> tags = new LinkedList<TagModelForView>();
|
||||
for(TagIdentifier tagId : tagIds) {
|
||||
TagModelForView tag = tagMap.get(tagId);
|
||||
tags.add(tag);
|
||||
}
|
||||
taskTags.put(task, tags);
|
||||
|
||||
// hide hidden
|
||||
if(!filterShowHidden) {
|
||||
if(isTaskHidden(task)) {
|
||||
hiddenTasks++;
|
||||
i.remove();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(task.isTaskCompleted())
|
||||
completedTasks++;
|
||||
}
|
||||
int activeTasks = taskArray.size() - completedTasks;
|
||||
|
||||
// sort task list
|
||||
// do sort
|
||||
Collections.sort(taskArray, new Comparator<TaskModelForList>() {
|
||||
@Override
|
||||
public int compare(TaskModelForList arg0, TaskModelForList arg1) {
|
||||
return sortMode.compareTo(arg0, arg1);
|
||||
}
|
||||
});
|
||||
if(sortReverse)
|
||||
Collections.reverse(taskArray);
|
||||
|
||||
// hide "add" button if we have a few tasks
|
||||
if(taskArray.size() > 4)
|
||||
addButton.setVisibility(View.GONE);
|
||||
else
|
||||
addButton.setVisibility(View.VISIBLE);
|
||||
|
||||
// set up the title
|
||||
StringBuilder title = new StringBuilder().
|
||||
append(r.getString(R.string.taskList_titlePrefix)).append(" ");
|
||||
if(filterTag != null) {
|
||||
title.append(r.getString(R.string.taskList_titleTagPrefix,
|
||||
filterTag.getName())).append(" ");
|
||||
}
|
||||
|
||||
if(completedTasks > 0)
|
||||
title.append(r.getQuantityString(R.plurals.NactiveTasks,
|
||||
activeTasks, activeTasks, taskArray.size()));
|
||||
else
|
||||
title.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);
|
||||
|
||||
setUpListUI();
|
||||
}
|
||||
|
||||
/** Set up the adapter for our task list */
|
||||
private void setUpListUI() {
|
||||
// set up our adapter
|
||||
TaskListAdapter tasks = new TaskListAdapter(getParent(),
|
||||
R.layout.task_list_row, taskArray, new TaskListAdapterHooks() {
|
||||
@Override
|
||||
public TagController tagController() {
|
||||
return getTagController();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TagModelForView> getTagsFor(
|
||||
TaskModelForList task) {
|
||||
return taskTags.get(task);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TaskModelForList> getTaskArray() {
|
||||
return taskArray;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskController taskController() {
|
||||
return getTaskController();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performItemClick(View v, int position) {
|
||||
listView.performItemClick(v, position, 0);
|
||||
}
|
||||
|
||||
public void onCreatedTaskListView(View v, TaskModelForList task) {
|
||||
v.setOnTouchListener(getGestureListener());
|
||||
}
|
||||
});
|
||||
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(getParent(), TaskView.class);
|
||||
intent.putExtra(TaskEdit.LOAD_INSTANCE_TOKEN, task.
|
||||
getTaskIdentifier().getId());
|
||||
launchActivity(intent, ACTIVITY_VIEW);
|
||||
}
|
||||
});
|
||||
|
||||
// filters context menu
|
||||
listView.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View v,
|
||||
ContextMenuInfo menuInfo) {
|
||||
if(menu.hasVisibleItems())
|
||||
return;
|
||||
Resources r = getResources();
|
||||
menu.setHeaderTitle(R.string.taskList_filter_title);
|
||||
|
||||
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);
|
||||
|
||||
if(filterTag != null) {
|
||||
item = menu.add(Menu.NONE, CONTEXT_FILTER_TAG, Menu.NONE,
|
||||
r.getString(R.string.taskList_filter_tagged,
|
||||
filterTag.getName()));
|
||||
item.setCheckable(true);
|
||||
item.setChecked(true);
|
||||
}
|
||||
|
||||
item = menu.add(CONTEXT_SORT_GROUP, CONTEXT_SORT_AUTO, Menu.NONE,
|
||||
R.string.taskList_sort_auto);
|
||||
item.setChecked(sortMode == SortMode.AUTO);
|
||||
item = menu.add(CONTEXT_SORT_GROUP, CONTEXT_SORT_ALPHA, Menu.NONE,
|
||||
R.string.taskList_sort_alpha);
|
||||
item.setChecked(sortMode == SortMode.ALPHA);
|
||||
item = menu.add(CONTEXT_SORT_GROUP, CONTEXT_SORT_DUEDATE, Menu.NONE,
|
||||
R.string.taskList_sort_duedate);
|
||||
item.setChecked(sortMode == SortMode.DUEDATE);
|
||||
menu.setGroupCheckable(CONTEXT_SORT_GROUP, true, true);
|
||||
|
||||
item = menu.add(CONTEXT_SORT_GROUP, CONTEXT_SORT_REVERSE, Menu.NONE,
|
||||
R.string.taskList_sort_reverse);
|
||||
item.setCheckable(true);
|
||||
item.setChecked(sortReverse);
|
||||
}
|
||||
});
|
||||
|
||||
listView.setOnTouchListener(getGestureListener());
|
||||
}
|
||||
|
||||
/* ======================================================================
|
||||
* ======================================================= event handlers
|
||||
* ====================================================================== */
|
||||
|
||||
@Override
|
||||
protected boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if(keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
if(filterTag != null) {
|
||||
showTagsView();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if(keyCode >= KeyEvent.KEYCODE_A && keyCode <= KeyEvent.KEYCODE_Z) {
|
||||
createTask((char)('A' + (keyCode - KeyEvent.KEYCODE_A)));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if(resultCode == Constants.RESULT_SYNCHRONIZE) {
|
||||
Synchronizer.synchronize(getParent(), false, new SynchronizerListener() {
|
||||
@Override
|
||||
public void onSynchronizerFinished(int numServicesSynced) {
|
||||
if(numServicesSynced == 0)
|
||||
DialogUtilities.okDialog(getParent(), getResources().getString(
|
||||
R.string.sync_no_synchronizers), null);
|
||||
fillData();
|
||||
}
|
||||
});
|
||||
} else if(requestCode == ACTIVITY_TAGS)
|
||||
switchToActivity(ActivityCode.TAG_LIST, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasFocus) {
|
||||
// refresh, since stuff might have changed...
|
||||
if(hasFocus) {
|
||||
fillData();
|
||||
}
|
||||
}
|
||||
|
||||
/** Call an activity to create the given task */
|
||||
private void createTask(Character startCharacter) {
|
||||
Intent intent = new Intent(getParent(), TaskEdit.class);
|
||||
if(filterTag != null)
|
||||
intent.putExtra(TaskEdit.TAG_NAME_TOKEN, filterTag.getName());
|
||||
if(startCharacter != null)
|
||||
intent.putExtra(TaskEdit.START_CHAR_TOKEN, startCharacter);
|
||||
launchActivity(intent, ACTIVITY_CREATE);
|
||||
}
|
||||
|
||||
/** Show a dialog box and delete the task specified */
|
||||
private void deleteTask(final TaskIdentifier taskId) {
|
||||
new AlertDialog.Builder(getParent())
|
||||
.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) {
|
||||
getTaskController().deleteTask(taskId);
|
||||
fillData();
|
||||
}
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
/** Show the tags view */
|
||||
public void showTagsView() {
|
||||
switchToActivity(ActivityCode.TAG_LIST, null);
|
||||
}
|
||||
|
||||
/** Save the sorting mode to the preferences */
|
||||
private void saveTaskListSort() {
|
||||
int sortId = sortMode.ordinal() + 1;
|
||||
|
||||
if(filterShowDone)
|
||||
sortId |= SORTFLAG_FILTERDONE;
|
||||
if(filterShowHidden)
|
||||
sortId |= SORTFLAG_FILTERHIDDEN;
|
||||
|
||||
if(sortReverse)
|
||||
sortId *= -1;
|
||||
|
||||
Preferences.setTaskListSort(getParent(), sortId);
|
||||
}
|
||||
|
||||
/** Save the sorting mode to the preferences */
|
||||
private void loadTaskListSort() {
|
||||
int sortId = Preferences.getTaskListSort(getParent());
|
||||
if(sortId == 0)
|
||||
return;
|
||||
sortReverse = sortId < 0;
|
||||
sortId = Math.abs(sortId);
|
||||
|
||||
filterShowDone = (sortId & SORTFLAG_FILTERDONE) > 0;
|
||||
filterShowHidden = (sortId & SORTFLAG_FILTERHIDDEN) > 0;
|
||||
|
||||
sortId = sortId & ~(SORTFLAG_FILTERDONE | SORTFLAG_FILTERHIDDEN);
|
||||
|
||||
sortMode = SortMode.values()[sortId - 1];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemSelected(int featureId, MenuItem item) {
|
||||
Intent intent;
|
||||
final TaskModelForList task;
|
||||
Resources r = getResources();
|
||||
|
||||
switch(item.getItemId()) {
|
||||
// --- options menu items
|
||||
case INSERT_ID:
|
||||
createTask(null);
|
||||
return true;
|
||||
case FILTERS_ID:
|
||||
listView.showContextMenu();
|
||||
return true;
|
||||
case TAGS_ID:
|
||||
showTagsView();
|
||||
return true;
|
||||
case SYNC_ID:
|
||||
onActivityResult(ACTIVITY_SYNCHRONIZE, Constants.RESULT_SYNCHRONIZE, null);
|
||||
return true;
|
||||
case MORE_ID:
|
||||
layout.showContextMenu();
|
||||
return true;
|
||||
|
||||
// --- more options menu items
|
||||
case OPTIONS_SYNC_ID:
|
||||
launchActivity(new Intent(getParent(), SyncPreferences.class),
|
||||
ACTIVITY_SYNCHRONIZE);
|
||||
return true;
|
||||
case OPTIONS_SETTINGS_ID:
|
||||
launchActivity(new Intent(getParent(), EditPreferences.class), 0);
|
||||
return true;
|
||||
case OPTIONS_HELP_ID:
|
||||
Intent browserIntent = new Intent(Intent.ACTION_VIEW,
|
||||
Uri.parse(Constants.HELP_URL));
|
||||
launchActivity(browserIntent, 0);
|
||||
return true;
|
||||
|
||||
// --- list context menu items
|
||||
case TaskListAdapter.CONTEXT_EDIT_ID:
|
||||
task = taskArray.get(item.getGroupId());
|
||||
intent = new Intent(getParent(), TaskEdit.class);
|
||||
intent.putExtra(TaskEdit.LOAD_INSTANCE_TOKEN, task.getTaskIdentifier().getId());
|
||||
launchActivity(intent, ACTIVITY_EDIT);
|
||||
return true;
|
||||
case TaskListAdapter.CONTEXT_DELETE_ID:
|
||||
task = taskArray.get(item.getGroupId());
|
||||
deleteTask(task.getTaskIdentifier());
|
||||
return true;
|
||||
case TaskListAdapter.CONTEXT_TIMER_ID:
|
||||
task = taskArray.get(item.getGroupId());
|
||||
if(task.getTimerStart() == null)
|
||||
task.setTimerStart(new Date());
|
||||
else {
|
||||
task.stopTimerAndUpdateElapsedTime();
|
||||
}
|
||||
getTaskController().saveTask(task);
|
||||
fillData();
|
||||
return true;
|
||||
case TaskListAdapter.CONTEXT_POSTPONE_ID:
|
||||
task = taskArray.get(item.getGroupId());
|
||||
DialogUtilities.dayHourPicker(getParent(),
|
||||
r.getString(R.string.taskList_postpone_dialog),
|
||||
new OnNNumberPickedListener() {
|
||||
public void onNumbersPicked(int[] values) {
|
||||
long postponeMillis = (values[0] * 24 + values[1]) *
|
||||
3600L * 1000;
|
||||
Date preferred = task.getPreferredDueDate();
|
||||
if(preferred != null) {
|
||||
preferred = new Date(preferred.getTime() +
|
||||
postponeMillis);
|
||||
task.setPreferredDueDate(preferred);
|
||||
}
|
||||
Date definite = task.getDefiniteDueDate();
|
||||
if(definite != null) {
|
||||
definite = new Date(definite.getTime() +
|
||||
postponeMillis);
|
||||
task.setDefiniteDueDate(definite);
|
||||
}
|
||||
getTaskController().saveTask(task);
|
||||
fillData();
|
||||
}
|
||||
});
|
||||
return true;
|
||||
|
||||
// --- display context menu items
|
||||
case CONTEXT_FILTER_HIDDEN:
|
||||
TaskListSubActivity.filterShowHidden = !filterShowHidden;
|
||||
saveTaskListSort();
|
||||
fillData();
|
||||
return true;
|
||||
case CONTEXT_FILTER_DONE:
|
||||
TaskListSubActivity.filterShowDone = !filterShowDone;
|
||||
saveTaskListSort();
|
||||
fillData();
|
||||
return true;
|
||||
case CONTEXT_FILTER_TAG:
|
||||
switchToActivity(ActivityCode.TASK_LIST, null);
|
||||
return true;
|
||||
case CONTEXT_SORT_AUTO:
|
||||
if(sortMode == SortMode.AUTO)
|
||||
return true;
|
||||
TaskListSubActivity.sortReverse = false;
|
||||
TaskListSubActivity.sortMode = SortMode.AUTO;
|
||||
saveTaskListSort();
|
||||
fillData();
|
||||
return true;
|
||||
case CONTEXT_SORT_ALPHA:
|
||||
if(sortMode == SortMode.ALPHA)
|
||||
return true;
|
||||
TaskListSubActivity.sortReverse = false;
|
||||
TaskListSubActivity.sortMode = SortMode.ALPHA;
|
||||
saveTaskListSort();
|
||||
fillData();
|
||||
return true;
|
||||
case CONTEXT_SORT_DUEDATE:
|
||||
if(sortMode == SortMode.DUEDATE)
|
||||
return true;
|
||||
TaskListSubActivity.sortReverse = false;
|
||||
TaskListSubActivity.sortMode = SortMode.DUEDATE;
|
||||
saveTaskListSort();
|
||||
fillData();
|
||||
return true;
|
||||
case CONTEXT_SORT_REVERSE:
|
||||
TaskListSubActivity.sortReverse = !sortReverse;
|
||||
saveTaskListSort();
|
||||
fillData();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue