diff --git a/astrid/AndroidManifest.xml b/astrid/AndroidManifest.xml
index 8ab344d7a..983e0cf75 100644
--- a/astrid/AndroidManifest.xml
+++ b/astrid/AndroidManifest.xml
@@ -207,6 +207,12 @@
+
+
+
+
+
+
diff --git a/astrid/common-src/com/todoroo/andlib/sql/DBObject.java b/astrid/common-src/com/todoroo/andlib/sql/DBObject.java
index 7d27d70a6..c01b20af7 100644
--- a/astrid/common-src/com/todoroo/andlib/sql/DBObject.java
+++ b/astrid/common-src/com/todoroo/andlib/sql/DBObject.java
@@ -31,7 +31,7 @@ public abstract class DBObject> implements Cloneable {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
- DBObject dbObject = (DBObject) o;
+ DBObject> dbObject = (DBObject>) o;
if (alias != null ? !alias.equals(dbObject.alias) : dbObject.alias != null) return false;
if (expression != null ? !expression.equals(dbObject.expression) : dbObject.expression != null) return false;
diff --git a/astrid/common-src/com/todoroo/andlib/utility/UserTask.java b/astrid/common-src/com/todoroo/andlib/utility/UserTask.java
index 9440a49ae..6c11101eb 100644
--- a/astrid/common-src/com/todoroo/andlib/utility/UserTask.java
+++ b/astrid/common-src/com/todoroo/andlib/utility/UserTask.java
@@ -415,7 +415,7 @@ public abstract class UserTask {
}
protected static class InternalHandler extends Handler {
- @SuppressWarnings({"unchecked"})
+ @SuppressWarnings({"unchecked", "rawtypes"})
@Override
public void handleMessage(Message msg) {
UserTaskResult result = (UserTaskResult) msg.obj;
diff --git a/astrid/plugin-src/com/todoroo/astrid/repeats/RepeatControlSet.java b/astrid/plugin-src/com/todoroo/astrid/repeats/RepeatControlSet.java
index 98caab507..2c1fe8bfc 100644
--- a/astrid/plugin-src/com/todoroo/astrid/repeats/RepeatControlSet.java
+++ b/astrid/plugin-src/com/todoroo/astrid/repeats/RepeatControlSet.java
@@ -38,11 +38,18 @@ import com.todoroo.astrid.model.Task;
*/
public class RepeatControlSet implements TaskEditControlSet {
+ // --- spinner constants
+
private static final int INTERVAL_DAYS = 0;
private static final int INTERVAL_WEEKS = 1;
private static final int INTERVAL_MONTHS = 2;
private static final int INTERVAL_YEARS = 3;
+ private static final int TYPE_DUE_DATE = 0;
+ private static final int TYPE_COMPLETION_DATE = 1;
+
+ // --- instance variables
+
private final Activity activity;
private final CheckBox enabled;
private final Button value;
@@ -52,6 +59,8 @@ public class RepeatControlSet implements TaskEditControlSet {
private final LinearLayout daysOfWeekContainer;
private final CompoundButton[] daysOfWeek = new CompoundButton[7];
+ // --- implementation
+
public RepeatControlSet(final Activity activity, ViewGroup parent) {
this.activity = activity;
LayoutInflater.from(activity).inflate(R.layout.repeat_control, parent, true);
@@ -143,6 +152,7 @@ public class RepeatControlSet implements TaskEditControlSet {
public void readFromTask(Task task) {
String recurrence = task.getValue(Task.RECURRENCE);
+ // read recurrence rule
if(recurrence.length() > 0) {
try {
RRule rrule = new RRule(recurrence);
@@ -174,9 +184,14 @@ public class RepeatControlSet implements TaskEditControlSet {
recurrence = ""; //$NON-NLS-1$
}
}
-
enabled.setChecked(recurrence.length() > 0);
repeatContainer.setVisibility(enabled.isChecked() ? View.VISIBLE : View.GONE);
+
+ // read flag
+ if(task.getFlag(Task.FLAGS, Task.FLAG_REPEAT_AFTER_COMPLETION))
+ type.setSelection(TYPE_COMPLETION_DATE);
+ else
+ type.setSelection(TYPE_DUE_DATE);
}
@@ -210,5 +225,16 @@ public class RepeatControlSet implements TaskEditControlSet {
result = rrule.toIcal();
}
task.setValue(Task.RECURRENCE, result);
+
+ switch(type.getSelectedItemPosition()) {
+ case TYPE_DUE_DATE:
+ task.setFlag(Task.FLAGS, Task.FLAG_REPEAT_AFTER_COMPLETION, false);
+ break;
+ case TYPE_COMPLETION_DATE:
+ task.setFlag(Task.FLAGS, Task.FLAG_REPEAT_AFTER_COMPLETION, true);
+ }
+
+ if(task.getFlag(Task.FLAGS, Task.FLAG_REPEAT_AFTER_COMPLETION))
+ type.setSelection(1);
}
}
\ No newline at end of file
diff --git a/astrid/plugin-src/com/todoroo/astrid/repeats/RepeatTaskCompleteListener.java b/astrid/plugin-src/com/todoroo/astrid/repeats/RepeatTaskCompleteListener.java
new file mode 100644
index 000000000..7a45f876d
--- /dev/null
+++ b/astrid/plugin-src/com/todoroo/astrid/repeats/RepeatTaskCompleteListener.java
@@ -0,0 +1,99 @@
+package com.todoroo.astrid.repeats;
+
+import java.text.ParseException;
+import java.util.Date;
+import java.util.TimeZone;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+import com.google.ical.iter.RecurrenceIterator;
+import com.google.ical.iter.RecurrenceIteratorFactory;
+import com.google.ical.values.DateTimeValueImpl;
+import com.google.ical.values.DateValue;
+import com.google.ical.values.DateValueImpl;
+import com.todoroo.andlib.service.Autowired;
+import com.todoroo.andlib.service.DependencyInjectionService;
+import com.todoroo.andlib.service.ExceptionService;
+import com.todoroo.astrid.api.AstridApiConstants;
+import com.todoroo.astrid.model.Task;
+import com.todoroo.astrid.service.TaskService;
+
+public class RepeatTaskCompleteListener extends BroadcastReceiver {
+
+ @Autowired
+ private TaskService taskService;
+
+ @Autowired
+ private ExceptionService exceptionService;
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ long taskId = intent.getLongExtra(AstridApiConstants.EXTRAS_TASK_ID, -1);
+ if(taskId == -1)
+ return;
+
+ DependencyInjectionService.getInstance().inject(this);
+
+ Task task = taskService.fetchById(taskId, Task.ID, Task.RECURRENCE,
+ Task.DUE_DATE, Task.FLAGS);
+ if(task == null)
+ return;
+
+ String recurrence = task.getValue(Task.RECURRENCE);
+ if(recurrence.length() > 0) {
+ Date date = new Date();
+ DateValue today = new DateValueImpl(date.getYear() + 1900,
+ date.getMonth() + 1, date.getDate());
+
+ DateValue repeatFrom;
+ if(task.hasDueDate() && !task.getFlag(Task.FLAGS, Task.FLAG_REPEAT_AFTER_COMPLETION)) {
+ date = new Date(task.getValue(Task.DUE_DATE));
+ repeatFrom = new DateTimeValueImpl(date.getYear() + 1900,
+ date.getMonth() + 1, date.getDate(),
+ date.getHours(), date.getMinutes(), date.getSeconds());
+ } else {
+ repeatFrom = today;
+ }
+
+ // invoke the recurrence iterator
+ try {
+ RecurrenceIterator iterator = RecurrenceIteratorFactory.createRecurrenceIterator(recurrence,
+ repeatFrom, TimeZone.getDefault());
+ if(repeatFrom.compareTo(today) < 0)
+ repeatFrom = today;
+ // go to the latest value and advance one more
+ iterator.advanceTo(repeatFrom);
+ if(!iterator.hasNext())
+ return;
+ DateValue nextDate = iterator.next();
+ if(nextDate.equals(repeatFrom)) {
+ if(!iterator.hasNext())
+ return;
+ nextDate = iterator.next();
+ }
+
+ long newDueDate;
+ if(nextDate instanceof DateTimeValueImpl) {
+ DateTimeValueImpl newDateTime = (DateTimeValueImpl)nextDate;
+ newDueDate = task.createDueDate(Task.URGENCY_SPECIFIC_DAY_TIME,
+ new Date(newDateTime.year() - 1900, newDateTime.month() - 1,
+ newDateTime.day(), newDateTime.hour(),
+ newDateTime.minute(), newDateTime.second()).getTime());
+ } else {
+ newDueDate = task.createDueDate(Task.URGENCY_SPECIFIC_DAY,
+ new Date(nextDate.year() - 1900, nextDate.month() - 1,
+ nextDate.day()).getTime());
+ }
+
+ Task newTask = taskService.clone(task);
+ task.setValue(Task.DUE_DATE, newDueDate);
+ taskService.save(newTask, false);
+ } catch (ParseException e) {
+ exceptionService.reportError("recurrence-rule: " + recurrence, e); //$NON-NLS-1$
+ }
+ }
+ }
+
+}
diff --git a/astrid/plugin-src/com/todoroo/astrid/tags/TagFilterExposer.java b/astrid/plugin-src/com/todoroo/astrid/tags/TagFilterExposer.java
index 1f48c3234..099c503c9 100644
--- a/astrid/plugin-src/com/todoroo/astrid/tags/TagFilterExposer.java
+++ b/astrid/plugin-src/com/todoroo/astrid/tags/TagFilterExposer.java
@@ -78,8 +78,8 @@ public class TagFilterExposer extends BroadcastReceiver {
FilterListHeader tagsHeader = new FilterListHeader(TagsPlugin.IDENTIFIER,
context.getString(R.string.tag_FEx_header));
Filter untagged = new Filter(TagsPlugin.IDENTIFIER,
- "Untagged",
- "Untagged",
+ r.getString(R.string.tag_FEx_untagged),
+ r.getString(R.string.tag_FEx_untagged),
tagService.untaggedTemplate(),
null);
untagged.listingIcon = ((BitmapDrawable)r.getDrawable(R.drawable.filter_untagged)).getBitmap();
diff --git a/astrid/plugin-src/com/todoroo/astrid/tags/TagsControlSet.java b/astrid/plugin-src/com/todoroo/astrid/tags/TagsControlSet.java
new file mode 100644
index 000000000..50fb93488
--- /dev/null
+++ b/astrid/plugin-src/com/todoroo/astrid/tags/TagsControlSet.java
@@ -0,0 +1,127 @@
+package com.todoroo.astrid.tags;
+
+import java.util.ArrayList;
+
+import android.app.Activity;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ArrayAdapter;
+import android.widget.AutoCompleteTextView;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.timsu.astrid.R;
+import com.todoroo.andlib.data.TodorooCursor;
+import com.todoroo.astrid.activity.TaskEditActivity.TaskEditControlSet;
+import com.todoroo.astrid.model.Metadata;
+import com.todoroo.astrid.model.Task;
+import com.todoroo.astrid.tags.TagService.Tag;
+
+/**
+ * Control set to manage adding and removing tags
+ *
+ * @author Tim Su
+ *
+ */
+public final class TagsControlSet implements TaskEditControlSet {
+
+ // --- constants
+
+ /** Number of tags a task can have */
+ static final int MAX_TAGS = 5;
+
+ // --- instance variables
+
+ private final TagService tagService = new TagService();
+ private final Tag[] allTags;
+ private final LinearLayout tagsContainer;
+ private final Activity activity;
+
+ public TagsControlSet(Activity activity, int tagsContainer) {
+ allTags = tagService.getGroupedTags(TagService.GROUPED_TAGS_BY_SIZE);
+ this.activity = activity;
+ this.tagsContainer = (LinearLayout) activity.findViewById(tagsContainer);
+ }
+
+ @SuppressWarnings("nls")
+ @Override
+ public void readFromTask(Task task) {
+ // tags (only configure if not already set)
+ if(tagsContainer.getChildCount() == 0) {
+ TodorooCursor cursor = tagService.getTags(task.getId());
+ try {
+ for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext())
+ addTag(cursor.get(Metadata.VALUE));
+ } finally {
+ cursor.close();
+ }
+ addTag("");
+ }
+ }
+
+ @Override
+ public void writeToModel(Task task) {
+ ArrayList tags = new ArrayList();
+
+ for(int i = 0; i < tagsContainer.getChildCount(); i++) {
+ TextView tagName = (TextView)tagsContainer.getChildAt(i).findViewById(R.id.text1);
+ if(tagName.getText().length() == 0)
+ continue;
+ tags.add(tagName.getText().toString());
+ }
+
+ tagService.synchronizeTags(task.getId(), tags);
+ }
+
+ /** Adds a tag to the tag field */
+ boolean addTag(String tagName) {
+ if (tagsContainer.getChildCount() >= MAX_TAGS) {
+ return false;
+ }
+
+ LayoutInflater inflater = activity.getLayoutInflater();
+ final View tagItem = inflater.inflate(R.layout.tag_edit_row, null);
+ tagsContainer.addView(tagItem);
+
+ AutoCompleteTextView textView = (AutoCompleteTextView)tagItem.
+ findViewById(R.id.text1);
+ textView.setText(tagName);
+ ArrayAdapter tagsAdapter =
+ new ArrayAdapter(activity,
+ android.R.layout.simple_dropdown_item_1line, allTags);
+ textView.setAdapter(tagsAdapter);
+ textView.addTextChangedListener(new TextWatcher() {
+ @SuppressWarnings("nls")
+ public void onTextChanged(CharSequence s, int start, int before,
+ int count) {
+ if(start == 0 && tagsContainer.getChildAt(
+ tagsContainer.getChildCount()-1) == tagItem) {
+ addTag("");
+ }
+ }
+
+ public void afterTextChanged(Editable s) {
+ //
+ }
+
+
+ public void beforeTextChanged(CharSequence s, int start, int count,
+ int after) {
+ //
+ }
+ });
+
+ ImageButton reminderRemoveButton;
+ reminderRemoveButton = (ImageButton)tagItem.findViewById(R.id.button1);
+ reminderRemoveButton.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ tagsContainer.removeView(tagItem);
+ }
+ });
+
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/astrid/res/values/arrays.xml b/astrid/res/values/arrays.xml
index 0e8246a35..19b46080c 100644
--- a/astrid/res/values/arrays.xml
+++ b/astrid/res/values/arrays.xml
@@ -24,7 +24,7 @@
minimizing the annoyance.
-->
-
+
diff --git a/astrid/res/values/colors.xml b/astrid/res/values/colors.xml
index 42220ddd1..bb2ccbbe2 100644
--- a/astrid/res/values/colors.xml
+++ b/astrid/res/values/colors.xml
@@ -1,5 +1,5 @@
-
+
#FFFB6666
#FFFFFFFF
#ff777777
diff --git a/astrid/res/values/strings-3.0.xml b/astrid/res/values/strings-3.0.xml
index cb00216b9..52ac44c60 100644
--- a/astrid/res/values/strings-3.0.xml
+++ b/astrid/res/values/strings-3.0.xml
@@ -1,6 +1,6 @@
-
+
@@ -298,12 +298,6 @@ to the plugin creator for fastest service.
No Repeat Set
-
- Tags:
-
-
- Tag Name
-
Repeat Every (0 to disable)
Help: Astrid Repeats
diff --git a/astrid/res/values/strings-filters.xml b/astrid/res/values/strings-filters.xml
index d8921a5e0..7fb0ce1dd 100644
--- a/astrid/res/values/strings-filters.xml
+++ b/astrid/res/values/strings-filters.xml
@@ -1,6 +1,6 @@
-
+
diff --git a/astrid/res/values/strings-legacy.xml b/astrid/res/values/strings-legacy.xml
index 2603d4245..6d512cb4f 100644
--- a/astrid/res/values/strings-legacy.xml
+++ b/astrid/res/values/strings-legacy.xml
@@ -19,7 +19,7 @@
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-->
-
+
diff --git a/astrid/res/values/strings-reminders.xml b/astrid/res/values/strings-reminders.xml
index 4c214dfbc..30c6faaa9 100644
--- a/astrid/res/values/strings-reminders.xml
+++ b/astrid/res/values/strings-reminders.xml
@@ -1,6 +1,6 @@
-
+
diff --git a/astrid/res/values/strings-repeat.xml b/astrid/res/values/strings-repeat.xml
index 452d396f7..7d306614b 100644
--- a/astrid/res/values/strings-repeat.xml
+++ b/astrid/res/values/strings-repeat.xml
@@ -1,6 +1,6 @@
-
+
diff --git a/astrid/res/values/strings-tags.xml b/astrid/res/values/strings-tags.xml
index cf7ba787b..9e2e164aa 100644
--- a/astrid/res/values/strings-tags.xml
+++ b/astrid/res/values/strings-tags.xml
@@ -1,24 +1,32 @@
-
+
- Add Tags
- Tags: %s
-
- Tags: %s
-
- Tags
- By Size
- Alphabetical
-
-
- $T ($C)
-
- Tagged \'%s\'
+
+
+
+ Tags:
+
+
+ Tag Name
+
+
+
+ Tags: %s
- Type In a Tag
- Edit Tags
+
+
+ Tags
+ By Size
+ Alphabetical
+ Untagged
+
+
+ $T ($C)
+
+
+ Tagged \'%s\'
diff --git a/astrid/res/values/styles-3.0.xml b/astrid/res/values/styles-3.0.xml
index f13d6c3ca..9d65e463c 100644
--- a/astrid/res/values/styles-3.0.xml
+++ b/astrid/res/values/styles-3.0.xml
@@ -1,6 +1,6 @@
-
+
diff --git a/astrid/res/values/styles-legacy.xml b/astrid/res/values/styles-legacy.xml
index 4433d17c4..c6f8f3053 100644
--- a/astrid/res/values/styles-legacy.xml
+++ b/astrid/res/values/styles-legacy.xml
@@ -19,7 +19,7 @@
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-->
-
+