Deleted unused layouts and activities

pull/14/head
Tim Su 14 years ago
parent bafbbf7307
commit fc25791878

@ -1,42 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<Button android:id="@+id/date"
android:layout_weight="0.7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button android:id="@+id/time"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ImageButton android:id="@+id/button1"
style="?android:attr/buttonStyleInset"
android:src="@android:drawable/ic_delete"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_marginTop="2dip"
android:layout_marginRight="2dip"
android:layout_marginBottom="2dip"
android:gravity="center_vertical"
/>
</LinearLayout>

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_weight="1"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ToggleButton android:id="@+id/button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="18dip"
android:disabledAlpha="0.3"/>
</FrameLayout>

@ -1,29 +0,0 @@
<!--
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
-->
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="@android:color/black"
android:gravity="center_vertical"
android:paddingLeft="10dip"
android:singleLine="true"
android:layout_width="fill_parent"
android:layout_height="50dip" />

@ -1,139 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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
-->
<com.timsu.astrid.widget.ViewFlipper android:id="@+id/main"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<!-- task list -->
<LinearLayout android:id="@+id/tasklist_layout"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView android:id="@+id/loading"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_weight="1"
android:text="@string/loading"
style="@style/TextAppearance.TaskList_Task"
android:gravity="center_vertical"/>
<ListView android:id="@+id/tasklist"
android:layout_weight="100"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<!-- Footer -->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal">
<!-- Quick Add Task -->
<EditText android:id="@+id/quickAddText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="100"
android:hint="@string/quick_add_hint"
android:singleLine="true"
android:autoText="true"
android:capitalize="sentences"/>
<!-- Quick Add Button -->
<ImageButton android:id="@+id/quickAddButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:src="@android:drawable/ic_input_add"/>
</LinearLayout>
</LinearLayout>
<!-- tag list -->
<LinearLayout android:id="@+id/taglist_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView android:id="@+id/loading"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:text="@string/loading"
style="@style/TextAppearance.TaskList_Task"
android:gravity="center_vertical"/>
<ListView android:id="@+id/taglist"
android:layout_weight="1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
<!-- task list w/ tag-->
<LinearLayout android:id="@+id/tasklistwtag_layout"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView android:id="@+id/loading"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_weight="1"
android:text="@string/loading"
style="@style/TextAppearance.TaskList_Task"
android:gravity="center_vertical"/>
<ListView android:id="@+id/tasklist"
android:layout_weight="100"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<!-- Footer -->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal">
<!-- Quick Add Task -->
<EditText android:id="@+id/quickAddText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="100"
android:hint="@string/quick_add_hint"
android:singleLine="true"
android:autoText="true"
android:capitalize="sentences"/>
<!-- Quick Add Button -->
<ImageButton android:id="@+id/quickAddButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:src="@android:drawable/ic_input_add"/>
</LinearLayout>
</LinearLayout>
</com.timsu.astrid.widget.ViewFlipper>

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dip"
android:orientation="vertical">
<TextView android:id="@+id/message"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:paddingBottom="5dip" />
<View
android:layout_width="fill_parent"
android:layout_height="2dip"
android:background="#888888"
/>
<ListView android:id="@+id/items"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:textSize="12sp" />
</LinearLayout>

@ -1,135 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/row_layout"
android:orientation="horizontal"
android:focusable="true"
android:background="@android:drawable/list_selector_background"
android:paddingLeft="6dip"
android:paddingTop="2dip"
android:paddingBottom="2dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:minHeight="45dip" >
<!-- icons on the left -->
<LinearLayout android:id="@+id/icon_layout"
android:orientation="vertical"
android:minWidth="41dip"
android:gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="fill_parent">
<CheckBox android:id="@+id/cb1"
android:paddingBottom="5dip"
android:layout_gravity="center_vertical"
android:layout_width="48dip"
android:layout_height="52dip"
android:scaleType="center" />
<ImageView android:id="@+id/imageLeft"
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:scaleType="center"/>
</LinearLayout>
<!-- all text -->
<LinearLayout android:id="@+id/text_layout"
android:orientation="vertical"
android:paddingLeft="5dip"
android:paddingTop="6dip"
android:paddingBottom="6dip"
android:layout_weight="1.0"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<!-- task name -->
<TextView android:id="@+id/task_name"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
style="@style/TextAppearance.TaskList_Task"
android:gravity="center_vertical"/>
<!-- absolute / goal deadline -->
<TextView android:id="@+id/text_deadlines"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
style="@style/TextAppearance.TaskList_Detail"
color="@color/taskList_dueDate"
android:singleLine="true"/>
<!-- other details (gray) -->
<TextView android:id="@+id/details"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
style="@style/TextAppearance.TaskList_Detail"/>
<LinearLayout android:id="@+id/expanded_layout"
android:orientation="vertical"
android:paddingTop="5dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<View android:background="@android:drawable/divider_horizontal_dark"
android:layout_width="fill_parent"
android:layout_height="1dip"/>
<TextView android:id="@+id/expanded_details"
android:paddingTop="5dip"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
style="@style/TextAppearance.TaskList_Detail"/>
<LinearLayout android:id="@+id/expanded_buttons"
android:orientation="horizontal"
android:paddingTop="5dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<Button android:id="@+id/timer"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:layout_weight="0.5"/>
<Button android:id="@+id/edit"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:layout_gravity="top"
android:text="@string/edit_label"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
<!-- importance -->
<View android:id="@+id/importance"
android:layout_width="12dip"
android:layout_height="fill_parent"
android:paddingLeft="6dip"/>
</LinearLayout>

@ -1,49 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView android:id="@+id/greeting"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<TextView android:id="@+id/taskname"
android:paddingTop="20dip"
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<Button android:id="@+id/btn_viewtask"
android:paddingTop="40dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/addtask_label"/>
<Button android:id="@+id/btn_tasklist"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/addtask_label"/>
</LinearLayout>

@ -1,68 +0,0 @@
/*
* 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 android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import com.flurry.android.FlurryAgent;
import com.timsu.astrid.R;
import com.timsu.astrid.utilities.Calendars;
import com.timsu.astrid.utilities.Constants;
import com.timsu.astrid.utilities.Preferences;
/**
* Displays the preference screen for users to edit their preferences
*
* @author timsu
*
*/
public class EditPreferences extends PreferenceActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
Preference backupPreference = findPreference(getString(R.string.p_backup));
String backupSummary = Preferences.getBackupSummary(this);
if(backupSummary != null && backupPreference != null)
backupPreference.setSummary(backupSummary);
ListPreference defaultCalendarPreference = (ListPreference) findPreference(getString(R.string.prefs_defaultCalendar));
Calendars.initCalendarsPreference(this, defaultCalendarPreference);
}
@Override
protected void onStart() {
super.onStart();
// set up flurry
FlurryAgent.onStartSession(this, Constants.FLURRY_KEY);
}
@Override
protected void onStop() {
super.onStop();
FlurryAgent.onEndSession(this);
}
}

@ -1,150 +0,0 @@
/*
* 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 android.app.Activity;
import android.content.Intent;
import android.content.res.Resources;
import android.database.Cursor;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import com.timsu.astrid.data.tag.TagController;
import com.timsu.astrid.data.task.TaskController;
/**
* Interface for views that are displayed from the main view page.
*
* @author timsu
*/
abstract public class SubActivity {
private TaskList parent;
int code;
private View view;
public SubActivity(TaskList parent, int code, View view) {
this.parent = parent;
this.code = code;
this.view = view;
view.setTag(this);
}
// --- pass-through to activity listeners
/** Called when this subactivity is displayed to the user */
void onDisplay(Bundle variables) {
//
}
boolean onPrepareOptionsMenu(Menu menu) {
return false;
}
void onActivityResult(int requestCode, int resultCode, Intent data) {
//
}
boolean onMenuItemSelected(int featureId, MenuItem item) {
return false;
}
void onWindowFocusChanged(boolean hasFocus) {
//
}
boolean onKeyDown(int keyCode, KeyEvent event) {
return false;
}
void onSaveInstanceState(Bundle outState) {
//
}
Object onRetainNonConfigurationInstance() {
return null;
}
// --- 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) {
if(c != null)
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);
}
public Object getLastNonConfigurationInstance() {
return parent.getLastNonConfigurationInstance();
}
// --- 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(int activity, Bundle state) {
parent.switchToActivity(activity, state);
}
// --- internal methods
protected int getActivityCode() {
return code;
}
protected View getView() {
return view;
}
}

@ -119,9 +119,9 @@ public class SyncLoginActivity extends Activity {
@Override
public void run() {
final String result = callback.verifyLogin(handler);
TaskListSubActivity.syncPreferencesOpened = true;
// TaskListSubActivity.syncPreferencesOpened = true;
if(result == null) {
TaskList.synchronizeNow = true;
// TaskList.synchronizeNow = true;
finish();
} else {
// display the error
@ -131,7 +131,7 @@ public class SyncLoginActivity extends Activity {
DialogUtilities.okDialog(SyncLoginActivity.this, result,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
TaskListSubActivity.shouldRefreshTaskList = true;
// TaskListSubActivity.shouldRefreshTaskList = true;
finish();
}
});

@ -1,492 +0,0 @@
/*
* 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.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.database.StaleDataException;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnCreateContextMenuListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.flurry.android.FlurryAgent;
import com.timsu.astrid.R;
import com.timsu.astrid.data.tag.TagIdentifier;
import com.timsu.astrid.data.tag.TagModelForView;
import com.timsu.astrid.data.task.TaskIdentifier;
import com.timsu.astrid.utilities.DialogUtilities;
import com.timsu.astrid.utilities.Preferences;
import com.todoroo.astrid.activity.TaskEditActivity;
/**
* List all tags and allows a user to see all tasks for a given tag
*
* @author timsu
*
*/
public class TagListSubActivity extends SubActivity {
private static final int ACTIVITY_CREATE = 0;
private static final int MENU_SORT_ALPHA_ID = Menu.FIRST;
private static final int MENU_SORT_SIZE_ID = Menu.FIRST + 1;
private static final int CONTEXT_CREATE_ID = Menu.FIRST + 10;
private static final int CONTEXT_DELETE_ID = Menu.FIRST + 11;
private static final int CONTEXT_SHOWHIDE_ID = Menu.FIRST + 12;
private static final int CONTEXT_SHORTCUT_ID = Menu.FIRST + 13;
protected ListView listView;
protected LinkedList<TagModelForView> tagArray;
HashMap<TagModelForView, Integer> tagToTaskCount;
protected Handler handler;
protected TextView loadingText;
protected boolean untaggedTagDisplayed;
protected static SortMode sortMode = SortMode.SIZE;
protected static boolean sortReverse = false;
public TagListSubActivity(TaskList parent, int code, View view) {
super(parent, code, view);
}
@Override
public void onDisplay(Bundle variables) {
listView = (ListView)findViewById(R.id.taglist);
handler = new Handler();
loadingText = (TextView)findViewById(R.id.loading);
// time to go!
new Thread(new Runnable() {
public void run() {
loadTagListSort();
fillData();
}
}).start();
FlurryAgent.onEvent("view-tags"); //$NON-NLS-1$
}
// --- stuff for sorting
private enum SortMode {
ALPHA {
@Override
int compareTo(TagListSubActivity self, TagModelForView arg0, TagModelForView arg1) {
return arg0.getName().compareTo(arg1.getName());
}
},
SIZE {
@Override
int compareTo(TagListSubActivity self, TagModelForView arg0, TagModelForView arg1) {
synchronized(self) {
return self.tagToTaskCount.get(arg1) - self.tagToTaskCount.get(arg0);
}
}
};
abstract int compareTo(TagListSubActivity self, TagModelForView arg0, TagModelForView arg1);
};
/** Counts how many tasks appear in active task list */
public static int countActiveTasks(HashSet<TaskIdentifier> activeTasks, LinkedList<TaskIdentifier> tasks) {
int count = 0;
if(tasks != null) {
for(TaskIdentifier task : tasks)
if(activeTasks.contains(task))
count++;
}
return count;
}
private synchronized void sortTagArray() {
// get all tasks
HashSet<TaskIdentifier> activeTasks =
getTaskController().getActiveTaskIdentifiers();
if(activeTasks == null)
activeTasks = new HashSet<TaskIdentifier>();
// get task count for each tag
tagToTaskCount = new HashMap<TagModelForView, Integer>();
for(TagModelForView tag : tagArray) {
LinkedList<TaskIdentifier> tasks;
tasks = getTagController().getTaggedTasks(tag.getTagIdentifier());
int count = countActiveTasks(activeTasks, tasks);
tagToTaskCount.put(tag, count);
}
// do sort
Collections.sort(tagArray, new Comparator<TagModelForView>() {
public int compare(TagModelForView arg0, TagModelForView arg1) {
return sortMode.compareTo(TagListSubActivity.this, arg0, arg1);
}
});
// show "untagged" as a category at the top, in the proper language/localization
String untaggedLabel = getResources().getString(R.string.tagList_untagged);
TagModelForView untaggedModel = TagModelForView.getUntaggedModel(untaggedLabel);
int count = countActiveTasks(activeTasks, getTagController().getUntaggedTasks());
if(count > 0) {
untaggedTagDisplayed = true;
tagArray.addFirst(untaggedModel);
tagToTaskCount.put(untaggedModel, count);
}
if(sortReverse)
Collections.reverse(tagArray);
}
/** Save the sorting mode to the preferences */
private void saveTagListSort() {
int sortId = sortMode.ordinal() + 1;
if (sortReverse)
sortId *= -1;
Preferences.setTagListSort(getParent(), sortId);
}
/** Save the sorting mode to the preferences */
protected void loadTagListSort() {
try {
int sortId = Preferences.getTagListSort(getParent());
if (sortId == 0)
return;
sortReverse = sortId < 0;
sortId = Math.abs(sortId) - 1;
sortMode = SortMode.values()[sortId];
} catch (Exception e) {
// do nothing
}
}
// --- fill data
/** Fill in the Tag List with our tags */
protected synchronized void fillData() {
try {
tagArray = getTagController().getAllTags();
sortTagArray(); // count and sort each tag
} catch (StaleDataException e) {
// happens when you rotate the screen while the thread is
// still running. i don't think it's avoidable?
Log.w("astrid", "StaleDataException", e); //$NON-NLS-1$ //$NON-NLS-2$
return;
} catch (Exception e) {
Log.e("astrid", "Error loading list", e); //$NON-NLS-1$ //$NON-NLS-2$
}
handler.post(new Runnable() {
public void run() {
synchronized(TagListSubActivity.this) {
// set up our adapter
final TagListAdapter tagAdapter = new TagListAdapter(getParent(),
android.R.layout.simple_list_item_1, tagArray,
tagToTaskCount);
// set up ui components
setUpListUI(tagAdapter);
}
loadingText.setVisibility(View.GONE);
}
});
}
/** Set up list handlers and adapter. run on the UI thread */
protected void setUpListUI(ListAdapter adapter) {
// set up the title
Resources r = getResources();
int tags = tagArray.size();
if(untaggedTagDisplayed && tags > 0)
tags--;
StringBuilder title = new StringBuilder().
append(r.getString(R.string.tagList_titlePrefix)).
append(" ").append(r.getQuantityString(R.plurals.Ntags,
tags, tags));
final CharSequence finalTitle = title;
handler.post(new Runnable() {
public void run() {
setTitle(finalTitle);
}
});
listView.setAdapter(adapter);
// list view listener
listView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
TagModelForView tag = (TagModelForView)view.getTag();
Bundle bundle = new Bundle();
bundle.putLong(TaskListSubActivity.TAG_TOKEN, tag.getTagIdentifier().getId());
switchToActivity(TaskList.AC_TASK_LIST_W_TAG, bundle);
}
});
listView.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
AdapterContextMenuInfo adapterMenuInfo =
(AdapterContextMenuInfo)menuInfo;
int position = adapterMenuInfo.position;
menu.add(position, CONTEXT_CREATE_ID, Menu.NONE,
R.string.tagList_context_create);
menu.add(position, CONTEXT_DELETE_ID, Menu.NONE,
R.string.tagList_context_delete);
int showHideLabel = R.string.tagList_context_hideTag;
if(tagArray.get(position).shouldHideFromMainList())
showHideLabel = R.string.tagList_context_showTag;
menu.add(position, CONTEXT_SHOWHIDE_ID, Menu.NONE,
showHideLabel);
menu.add(position, CONTEXT_SHORTCUT_ID, Menu.NONE,
R.string.tagList_context_shortcut);
menu.setHeaderTitle(tagArray.get(position).getName());
}
});
listView.setOnTouchListener(getGestureListener());
}
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent intent) {
fillData();
}
// --- list adapter
private void createTask(TagModelForView tag) {
Intent intent = new Intent(getParent(), TaskEditActivity.class);
launchActivity(intent, ACTIVITY_CREATE);
}
private void deleteTag(final TagIdentifier tagId) {
new AlertDialog.Builder(getParent())
.setTitle(R.string.delete_title)
.setMessage(R.string.delete_this_tag_title)
.setIcon(android.R.drawable.ic_dialog_alert)
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
getTagController().deleteTag(tagId);
fillData();
}
})
.setNegativeButton(android.R.string.cancel, null)
.show();
}
@Override
/** Handle back button by moving to task list */
protected boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_BACK) {
switchToActivity(TaskList.AC_TASK_LIST, null);
return true;
}
return false;
}
@Override
/** Picked item in the options list */
public boolean onMenuItemSelected(int featureId, MenuItem item) {
switch(item.getItemId()) {
case MENU_SORT_ALPHA_ID:
if(sortMode == SortMode.ALPHA)
sortReverse = !sortReverse;
else {
sortMode = SortMode.ALPHA;
sortReverse = false;
}
saveTagListSort();
fillData();
return true;
case MENU_SORT_SIZE_ID:
if(sortMode == SortMode.SIZE)
sortReverse = !sortReverse;
else {
sortMode = SortMode.SIZE;
sortReverse = false;
}
saveTagListSort();
fillData();
return true;
case CONTEXT_CREATE_ID:
TagModelForView tag = tagArray.get(item.getGroupId());
createTask(tag);
return true;
case CONTEXT_DELETE_ID:
tag = tagArray.get(item.getGroupId());
deleteTag(tag.getTagIdentifier());
return true;
case CONTEXT_SHOWHIDE_ID:
tag = tagArray.get(item.getGroupId());
tag.toggleHideFromMainList();
try {
getTagController().saveTag(tag);
} catch (Exception e) {
DialogUtilities.okDialog(getParent(), "Error: You probably " +
"already have a tag named '" + tag.getName() + "'!",
null);
}
fillData();
return true;
case CONTEXT_SHORTCUT_ID:
tag = tagArray.get(item.getGroupId());
Resources r = getResources();
Intent shortcutIntent = new Intent(Intent.ACTION_VIEW);
shortcutIntent.setComponent(new ComponentName(
getParent().getApplicationContext(), TagView.class));
shortcutIntent.setData(Uri.parse("tag:" + tag.getTagIdentifier().getId())); //$NON-NLS-1$
Intent createShortcutIntent = new Intent();
createShortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
String label = tag.getName();
if(tag.shouldHideFromMainList())
label = label.substring(1);
// add the @ sign if the task starts with a letter, for clarity
if(Character.isLetterOrDigit(label.charAt(0)))
label = "@" + label; //$NON-NLS-1$
createShortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, label);
createShortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON,
((BitmapDrawable)r.getDrawable(R.drawable.icon_blank)).getBitmap());
createShortcutIntent.setAction("com.android.launcher.action.INSTALL_SHORTCUT"); //$NON-NLS-1$
getParent().sendBroadcast(createShortcutIntent);
Toast.makeText(getParent(), R.string.tagList_shortcut_created, Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
// --- creating stuff
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem item;
item = menu.add(Menu.NONE, MENU_SORT_ALPHA_ID, Menu.NONE,
R.string.tagList_menu_sortAlpha);
item.setIcon(android.R.drawable.ic_menu_sort_alphabetically);
item.setAlphabeticShortcut('a');
item = menu.add(Menu.NONE, MENU_SORT_SIZE_ID, Menu.NONE,
R.string.tagList_menu_sortSize);
item.setIcon(android.R.drawable.ic_menu_sort_by_size);
item.setAlphabeticShortcut('s');
return true;
}
// --------------------------------------------------- tag list adapter
class TagListAdapter extends ArrayAdapter<TagModelForView> {
private final List<TagModelForView> objects;
private final int resource;
private final LayoutInflater inflater;
private HashMap<TagModelForView, Integer> tagCount;
public TagListAdapter(Context context, int resource,
List<TagModelForView> objects, HashMap<TagModelForView, Integer>
tagToTaskCount) {
super(context, resource, objects);
inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.objects = objects;
this.resource = resource;
this.tagCount = tagToTaskCount;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if(view == null) {
view = inflater.inflate(resource, parent, false);
}
setupView(view, objects.get(position), false);
return view;
}
public void setupView(View view, final TagModelForView tag, boolean retry) {
Resources r = getResources();
view.setTag(tag);
final TextView name = ((TextView)view.findViewById(android.R.id.text1));
try {
if(tagCount == null)
tagCount = tagToTaskCount;
name.setText(new StringBuilder(tag.getName()).
append(" (").append(tagCount.get(tag)).append(")"));
if(tagCount == null || tagCount.get(tag) == null || tagCount.get(tag) == 0)
name.setTextColor(r.getColor(R.color.task_list_done));
else
name.setTextColor(r.getColor(android.R.color.white));
} catch (Exception e) {
Log.e("astrid", "Error loading tag list", e); //$NON-NLS-1$ //$NON-NLS-2$
}
}
}
}

@ -1,62 +0,0 @@
/*
* 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 android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
/**
* This activity is launched from a desktop shortcut and takes the user to
* view a specific tag
*
* @author timsu
*
*/
public class TagView extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
launchTaskList(getIntent());
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
launchTaskList(intent);
}
private void launchTaskList(Intent intent) {
String tag = intent.getData().toString();
long tagId = Long.parseLong(tag.substring(tag.indexOf(":")+1));
Bundle variables = new Bundle();
variables.putLong(TaskListSubActivity.TAG_TOKEN, tagId);
Intent taskListIntent = new Intent(this, TaskList.class);
taskListIntent.putExtra(TaskList.VARIABLES_TAG, variables);
startActivity(taskListIntent);
finish();
}
}

@ -1,384 +0,0 @@
/*
* 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 android.app.Activity;
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
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.GestureDetector.SimpleOnGestureListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.RemoteViews;
import android.widget.ViewFlipper;
import com.flurry.android.FlurryAgent;
import com.timsu.astrid.R;
import com.timsu.astrid.appwidget.AstridAppWidgetProvider;
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.AstridUtilities.AstridUncaughtExceptionHandler;
/**
* TaskList is the main launched activity for Astrid. It uses a ViewFlipper
* to flip between child views, which in this case are the TaskListSubActivity
* and the TagListSubActivity.
*
* @author timsu
*/
public class TaskList extends Activity {
// constants for the different pages that we can display
public static final int AC_TASK_LIST = 0;
public static final int AC_TAG_LIST = 1;
public static final int AC_TASK_LIST_W_TAG = 2;
/** Bundle Key: activity code id of current activity */
private static final String LAST_ACTIVITY_TAG = "l";
/** Bundle Key: variables of current activity */
private static final String LAST_BUNDLE_TAG = "b";
/** Bundle Key: variables to pass to the sub-activity */
public static final String VARIABLES_TAG = "v";
/** Minimum distance a fling must cover to trigger motion */
private static final int FLING_DIST_THRESHOLD = 120;
/** Maximum distance in the other axis for a fling */
private static final int MAX_FLING_OTHER_AXIS = 300;
/** Minimum velocity a fling must have to trigger motion */
private static final int FLING_VEL_THRESHOLD = 200;
// view components
private ViewFlipper viewFlipper;
private GestureDetector gestureDetector;
View.OnTouchListener gestureListener;
private SubActivity taskList;
private SubActivity tagList;
private SubActivity taskListWTag;
private Bundle lastActivityBundle;
// animations
private Animation mFadeInAnim;
private Animation mFadeOutAnim;
// data controllers
TaskController taskController;
TagController tagController;
// static variables
public static boolean synchronizeNow = false;
/** If set, the application will close when this activity gets focus */
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);
// set uncaught exception handler
Thread.setDefaultUncaughtExceptionHandler(new AstridUncaughtExceptionHandler());
// open controllers & perform application startup rituals
// StartupReceiver.onStartupApplication(this);
shouldCloseInstance = false;
taskController = new TaskController(this);
taskController.open();
tagController = new TagController(this);
tagController.open();
setupUIComponents();
Bundle variables = new Bundle();
if(savedInstanceState != null && savedInstanceState.containsKey(LAST_ACTIVITY_TAG)) {
viewFlipper.setDisplayedChild(savedInstanceState.getInt(LAST_ACTIVITY_TAG));
Bundle lastBundle = savedInstanceState.getBundle(LAST_BUNDLE_TAG);
if(lastBundle != null)
variables.putAll(lastBundle);
}
if(getIntent().hasExtra(VARIABLES_TAG))
variables.putAll(getIntent().getBundleExtra(VARIABLES_TAG));
getCurrentSubActivity().onDisplay(variables);
// sync now if requested
if(synchronizeNow) {
synchronizeNow = false;
Synchronizer sync = new Synchronizer(false);
sync.setTagController(tagController);
sync.setTaskController(taskController);
sync.synchronize(this, null);
}
// if we have no filter tag, we're not on the last task
if(getCurrentSubActivity() == taskListWTag &&
((TaskListSubActivity)taskListWTag).getFilterTag() == null) {
switchToActivity(AC_TASK_LIST, null);
}
}
@Override
protected void onStart() {
super.onStart();
// set up flurry
FlurryAgent.onStartSession(this, Constants.FLURRY_KEY);
}
@Override
protected void onStop() {
super.onStop();
updateWidget();
FlurryAgent.onEndSession(this);
}
private void updateWidget()
{
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);
RemoteViews views = AstridAppWidgetProvider.UpdateService.buildUpdate(this);
ComponentName widgetName = new ComponentName(this, AstridAppWidgetProvider.class);
appWidgetManager.updateAppWidget(widgetName, views);
}
/** Set up user interface components */
private void setupUIComponents() {
gestureDetector = new GestureDetector(new AstridGestureDetector());
viewFlipper = (ViewFlipper)findViewById(R.id.main);
taskList = new TaskListSubActivity(this, AC_TASK_LIST,
findViewById(R.id.tasklist_layout));
tagList = new TagListSubActivity(this, AC_TAG_LIST,
findViewById(R.id.taglist_layout));
taskListWTag = new TaskListSubActivity(this, AC_TASK_LIST_W_TAG,
findViewById(R.id.tasklistwtag_layout));
mFadeInAnim = AnimationUtils.loadAnimation(this, R.anim.fade_in);
mFadeOutAnim = AnimationUtils.loadAnimation(this, R.anim.fade_out);
viewFlipper.setInAnimation(mFadeInAnim);
viewFlipper.setOutAnimation(mFadeOutAnim);
gestureListener = new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (gestureDetector.onTouchEvent(event)) {
return true;
}
return false;
}
};
}
/** Gesture detector switches between sub-activities */
class AstridGestureDetector extends SimpleOnGestureListener {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
try {
if(Math.abs(e1.getY() - e2.getY()) > MAX_FLING_OTHER_AXIS)
return false;
Log.i("astrid", "Got fling. X: " + (e2.getX() - e1.getX()) +
", vel: " + velocityX + " Y: " + (e2.getY() - e1.getY()));
// flick R to L
if(e1.getX() - e2.getX() > FLING_DIST_THRESHOLD &&
Math.abs(velocityX) > FLING_VEL_THRESHOLD) {
switch(getCurrentSubActivity().getActivityCode()) {
case AC_TASK_LIST:
switchToActivity(AC_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 AC_TASK_LIST_W_TAG:
switchToActivity(AC_TAG_LIST, null);
return true;
case AC_TAG_LIST:
switchToActivity(AC_TASK_LIST, null);
return true;
default:
return false;
}
}
} catch (Exception e) {
// ignore!
}
return false;
}
}
/* ======================================================================
* ==================================================== subactivity stuff
* ====================================================================== */
/** Switches to another activity, with appropriate animation */
void switchToActivity(int activity, Bundle variables) {
closeOptionsMenu();
// and flip to them
switch(getCurrentSubActivity().getActivityCode()) {
case AC_TASK_LIST:
switch(activity) {
case AC_TAG_LIST:
viewFlipper.showNext();
break;
case AC_TASK_LIST_W_TAG:
viewFlipper.setDisplayedChild(taskListWTag.code);
}
break;
case AC_TAG_LIST:
switch(activity) {
case AC_TASK_LIST:
viewFlipper.showPrevious();
break;
case AC_TASK_LIST_W_TAG:
viewFlipper.showNext();
break;
}
break;
case AC_TASK_LIST_W_TAG:
switch(activity) {
case AC_TAG_LIST:
viewFlipper.showPrevious();
break;
case AC_TASK_LIST:
viewFlipper.setDisplayedChild(taskList.code);
}
break;
}
// initialize the components
switch(activity) {
case AC_TASK_LIST:
taskList.onDisplay(variables);
break;
case AC_TAG_LIST:
tagList.onDisplay(variables);
break;
case AC_TASK_LIST_W_TAG:
taskListWTag.onDisplay(variables);
}
lastActivityBundle = variables;
}
/** Helper method gets the currently visible subactivity */
private SubActivity getCurrentSubActivity() {
return (SubActivity)viewFlipper.getCurrentView().getTag();
}
/* ======================================================================
* ======================================================= event handling
* ====================================================================== */
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(LAST_ACTIVITY_TAG, getCurrentSubActivity().code);
outState.putBundle(LAST_BUNDLE_TAG, lastActivityBundle);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(getCurrentSubActivity().onKeyDown(keyCode, event))
return true;
else
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
menu.clear();
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(AC_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 onMenuItemSelected(int featureId, MenuItem item) {
if(getCurrentSubActivity().onMenuItemSelected(featureId, item))
return true;
else
return super.onMenuItemSelected(featureId, item);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (gestureDetector.onTouchEvent(event))
return true;
else
return false;
}
@Override
public Object onRetainNonConfigurationInstance() {
return getCurrentSubActivity().onRetainNonConfigurationInstance();
}
@Override
protected void onDestroy() {
super.onDestroy();
taskController.close();
tagController.close();
}
}

@ -1,741 +0,0 @@
/*
* ASTRID: Android's Simple Task Recording Dashboard
*
* 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.text.Format;
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.res.Resources;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.util.Log;
import android.view.ContextMenu;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnCreateContextMenuListener;
import android.view.View.OnKeyListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import com.flurry.android.FlurryAgent;
import com.timsu.astrid.R;
import com.timsu.astrid.data.alerts.AlertController;
import com.timsu.astrid.data.enums.Importance;
import com.timsu.astrid.data.tag.TagController;
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.data.task.AbstractTaskModel.RepeatInfo;
import com.timsu.astrid.utilities.AstridUtilities;
import com.timsu.astrid.utilities.DateUtilities;
import com.timsu.astrid.utilities.Preferences;
import com.timsu.astrid.utilities.TaskFieldsVisibility;
/**
* Adapter for displaying a list of TaskModelForList entities
*
* @author timsu
*
*/
public class TaskListAdapter extends ArrayAdapter<TaskModelForList> {
public static final int CONTEXT_EDIT_ID = Menu.FIRST + 50;
public static final int CONTEXT_DELETE_ID = Menu.FIRST + 51;
public static final int CONTEXT_TIMER_ID = Menu.FIRST + 52;
public static final int CONTEXT_POSTPONE_ID = Menu.FIRST + 53;
// keys for caching task properties
private static final int KEY_NAME = 0;
private static final int KEY_DEADLINE = 1;
private static final int KEY_OVERDUE = 2;
private static final int KEY_REPEAT = 3;
private static final int KEY_REMINDERS = 4;
private static final int KEY_TIMES = 5;
private static final int KEY_TAGS = 6;
private static final int KEY_HIDDEN = 7;
private static final int KEY_EXPANDED = 8;
private static final int KEY_CREATION = 9;
private static final String CACHE_TRUE = "y";
/** Number of seconds after which we display the full date deadline */
private static final int FULL_DATE_THRESHOLD = 7*24*3600;
// alarm date formatter
private static Format alarmFormat = null;
private final Activity activity;
private final List<TaskModelForList> objects;
private final int resource;
private final LayoutInflater inflater;
private final TaskListAdapterHooks hooks;
private final TextView deletedItemView = new TextView(getContext());
private final Integer fontSizePreference;
private final AlertController alarmController;
private TaskModelForList recentlyCompleted = null;
/**
* Call-back interface for interacting with parent activity
*
* @author timsu
*
*/
public interface TaskListAdapterHooks {
List<TaskModelForList> getTaskArray();
String getTagsFor(TaskModelForList task);
TaskController taskController();
TagController tagController();
void performItemClick(View v, int position);
void onCreatedTaskListView(View v, TaskModelForList task);
void editItem(TaskModelForList task);
void toggleTimerOnItem(TaskModelForList task);
void setSelectedItem(TaskIdentifier taskId);
}
/**
* Constructor
*
* @param activity
* @param context
* @param resource
* @param objects
* @param hooks
*/
public TaskListAdapter(Activity activity, int resource,
List<TaskModelForList> objects, TaskListAdapterHooks hooks) {
super(activity, resource, objects);
inflater = (LayoutInflater)activity.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
this.objects = objects;
this.resource = resource;
this.activity = activity;
this.hooks = hooks;
fontSizePreference = Preferences.getTaskListFontSize(getContext());
alarmController = new AlertController(activity);
}
/** Sets the expanded state as desired */
public void setExpanded(View view, TaskModelForList task, boolean state) {
try {
if(state) {
task.clearCache();
task.putCachedLabel(KEY_EXPANDED, CACHE_TRUE);
hooks.setSelectedItem(task.getTaskIdentifier());
} else {
task.putCachedLabel(KEY_EXPANDED, null);
hooks.setSelectedItem(null);
}
if(view != null) {
setFieldContentsAndVisibility(view, task);
// if the item is near the bottom of the list, we need to give
// it focus so that the list knows there's new stuff down there
int position = objects.indexOf(task);
if(objects.size() - position < 2 && view.getParent() != null)
((ListView)view.getParent()).setSelection(position);
view.requestFocus();
}
} catch (Exception e) {
AstridUtilities.reportFlurryError("task-adapter-set-expanded", e);
Log.e("astrid", "Error in setExpanded", e);
}
}
/** Toggle the expanded state of this task */
public void toggleExpanded(View view, TaskModelForList task) {
if(CACHE_TRUE.equals(task.getCachedLabel(KEY_EXPANDED))) {
setExpanded(view, task, false);
} else {
setExpanded(view, task, true);
}
}
// ----------------------------------------------------------------------
// --- code for setting up each view
// ----------------------------------------------------------------------
@Override
/** Creates or reuses the view for a row in the list */
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if(objects.size() <= position || objects.get(position) == null)
return deletedItemView;
if(view == null) {
view = inflater.inflate(resource, parent, false);
initializeView(view);
addListeners(view);
}
setupView(view, objects.get(position));
return view;
}
/**
* Perform initial setup on the row. Called once for the whole list
*
* @param view
*/
private void initializeView(View view) {
final TextView name = ((TextView)view.findViewById(R.id.task_name));
if(fontSizePreference != null && fontSizePreference > 0)
name.setTextSize(fontSizePreference);
deletedItemView.setText(getContext().getResources().getString(R.string.taskList_deleted));
}
/**
* Setup the given view for the specified task. Called every row
*
* @param view
* @param task
*/
private void setupView(View view, final TaskModelForList task) {
Resources r = activity.getResources();
view.setTag(task);
setFieldContentsAndVisibility(view, task);
if(task == null) {
return;
}
final CheckBox progress = ((CheckBox)view.findViewById(R.id.cb1));
progress.setChecked(task.isTaskCompleted());
final ImageView timer = ((ImageView)view.findViewById(R.id.imageLeft));
if(task.getTimerStart() != null) {
timer.setImageDrawable(r.getDrawable(R.drawable.icon_timer));
view.setMinimumHeight(90);
} else {
timer.setImageDrawable(null);
view.setMinimumHeight(45);
}
final TextView name = ((TextView)view.findViewById(R.id.task_name));
setTaskAppearance(task, name, progress);
hooks.onCreatedTaskListView(view, task);
}
/** Helper method to set the visibility based on if there's stuff inside */
private static void setVisibility(TextView v) {
if(v.getText().length() > 0)
v.setVisibility(View.VISIBLE);
else
v.setVisibility(View.GONE);
}
/** Helper method to add a line and maybe a newline */
private static void appendLine(StringBuilder sb, String line) {
if(line.length() == 0)
return;
if(sb.length() > 0)
sb.append("\n");
sb.append(line);
}
/** Helper method to set the contents and visibility of each field */
private void setFieldContentsAndVisibility(View view, TaskModelForList task) {
if(task == null) {
view.setVisibility(View.GONE);
return;
}
Resources r = getContext().getResources();
TaskFieldsVisibility visibleFields = Preferences.getTaskFieldsVisibility(activity);
boolean isExpanded = CACHE_TRUE.equals(task.getCachedLabel(KEY_EXPANDED));
StringBuilder details = new StringBuilder();
StringBuilder expandedDetails = new StringBuilder();
// expanded container
final View expandedContainer = view.findViewById(R.id.expanded_layout);
if(expandedContainer != null)
expandedContainer.setVisibility(isExpanded ? View.VISIBLE : View.GONE);
// name
final TextView name = ((TextView)view.findViewById(R.id.task_name)); {
String cachedResult = task.getCachedLabel(KEY_NAME);
if(cachedResult == null) {
String nameValue = task.getName();
if(task.getHiddenUntil() != null && task.getHiddenUntil().getTime() > System.currentTimeMillis()) {
nameValue = "(" + r.getString(R.string.taskList_hiddenPrefix) + ") " + nameValue;
task.putCachedLabel(KEY_HIDDEN, CACHE_TRUE);
}
cachedResult = nameValue;
task.putCachedLabel(KEY_NAME, cachedResult);
}
name.setText(cachedResult);
if(CACHE_TRUE.equals(task.getCachedLabel(KEY_HIDDEN)))
name.setTypeface(Typeface.DEFAULT, Typeface.ITALIC);
else
name.setTypeface(Typeface.DEFAULT, Typeface.BOLD);
}
// importance
final View importance = view.findViewById(R.id.importance);
if(visibleFields.IMPORTANCE) {
importance.setBackgroundColor(r.getColor(
task.getImportance().getColorResource()));
} else
importance.setVisibility(View.GONE);
// due date / completion date
final TextView deadlines = ((TextView)view.findViewById(R.id.text_deadlines));
if(visibleFields.DEADLINE || isExpanded) {
String cachedResult = task.getCachedLabel(KEY_DEADLINE);
if(cachedResult == null) {
StringBuilder label = new StringBuilder();
if(task.isTaskCompleted()) {
if(task.getCompletionDate() != null) {
int secondsLeft = (int)((task.getCompletionDate().getTime() -
System.currentTimeMillis()) / 1000);
String finishedTime;
if(Math.abs(secondsLeft) < FULL_DATE_THRESHOLD)
finishedTime = r.getString(R.string.ago_string,
DateUtilities.getDurationString(r,
Math.abs(secondsLeft), 1));
else
finishedTime = DateUtilities.getFormattedDate(activity,
task.getCompletionDate());
label.append(r.getString(R.string.taskList_completedPrefix,
finishedTime));
}
} else {
boolean taskOverdue = false;
if(task.getDefiniteDueDate() != null) {
long timeLeft = (task.getDefiniteDueDate().getTime() -
System.currentTimeMillis())/1000;
if(timeLeft > 0) {
if(timeLeft < FULL_DATE_THRESHOLD)
label.append(r.getString(R.string.taskList_dueRelativeTime)).append(" ");
else
label.append(r.getString(R.string.taskList_dueAbsoluteDate)).append(" ");
} else {
taskOverdue = true;
label.append(r.getString(R.string.taskList_overdueBy)).append(" ");
task.putCachedLabel(KEY_OVERDUE, CACHE_TRUE);
}
if(timeLeft < FULL_DATE_THRESHOLD)
label.append(DateUtilities.getDurationString(r,
(int)Math.abs(timeLeft), 1, true));
else
label.append(DateUtilities.getFormattedDate(activity,
task.getDefiniteDueDate()));
}
if(!taskOverdue && task.getPreferredDueDate() != null) {
if(task.getDefiniteDueDate() != null)
label.append(" / ");
long timeLeft = (task.getPreferredDueDate().getTime() -
System.currentTimeMillis())/1000;
label.append(r.getString(R.string.taskList_goalPrefix)).append(" ");
if(timeLeft > 0) {
if(timeLeft < FULL_DATE_THRESHOLD)
label.append(r.getString(R.string.taskList_dueRelativeTime)).append(" ");
else
label.append(r.getString(R.string.taskList_dueAbsoluteDate)).append(" ");
} else {
label.append(r.getString(R.string.taskList_overdueBy)).append(" ");
task.putCachedLabel(KEY_OVERDUE, CACHE_TRUE);
}
if(timeLeft < FULL_DATE_THRESHOLD)
label.append(DateUtilities.getDurationString(r,
(int)Math.abs(timeLeft), 1, true));
else
label.append(DateUtilities.getFormattedDate(activity,
task.getPreferredDueDate()));
}
}
cachedResult = label.toString();
task.putCachedLabel(KEY_DEADLINE, cachedResult);
}
if(visibleFields.DEADLINE) {
deadlines.setText(cachedResult);
if(CACHE_TRUE.equals(task.getCachedLabel(KEY_OVERDUE)))
deadlines.setTextColor(r.getColor(R.color.taskList_dueDateOverdue));
else
deadlines.setTextColor(r.getColor(R.color.taskList_details));
} else {
expandedDetails.append(cachedResult);
}
}
setVisibility(deadlines);
// estimated / elapsed time
if(visibleFields.TIMES || isExpanded) {
String cachedResult = task.getCachedLabel(KEY_TIMES);
if(cachedResult == null) {
Integer elapsed = task.getElapsedSeconds();
if(task.getTimerStart() != null)
elapsed += (int)((System.currentTimeMillis() - task.getTimerStart().getTime())/1000L);
Integer estimated = task.getEstimatedSeconds();
StringBuilder label = new StringBuilder();
if(estimated > 0) {
label.append(r.getString(R.string.taskList_estimatedTimePrefix)).
append(" ").
append(DateUtilities.getDurationString(r, estimated, 2));
if(elapsed > 0)
label.append(" / ");
}
if(elapsed > 0) {
label.append(r.getString(R.string.taskList_elapsedTimePrefix)).
append(" ").
append(DateUtilities.getAbbreviatedDurationString(r, elapsed, 2));
}
cachedResult = label.toString();
task.putCachedLabel(KEY_TIMES, cachedResult);
}
if(visibleFields.TIMES)
appendLine(details, cachedResult);
else
appendLine(expandedDetails, cachedResult);
}
// reminders
if(visibleFields.REMINDERS || isExpanded) {
String cachedResult = task.getCachedLabel(KEY_REMINDERS);
if(cachedResult == null) {
Integer notifyEvery = task.getNotificationIntervalSeconds();
StringBuilder label = new StringBuilder();
if(notifyEvery != null && notifyEvery > 0) {
label.append(r.getString(R.string.taskList_periodicReminderPrefix)).
append(" ").append(DateUtilities.getDurationString(r, notifyEvery, 1, true));
}
try {
alarmController.open();
List<Date> alerts = alarmController.getTaskAlerts(task.getTaskIdentifier());
if(alerts.size() > 0) {
Date nextAlarm = null;
Date now = new Date();
for(Date alert : alerts) {
if(alert.after(now) && (nextAlarm == null ||
alert.before(nextAlarm)))
nextAlarm = alert;
}
if(nextAlarm != null) {
if(label.length() > 0)
label.append(". ");
if(alarmFormat == null)
alarmFormat = Preferences.getDateWithTimeFormat(activity);
String alarmString = alarmFormat.format(nextAlarm);
label.append(r.getString(R.string.taskList_alarmPrefix) +
" " + alarmString);
}
}
} finally {
alarmController.close();
}
cachedResult = label.toString();
task.putCachedLabel(KEY_REMINDERS, cachedResult);
}
if(visibleFields.REMINDERS)
appendLine(details, cachedResult);
else
appendLine(expandedDetails, cachedResult);
}
// repeats
if(visibleFields.REPEATS || isExpanded) {
String cachedResult = task.getCachedLabel(KEY_REPEAT);
if(cachedResult == null) {
RepeatInfo repeatInfo = task.getRepeat();
if((task.getFlags() & TaskModelForList.FLAG_SYNC_ON_COMPLETE) > 0) {
cachedResult = r.getString(R.string.taskList_repeatsRemotely);
} else if(repeatInfo != null) {
cachedResult = r.getString(R.string.taskList_repeatPrefix) +
" " + repeatInfo.getValue() + " " +
r.getString(repeatInfo.getInterval().getLabelResource());
} else {
cachedResult = "";
}
task.putCachedLabel(KEY_REPEAT, cachedResult);
}
if(visibleFields.REPEATS)
appendLine(details, cachedResult);
else
appendLine(expandedDetails, cachedResult);
}
// tags
if(visibleFields.TAGS || isExpanded) {
String cachedResult = task.getCachedLabel(KEY_TAGS);
if(cachedResult == null) {
String tagString = hooks.getTagsFor(task);
if(tagString != null && !tagString.equals(""))
cachedResult = r.getString(R.string.taskList_tagsPrefix) +
" " + tagString;
else
cachedResult = "";
task.putCachedLabel(KEY_TAGS, cachedResult);
}
if(visibleFields.TAGS)
appendLine(details, cachedResult);
else
appendLine(expandedDetails, cachedResult);
}
// notes
if(visibleFields.NOTES || isExpanded) {
if(task.getNotes() != null && task.getNotes().length() > 0) {
String notes = r.getString(R.string.taskList_notesPrefix) +
" " + task.getNotes();
if(visibleFields.NOTES)
appendLine(details, notes);
else
appendLine(expandedDetails, notes);
}
}
final TextView detailsView = ((TextView)view.findViewById(R.id.details));
detailsView.setText(details.toString());
setVisibility(detailsView);
// expanded-only fields: creation date, ...
if(isExpanded) {
if(task.getCreationDate() != null) {
String cachedResult = task.getCachedLabel(KEY_CREATION);
if(cachedResult == null) {
int secondsAgo = (int) ((System.currentTimeMillis() -
task.getCreationDate().getTime())/1000);
cachedResult = r.getString(R.string.taskList_createdPrefix) + " " +
r.getString(R.string.ago_string, DateUtilities.getDurationString(r, Math.abs(secondsAgo), 1));
task.putCachedLabel(KEY_CREATION, cachedResult);
}
appendLine(expandedDetails, cachedResult);
}
final Button timerButton =
((Button)view.findViewById(R.id.timer));
if(task.getTimerStart() == null)
timerButton.setText(r.getString(R.string.startTimer_label));
else
timerButton.setText(r.getString(R.string.stopTimer_label));
final TextView expandedDetailsView =
((TextView)view.findViewById(R.id.expanded_details));
expandedDetailsView.setText(expandedDetails.toString());
}
}
/**
* Refresh the item given at the specified position in the list (not
* related to task identifier number)
*
* @param listView the parent view to refresh
* @param position the index of the item
*/
public void refreshItem(ListView listView, int position) {
TaskModelForList task = hooks.getTaskArray().get(position);
task.clearCache();
listView.invalidateViews();
}
/** Set listeners for this view. This is called once total */
private void addListeners(View view) {
final CheckBox progress = ((CheckBox)view.findViewById(R.id.cb1));
// clicking the check box
progress.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
View parent = (View)v.getParent().getParent();
TaskModelForList task = (TaskModelForList)parent.getTag();
int newProgressPercentage;
if(progress.isChecked())
newProgressPercentage =
TaskModelForList.getCompletedPercentage();
else
newProgressPercentage = 0;
if(newProgressPercentage != task.getProgressPercentage()) {
setTaskProgress(task, parent, newProgressPercentage);
setupView(parent, task);
}
}
});
// clicking the text field
view.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
TaskModelForList task = (TaskModelForList)v.getTag();
toggleExpanded(v, task);
}
});
// typing while selected something
view.setOnKeyListener(new OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
if(event.getAction() != KeyEvent.ACTION_UP)
return false;
// hot-key to set task priority - 1-4 or ALT + Q-R
Importance importance = null;
if(event.getNumber() >= '1' && event.getNumber() <= '4')
importance = Importance.values()[event.getNumber() - '1'];
if(importance != null) {
TaskModelForList task = (TaskModelForList)v.getTag();
task.setImportance(importance);
hooks.taskController().saveTask(task, false);
setFieldContentsAndVisibility(v, task);
return true;
}
return false;
}
});
// long-clicking the text field
view.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
TaskModelForList task = (TaskModelForList)v.getTag();
int id = (int)task.getTaskIdentifier().getId();
menu.add(id, CONTEXT_EDIT_ID, Menu.NONE,
R.string.taskList_context_edit);
menu.add(id, 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(id, CONTEXT_TIMER_ID, Menu.NONE, timerTitle);
if(task.getDefiniteDueDate() != null ||
task.getPreferredDueDate() != null)
menu.add(id, CONTEXT_POSTPONE_ID, Menu.NONE,
R.string.taskList_context_postpone);
menu.setHeaderTitle(task.getName());
}
});
// clicking one of the expanded buttons
Button editButton = (Button)view.findViewById(R.id.edit);
editButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
View parent = (View)v.getParent().getParent().getParent().getParent();
TaskModelForList task = (TaskModelForList)parent.getTag();
hooks.editItem(task);
}
});
Button toggleTimerButton = (Button)view.findViewById(R.id.timer);
toggleTimerButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
View parent = (View)v.getParent().getParent().getParent().getParent();
TaskModelForList task = (TaskModelForList)parent.getTag();
hooks.toggleTimerOnItem(task);
}
});
}
/** Helper method to set a task's progress and then adjust its appearance
*
* @param task
* @param view
* @param progress
*/
private void setTaskProgress(final TaskModelForList task, View view, int progress) {
final ImageView timer = ((ImageView)view.findViewById(R.id.imageLeft));
task.setProgressPercentage(progress);
hooks.taskController().saveTask(task, false);
// show this task as completed even if it has repeats
if(progress == 100) {
recentlyCompleted = task;
FlurryAgent.onEvent("complete-task");
} else {
FlurryAgent.onEvent("uncomplete-task");
recentlyCompleted = null;
}
// if our timer is on, ask if we want to stop
if(progress == 100 && task.getTimerStart() != null) {
new AlertDialog.Builder(activity)
.setTitle(R.string.question_title)
.setMessage(R.string.stop_timer_title)
.setIcon(android.R.drawable.ic_dialog_alert)
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
task.stopTimerAndUpdateElapsedTime();
hooks.taskController().saveTask(task, false);
timer.setVisibility(View.GONE);
}
})
.setNegativeButton(android.R.string.cancel, null)
.show();
}
}
/** Helper method to adjust a tasks' apperance if the task is completed or
* uncompleted.
*
* @param task
* @param name
* @param progress
*/
private void setTaskAppearance(TaskModelForList task, TextView name, CheckBox progress) {
Resources r = activity.getResources();
if(task.isTaskCompleted() || task == recentlyCompleted) {
name.setPaintFlags(name.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
name.setTextColor(r.getColor(R.color.task_list_done));
progress.setButtonDrawable(R.drawable.btn_check);
progress.setChecked(true);
} else {
name.setPaintFlags(name.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
name.setTextColor(r.getColor(task.getTaskColorResource(getContext())));
progress.setButtonDrawable(R.drawable.btn_check);
}
}
}

@ -1,108 +0,0 @@
/*
* 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 android.app.Activity;
import android.content.DialogInterface;
import android.content.res.Resources;
import android.os.Bundle;
import com.flurry.android.FlurryAgent;
import com.timsu.astrid.R;
import com.timsu.astrid.data.task.AbstractTaskModel;
import com.timsu.astrid.data.task.TaskController;
import com.timsu.astrid.data.task.TaskIdentifier;
import com.timsu.astrid.utilities.Constants;
import com.timsu.astrid.utilities.DialogUtilities;
/** Abstract activity that operates on a single task. Use the generic parameter
* to pass in the model class you are working with.
*
* @author timsu
*/
public abstract class TaskModificationActivity<MODEL_TYPE extends
AbstractTaskModel> extends Activity {
public static final String LOAD_INSTANCE_TOKEN = "id";
protected TaskController controller;
protected MODEL_TYPE model;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
controller = new TaskController(this);
controller.open();
// check if we have a TaskIdentifier
TaskIdentifier identifier = null;
Bundle extras = getIntent().getExtras();
if(savedInstanceState != null && savedInstanceState.containsKey(LOAD_INSTANCE_TOKEN)) {
identifier = new TaskIdentifier(savedInstanceState.getLong(
LOAD_INSTANCE_TOKEN));
} else if(extras != null && extras.containsKey(LOAD_INSTANCE_TOKEN))
identifier = new TaskIdentifier(extras.getLong(
LOAD_INSTANCE_TOKEN));
model = getModel(identifier);
} catch (Exception e) {
showErrorAndFinish(R.string.error_opening, e);
}
}
@Override
protected void onStart() {
super.onStart();
// set up flurry
FlurryAgent.onStartSession(this, Constants.FLURRY_KEY);
}
@Override
protected void onStop() {
super.onStop();
FlurryAgent.onEndSession(this);
}
protected void showErrorAndFinish(int prefix, Throwable e) {
Resources r = getResources();
DialogUtilities.okDialog(this,
r.getString(prefix) + " " +
e.getLocalizedMessage(), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
}
abstract protected MODEL_TYPE getModel(TaskIdentifier identifier);
@Override
protected void onDestroy() {
super.onDestroy();
controller.close();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if(model.getTaskIdentifier() != null)
outState.putLong(LOAD_INSTANCE_TOKEN, model.getTaskIdentifier().getId());
}
}

@ -1,130 +0,0 @@
/*
* 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 android.app.TabActivity;
import android.content.DialogInterface;
import android.content.res.Resources;
import android.os.Bundle;
import com.flurry.android.FlurryAgent;
import com.timsu.astrid.R;
import com.timsu.astrid.data.task.AbstractTaskModel;
import com.timsu.astrid.data.task.TaskController;
import com.timsu.astrid.data.task.TaskIdentifier;
import com.timsu.astrid.utilities.AstridUtilities;
import com.timsu.astrid.utilities.Constants;
import com.timsu.astrid.utilities.DialogUtilities;
/** Hack hack for tabbed activity. Should provide better interaction
*
* @author timsu
*/
public abstract class TaskModificationTabbedActivity<MODEL_TYPE extends
AbstractTaskModel> extends TabActivity {
public static final String LOAD_INSTANCE_TOKEN = TaskModificationActivity.LOAD_INSTANCE_TOKEN;
protected TaskController controller;
protected MODEL_TYPE model;
protected class Context {
protected MODEL_TYPE cModel;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
controller = new TaskController(this);
controller.open();
// if we've saved our model, use that instead
if(getLastNonConfigurationInstance() != null) {
Context context = (Context)getLastNonConfigurationInstance();
model = context.cModel;
} else {
try {
// check if we have a TaskIdentifier
TaskIdentifier identifier = null;
Bundle extras = getIntent().getExtras();
if(savedInstanceState != null && savedInstanceState.containsKey(LOAD_INSTANCE_TOKEN)) {
identifier = new TaskIdentifier(savedInstanceState.getLong(
LOAD_INSTANCE_TOKEN));
} else if(extras != null && extras.containsKey(LOAD_INSTANCE_TOKEN))
identifier = new TaskIdentifier(extras.getLong(
LOAD_INSTANCE_TOKEN));
model = getModel(identifier);
} catch (Exception e) {
showErrorAndFinish(R.string.error_opening, e);
}
}
}
/**
* Called when screen is rotated. We return the model we are editing so that
* we will have access to it instead of having to re-read from the database
*/
@Override
public Object onRetainNonConfigurationInstance() {
Context context = new Context();
context.cModel = model;
return context;
}
@Override
protected void onStart() {
super.onStart();
FlurryAgent.onStartSession(this, Constants.FLURRY_KEY);
}
@Override
protected void onStop() {
super.onStop();
FlurryAgent.onEndSession(this);
}
protected void showErrorAndFinish(int prefix, Throwable e) {
AstridUtilities.reportFlurryError("taskedit", e);
Resources r = getResources();
DialogUtilities.okDialog(this,
r.getString(prefix) + " " +
e.getLocalizedMessage(), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
}
abstract protected MODEL_TYPE getModel(TaskIdentifier identifier);
@Override
protected void onDestroy() {
super.onDestroy();
controller.close();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if(model.getTaskIdentifier() != null)
outState.putLong(LOAD_INSTANCE_TOKEN, model.getTaskIdentifier().getId());
}
}

@ -16,10 +16,10 @@ import android.view.View;
import android.widget.RemoteViews;
import com.timsu.astrid.R;
import com.timsu.astrid.activities.TaskList;
import com.timsu.astrid.data.task.TaskController;
import com.timsu.astrid.data.task.TaskModelForWidget;
import com.todoroo.astrid.activity.TaskEditActivity;
import com.todoroo.astrid.activity.TaskListActivity;
import com.todoroo.astrid.service.AstridDependencyInjector;
public class AstridAppWidgetProvider extends AppWidgetProvider {
@ -81,7 +81,7 @@ public class AstridAppWidgetProvider extends AppWidgetProvider {
.getTasksForWidget(Integer.toString(numberOfTasks));
taskController.close();
Intent listIntent = new Intent(context, TaskList.class);
Intent listIntent = new Intent(context, TaskListActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
listIntent, 0);
views.setOnClickPendingIntent(R.id.taskbody, pendingIntent);

@ -36,7 +36,6 @@ import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;
import android.util.Log;
import com.timsu.astrid.activities.TaskListSubActivity;
import com.timsu.astrid.appwidget.AstridAppWidgetProvider.UpdateService;
import com.timsu.astrid.data.AbstractController;
import com.timsu.astrid.data.alerts.AlertController;
@ -377,7 +376,7 @@ public class TaskController extends AbstractController {
Synchronizer synchronizer = new Synchronizer(model.getTaskIdentifier());
synchronizer.synchronize(context, new SynchronizerListener() {
public void onSynchronizerFinished(int numServicesSynced) {
TaskListSubActivity.shouldRefreshTaskList = true;
// TaskListSubActivity.shouldRefreshTaskList = true;
}
});
}

@ -26,7 +26,6 @@ import android.app.Activity;
import android.content.Context;
import android.util.Log;
import com.timsu.astrid.activities.TaskListSubActivity;
import com.timsu.astrid.data.AbstractController;
import com.timsu.astrid.data.alerts.AlertController;
import com.timsu.astrid.data.sync.SyncDataController;
@ -195,7 +194,7 @@ public class Synchronizer {
if(getSingleTaskForSync() == null)
Preferences.setSyncLastSync(context, new Date());
if(!isService) {
TaskListSubActivity.shouldRefreshTaskList = true;
// TaskListSubActivity.shouldRefreshTaskList = true;
}
Log.i("sync", "Synchronization Service Finished");
@ -203,13 +202,13 @@ public class Synchronizer {
// --- controller stuff
private ControllerWrapper<SyncDataController> syncController =
private final ControllerWrapper<SyncDataController> syncController =
new ControllerWrapper<SyncDataController>(SyncDataController.class);
private ControllerWrapper<TaskController> taskController =
private final ControllerWrapper<TaskController> taskController =
new ControllerWrapper<TaskController>(TaskController.class);
private ControllerWrapper<TagController> tagController =
private final ControllerWrapper<TagController> tagController =
new ControllerWrapper<TagController>(TagController.class);
private ControllerWrapper<AlertController> alertController =
private final ControllerWrapper<AlertController> alertController =
new ControllerWrapper<AlertController>(AlertController.class);
private static class ControllerWrapper<TYPE extends AbstractController> {

@ -11,7 +11,6 @@ import android.util.Log;
import com.timsu.astrid.R;
import com.timsu.astrid.activities.LocaleEditAlerts;
import com.timsu.astrid.activities.TagListSubActivity;
import com.timsu.astrid.data.tag.TagController;
import com.timsu.astrid.data.tag.TagIdentifier;
import com.timsu.astrid.data.task.TaskController;
@ -57,7 +56,8 @@ public class LocaleReceiver extends BroadcastReceiver {
HashSet<TaskIdentifier> activeTasks = taskController.getActiveVisibleTaskIdentifiers();
LinkedList<TaskIdentifier> tasks = tagController.getTaggedTasks(
new TagIdentifier(tagId));
int count = TagListSubActivity.countActiveTasks(activeTasks, tasks);
// int count = TagListSubActivity.countActiveTasks(activeTasks, tasks);
int count = 0;
if(count > 0) {
Resources r = context.getResources();
String reminder = r.getString(R.string.notif_tagNotification).

Loading…
Cancel
Save