Got the awesome filter screen working. Won't save as bookmarks, but at least... it works and can filter tasks. Can edit the chaining type, can delete rows. Pretty much awesome.

pull/14/head
Tim Su 16 years ago
parent 0f77edb13e
commit 8e7b96f78f

@ -3,10 +3,15 @@
*/ */
package com.todoroo.astrid.api; package com.todoroo.astrid.api;
import java.util.Date;
import android.content.ContentValues; import android.content.ContentValues;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import com.todoroo.andlib.utility.DateUtilities;
import edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.CheckForNull;
/** /**
@ -16,9 +21,9 @@ import edu.umd.cs.findbugs.annotations.CheckForNull;
* @author Tim Su <tim@todoroo.com> * @author Tim Su <tim@todoroo.com>
* *
*/ */
public final class CustomFilterCriterion extends FilterListItem { public final class CustomFilterCriterion implements Parcelable {
// --- constants // --- placeholder strings
/** value to be replaced with the current time as long */ /** value to be replaced with the current time as long */
public static final String VALUE_NOW = "NOW()"; //$NON-NLS-1$ public static final String VALUE_NOW = "NOW()"; //$NON-NLS-1$
@ -38,6 +43,28 @@ public final class CustomFilterCriterion extends FilterListItem {
/** value to be replaced by end of day next week as long */ /** value to be replaced by end of day next week as long */
public static final String VALUE_EOD_NEXT_WEEK = "EODW()"; //$NON-NLS-1$ public static final String VALUE_EOD_NEXT_WEEK = "EODW()"; //$NON-NLS-1$
/** Replace placeholder strings with actual */
public static String replacePlaceholders(String value) {
if(value.contains(VALUE_NOW))
value = value.replace(VALUE_NOW, Long.toString(DateUtilities.now()));
if(value.contains(VALUE_EOD) || value.contains(VALUE_EOD_DAY_AFTER) ||
value.contains(VALUE_EOD_NEXT_WEEK) || value.contains(VALUE_EOD_TOMORROW) ||
value.contains(VALUE_EOD_YESTERDAY)) {
Date date = new Date();
date.setHours(23);
date.setMinutes(59);
date.setSeconds(59);
long time = date.getTime();
value = value.replace(VALUE_EOD_YESTERDAY, Long.toString(time - DateUtilities.ONE_DAY));
value = value.replace(VALUE_EOD, Long.toString(time));
value = value.replace(VALUE_EOD_TOMORROW, Long.toString(time + DateUtilities.ONE_DAY));
value = value.replace(VALUE_EOD_DAY_AFTER, Long.toString(time + 2 * DateUtilities.ONE_DAY));
value = value.replace(VALUE_EOD_NEXT_WEEK, Long.toString(time + 7 * DateUtilities.ONE_DAY));
}
return value;
}
// --- instance variables // --- instance variables
/** /**
@ -131,9 +158,7 @@ public final class CustomFilterCriterion extends FilterListItem {
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override
public void writeToParcel(Parcel dest, int flags) { public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeString(text); dest.writeString(text);
dest.writeString(sql); dest.writeString(sql);
dest.writeParcelable(valuesForNewTasks, 0); dest.writeParcelable(valuesForNewTasks, 0);
@ -169,4 +194,5 @@ public final class CustomFilterCriterion extends FilterListItem {
} }
}; };
} }

@ -9,8 +9,8 @@ import android.content.ContentValues;
import android.content.Context; import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.util.Log; import android.util.Log;
import com.todoroo.andlib.data.Property.PropertyVisitor; import com.todoroo.andlib.data.Property.PropertyVisitor;
@ -95,10 +95,13 @@ abstract public class AbstractDatabase {
} }
protected synchronized final void initializeHelper() { protected synchronized final void initializeHelper() {
if(helper == null) if(helper == null) {
if(ContextManager.getContext() == null)
throw new NullPointerException("Null context creating database helper");
helper = new DatabaseHelper(ContextManager.getContext(), helper = new DatabaseHelper(ContextManager.getContext(),
getName(), null, getVersion()); getName(), null, getVersion());
} }
}
/** /**
* Open the database for writing. Must be closed afterwards. If user is * Open the database for writing. Must be closed afterwards. If user is

@ -5,23 +5,31 @@ import java.util.List;
import android.app.ListActivity; import android.app.ListActivity;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Intent;
import android.content.res.Resources; import android.content.res.Resources;
import android.database.Cursor; import android.database.Cursor;
import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle; import android.os.Bundle;
import android.view.ContextMenu; import android.view.ContextMenu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.SubMenu;
import android.view.View; import android.view.View;
import android.view.ContextMenu.ContextMenuInfo; import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnCreateContextMenuListener;
import android.widget.Button; import android.widget.Button;
import android.widget.TextView;
import com.timsu.astrid.R; import com.timsu.astrid.R;
import com.todoroo.andlib.data.Property.CountProperty; import com.todoroo.andlib.data.Property.CountProperty;
import com.todoroo.andlib.service.Autowired; import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.service.DependencyInjectionService; import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.sql.Criterion; import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.sql.Join;
import com.todoroo.andlib.sql.Query; import com.todoroo.andlib.sql.Query;
import com.todoroo.astrid.activity.TaskListActivity;
import com.todoroo.astrid.api.CustomFilterCriterion; import com.todoroo.astrid.api.CustomFilterCriterion;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.dao.Database; import com.todoroo.astrid.dao.Database;
import com.todoroo.astrid.dao.MetadataDao.MetadataCriteria; import com.todoroo.astrid.dao.MetadataDao.MetadataCriteria;
import com.todoroo.astrid.dao.TaskDao.TaskCriteria; import com.todoroo.astrid.dao.TaskDao.TaskCriteria;
@ -40,6 +48,8 @@ public class CustomFilterActivity extends ListActivity {
static final int MENU_GROUP_FILTER = 0; static final int MENU_GROUP_FILTER = 0;
static final int MENU_GROUP_FILTER_OPTION = 1; static final int MENU_GROUP_FILTER_OPTION = 1;
static final int MENU_GROUP_CONTEXT_TYPE = 2;
static final int MENU_GROUP_CONTEXT_DELETE = 3;
// --- hierarchy of filter classes // --- hierarchy of filter classes
@ -53,15 +63,16 @@ public class CustomFilterActivity extends ListActivity {
public CustomFilterCriterion criterion; public CustomFilterCriterion criterion;
/** which of the entries is selected */ /** which of the entries is selected */
public int selectedIndex; public int selectedIndex = -1;
/** type of join */ /** type of join */
public int type; public int type = TYPE_INTERSECT;
/** statistics for {@link FilterView} */ /** statistics for {@link FilterView} */
public int start, end, max; public int start, end, max;
} }
private TextView filterName;
private CustomFilterAdapter adapter; private CustomFilterAdapter adapter;
private final ArrayList<CustomFilterCriterion> criteria = private final ArrayList<CustomFilterCriterion> criteria =
new ArrayList<CustomFilterCriterion>(); new ArrayList<CustomFilterCriterion>();
@ -74,13 +85,16 @@ public class CustomFilterActivity extends ListActivity {
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
ContextManager.setContext(this);
setContentView(R.layout.custom_filter_activity); setContentView(R.layout.custom_filter_activity);
setTitle(R.string.CFA_title); setTitle(R.string.CFA_title);
DependencyInjectionService.getInstance().inject(this); DependencyInjectionService.getInstance().inject(this);
database.openForReading();
populateCriteria(); populateCriteria();
filterName = (TextView)findViewById(R.id.filterName);
List<CriterionInstance> startingCriteria = new ArrayList<CriterionInstance>(); List<CriterionInstance> startingCriteria = new ArrayList<CriterionInstance>();
startingCriteria.add(getStartingUniverse()); startingCriteria.add(getStartingUniverse());
adapter = new CustomFilterAdapter(this, startingCriteria); adapter = new CustomFilterAdapter(this, startingCriteria);
@ -109,7 +123,11 @@ public class CustomFilterActivity extends ListActivity {
values.put(Task.DUE_DATE.name, "%s"); values.put(Task.DUE_DATE.name, "%s");
CustomFilterCriterion criterion = new CustomFilterCriterion( CustomFilterCriterion criterion = new CustomFilterCriterion(
getString(R.string.CFC_dueBefore_text), getString(R.string.CFC_dueBefore_text),
Query.select(Task.ID).from(Task.TABLE).where(Task.DUE_DATE.lte("%s")).toString(), Query.select(Task.ID).from(Task.TABLE).where(
Criterion.and(
TaskCriteria.activeAndVisible(),
Task.DUE_DATE.gt(0),
Task.DUE_DATE.lte("%s"))).toString(),
values, r.getStringArray(R.array.CFC_dueBefore_entries), values, r.getStringArray(R.array.CFC_dueBefore_entries),
entryValues, ((BitmapDrawable)r.getDrawable(R.drawable.tango_calendar)).getBitmap(), entryValues, ((BitmapDrawable)r.getDrawable(R.drawable.tango_calendar)).getBitmap(),
getString(R.string.CFC_dueBefore_name)); getString(R.string.CFC_dueBefore_name));
@ -122,12 +140,17 @@ public class CustomFilterActivity extends ListActivity {
Integer.toString(Task.IMPORTANCE_SHOULD_DO), Integer.toString(Task.IMPORTANCE_SHOULD_DO),
Integer.toString(Task.IMPORTANCE_NONE), Integer.toString(Task.IMPORTANCE_NONE),
}; };
String[] entries = new String[] {
"!!!!", "!!!", "!!", "!"
};
values = new ContentValues(); values = new ContentValues();
values.put(Task.IMPORTANCE.name, "%s"); values.put(Task.IMPORTANCE.name, "%s");
criterion = new CustomFilterCriterion( criterion = new CustomFilterCriterion(
getString(R.string.CFC_importance_text), getString(R.string.CFC_importance_text),
Query.select(Task.ID).from(Task.TABLE).where(Task.IMPORTANCE.lte("%s")).toString(), Query.select(Task.ID).from(Task.TABLE).where(
values, r.getStringArray(R.array.EPr_default_importance), Criterion.and(TaskCriteria.activeAndVisible(),
Task.IMPORTANCE.lte("%s"))).toString(),
values, entries,
entryValues, ((BitmapDrawable)r.getDrawable(R.drawable.tango_warning)).getBitmap(), entryValues, ((BitmapDrawable)r.getDrawable(R.drawable.tango_warning)).getBitmap(),
getString(R.string.CFC_importance_name)); getString(R.string.CFC_importance_name));
criteria.add(criterion); criteria.add(criterion);
@ -142,7 +165,9 @@ public class CustomFilterActivity extends ListActivity {
values.put(TagService.TAG.name, "%s"); values.put(TagService.TAG.name, "%s");
criterion = new CustomFilterCriterion( criterion = new CustomFilterCriterion(
getString(R.string.CFC_tag_text), getString(R.string.CFC_tag_text),
Query.select(Metadata.TASK).from(Metadata.TABLE).where(Criterion.and( Query.select(Metadata.TASK).from(Metadata.TABLE).join(Join.inner(
Task.TABLE, Metadata.TASK.eq(Task.ID))).where(Criterion.and(
TaskCriteria.activeAndVisible(),
MetadataCriteria.withKey(TagService.KEY), MetadataCriteria.withKey(TagService.KEY),
TagService.TAG.eq("%s"))).toString(), TagService.TAG.eq("%s"))).toString(),
values, tagNames, tagNames, values, tagNames, tagNames,
@ -163,42 +188,155 @@ public class CustomFilterActivity extends ListActivity {
((Button)findViewById(R.id.add)).setOnClickListener(new View.OnClickListener() { ((Button)findViewById(R.id.add)).setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
menuItemInstance = null;
getListView().showContextMenu(); getListView().showContextMenu();
} }
}); });
getListView().setOnCreateContextMenuListener(this); ((Button)findViewById(R.id.saveAndView)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
saveAndView();
} }
});
// --- listeners and action events getListView().setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
@Override @Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
if(menu.hasVisibleItems())
return;
if(menuItemInstance == null) {
for(int i = 0; i < criteria.size(); i++) { for(int i = 0; i < criteria.size(); i++) {
CustomFilterCriterion item = criteria.get(i); CustomFilterCriterion item = criteria.get(i);
MenuItem menuItem = menu.add(MENU_GROUP_FILTER, i, i, item.name); SubMenu subMenu = menu.addSubMenu(item.name);
if(item.icon != null) if(item.icon != null)
menuItem.setIcon(new BitmapDrawable(item.icon)); subMenu.setIcon(new BitmapDrawable(item.icon));
for(int j = 0; j < item.entryTitles.length; j++) {
subMenu.add(CustomFilterActivity.MENU_GROUP_FILTER_OPTION,
i, j, item.entryTitles[j]);
}
} }
} }
// was invoked by short-pressing row
else {
CustomFilterCriterion criterion = menuItemInstance.criterion;
if(criterion.entryTitles == null ||
criterion.entryTitles.length == 0)
return;
menu.setHeaderTitle(criterion.name);
menu.setGroupCheckable(CustomFilterActivity.MENU_GROUP_FILTER_OPTION, true, true);
for(int i = 0; i < criterion.entryTitles.length; i++) {
menu.add(CustomFilterActivity.MENU_GROUP_FILTER_OPTION,
-1, i, criterion.entryTitles[i]);
}
}
}
});
}
// --- listeners and action events
CriterionInstance menuItemInstance = null;
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
if(menu.size() > 0)
menu.clear();
// view holder
if(v.getTag() != null) {
adapter.onCreateContextMenu(menu, v);
}
}
@SuppressWarnings("nls")
void saveAndView() {
StringBuilder sql = new StringBuilder(" WHERE ");
for(int i = 0; i < adapter.getCount(); i++) {
CriterionInstance instance = adapter.getItem(i);
if(instance.selectedIndex < 0 && instance.criterion.entryValues != null)
continue;
switch(instance.type) {
case CriterionInstance.TYPE_ADD:
sql.append("OR ");
break;
case CriterionInstance.TYPE_SUBTRACT:
sql.append("AND NOT ");
break;
case CriterionInstance.TYPE_INTERSECT:
sql.append("AND ");
break;
case CriterionInstance.TYPE_UNIVERSE:
}
// special code for all tasks universe
if(instance.criterion.sql == null)
sql.append(TaskCriteria.activeAndVisible()).append(' ');
else {
String subSql = instance.criterion.sql.replaceAll("%s",
instance.criterion.entryValues[instance.selectedIndex]);
subSql = CustomFilterCriterion.replacePlaceholders(subSql);
sql.append(Task.ID).append(" IN (").append(subSql).append(") ");
}
}
String title;
if(filterName.getText().length() > 0)
title = filterName.getText().toString();
else
title = filterName.getHint().toString();
ContentValues values = new ContentValues(); // TODO
Filter filter = new Filter(title, title, null, values);
filter.sqlQuery = sql.toString();
// TODO save
Intent taskListActivity = new Intent(this, TaskListActivity.class);
taskListActivity.putExtra(TaskListActivity.TOKEN_FILTER, filter);
startActivity(taskListActivity);
}
/** /**
* Recalculate all sizes * Recalculate all sizes
*/ */
@SuppressWarnings("nls") @SuppressWarnings("nls")
void updateList() { void updateList() {
int max = 0, last = -1; int max = 0, last = -1;
StringBuilder sql = new StringBuilder(Query.select(new CountProperty()).from(Task.TABLE).toString()). StringBuilder sql = new StringBuilder(Query.select(new CountProperty()).from(Task.TABLE).toString()).
append(" WHERE "); append(" WHERE ");
StringBuilder suggestedTitle = new StringBuilder();
for(int i = 0; i < adapter.getCount(); i++) { for(int i = 0; i < adapter.getCount(); i++) {
CriterionInstance instance = adapter.getItem(i); CriterionInstance instance = adapter.getItem(i);
if(instance.selectedIndex < 0 && instance.criterion.entryValues != null) {
instance.start = last;
instance.end = last;
continue;
}
String entryTitle = "";
if(instance.criterion.entryTitles != null) {
entryTitle = instance.criterion.entryTitles[instance.selectedIndex];
}
String title = instance.criterion.text.replace("%s", entryTitle);
switch(instance.type) { switch(instance.type) {
case CriterionInstance.TYPE_ADD: case CriterionInstance.TYPE_ADD:
sql.append("OR "); sql.append("OR ");
title = getString(R.string.CFA_type_add) + " " + title;
break; break;
case CriterionInstance.TYPE_SUBTRACT: case CriterionInstance.TYPE_SUBTRACT:
sql.append("AND NOT "); sql.append("AND NOT ");
title = getString(R.string.CFA_type_subtract) + " " + title;
break; break;
case CriterionInstance.TYPE_INTERSECT: case CriterionInstance.TYPE_INTERSECT:
sql.append("AND "); sql.append("AND ");
@ -206,18 +344,25 @@ public class CustomFilterActivity extends ListActivity {
case CriterionInstance.TYPE_UNIVERSE: case CriterionInstance.TYPE_UNIVERSE:
} }
suggestedTitle.append(title).append(' ');
// special code for all tasks universe // special code for all tasks universe
if(instance.criterion.sql == null) if(instance.criterion.sql == null)
sql.append(TaskCriteria.activeAndVisible()).append(' '); sql.append(TaskCriteria.activeAndVisible()).append(' ');
else else {
sql.append(Task.ID).append(" IN (").append(instance.criterion.sql).append(") "); String subSql = instance.criterion.sql.replaceAll("%s",
instance.criterion.entryValues[instance.selectedIndex]);
subSql = CustomFilterCriterion.replacePlaceholders(subSql);
sql.append(Task.ID).append(" IN (").append(subSql).append(") ");
}
Cursor cursor = database.getDatabase().rawQuery(sql.toString(), null); Cursor cursor = database.getDatabase().rawQuery(sql.toString(), null);
try { try {
cursor.moveToNext(); cursor.moveToNext();
max = Math.max(max, cursor.getCount());
instance.start = last == -1 ? cursor.getInt(0) : last; instance.start = last == -1 ? cursor.getInt(0) : last;
instance.end = cursor.getInt(0); instance.end = cursor.getInt(0);
last = instance.end;
max = Math.max(max, last);
} finally { } finally {
cursor.close(); cursor.close();
} }
@ -229,21 +374,38 @@ public class CustomFilterActivity extends ListActivity {
} }
adapter.notifyDataSetInvalidated(); adapter.notifyDataSetInvalidated();
if(adapter.getCount() > 1 && filterName.getText().length() == 0)
filterName.setHint(suggestedTitle);
} }
@Override @Override
public boolean onMenuItemSelected(int featureId, MenuItem item) { public boolean onMenuItemSelected(int featureId, MenuItem item) {
if(item.getGroupId() == MENU_GROUP_FILTER) { if(item.getGroupId() == MENU_GROUP_FILTER_OPTION) {
if(menuItemInstance == null) {
CustomFilterCriterion criterion = criteria.get(item.getItemId()); CustomFilterCriterion criterion = criteria.get(item.getItemId());
CriterionInstance instance = new CriterionInstance(); menuItemInstance = new CriterionInstance();
instance.criterion = criterion; menuItemInstance.criterion = criterion;
adapter.add(instance); }
menuItemInstance.selectedIndex = item.getOrder();
if(adapter.getPosition(menuItemInstance) == -1)
adapter.add(menuItemInstance);
updateList();
return true; return true;
} }
else if(item.getGroupId() == MENU_GROUP_FILTER_OPTION) else if(item.getGroupId() == MENU_GROUP_CONTEXT_TYPE) {
return adapter.onMenuItemSelected(item); CriterionInstance instance = adapter.getItem(item.getOrder());
instance.type = item.getItemId();
updateList();
}
else if(item.getGroupId() == MENU_GROUP_CONTEXT_DELETE) {
CriterionInstance instance = adapter.getItem(item.getOrder());
adapter.remove(instance);
updateList();
}
return super.onMenuItemSelected(featureId, item); return super.onMenuItemSelected(featureId, item);
} }

@ -12,14 +12,11 @@ import android.view.LayoutInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnCreateContextMenuListener;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import com.timsu.astrid.R; import com.timsu.astrid.R;
import com.todoroo.astrid.api.CustomFilterCriterion;
import com.todoroo.astrid.core.CustomFilterActivity.CriterionInstance; import com.todoroo.astrid.core.CustomFilterActivity.CriterionInstance;
import com.todoroo.astrid.model.AddOn; import com.todoroo.astrid.model.AddOn;
@ -53,35 +50,41 @@ public class CustomFilterAdapter extends ArrayAdapter<CriterionInstance> {
return; return;
// keep the filter options in the name context menu // keep the filter options in the name context menu
viewHolder.name.showContextMenu(); ((CustomFilterActivity)activity).menuItemInstance = viewHolder.item;
((CustomFilterActivity)activity).getListView().showContextMenu();
} }
}; };
OnCreateContextMenuListener createContextMenuListener = new OnCreateContextMenuListener() { public void onCreateContextMenu(ContextMenu menu, View v) {
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo info) { // view holder
ViewHolder viewHolder = (ViewHolder) ((View)view.getParent()).getTag(); ViewHolder viewHolder = (ViewHolder) v.getTag();
CustomFilterCriterion criteria = viewHolder.item.criterion; if(viewHolder == null || viewHolder.item.type == CriterionInstance.TYPE_UNIVERSE)
if(criteria.entryTitles == null ||
criteria.entryTitles.length == 0)
return; return;
menu.setHeaderTitle(criteria.name); int index = getPosition(viewHolder.item);
menu.setGroupCheckable(CustomFilterActivity.MENU_GROUP_FILTER_OPTION, true, true);
for(int i = 0; i < criteria.entryTitles.length; i++) { menu.setHeaderTitle(viewHolder.name.getText());
menu.add(CustomFilterActivity.MENU_GROUP_FILTER_OPTION, if(viewHolder.icon.getVisibility() == View.VISIBLE)
getPosition(viewHolder.item), menu.setHeaderIcon(viewHolder.icon.getDrawable());
i, criteria.entryTitles[i]);
}
} MenuItem item = menu.add(CustomFilterActivity.MENU_GROUP_CONTEXT_TYPE, CriterionInstance.TYPE_INTERSECT, index,
}; activity.getString(R.string.CFA_context_chain,
activity.getString(R.string.CFA_type_intersect)));
item.setChecked(viewHolder.item.type == CriterionInstance.TYPE_INTERSECT);
item = menu.add(CustomFilterActivity.MENU_GROUP_CONTEXT_TYPE, CriterionInstance.TYPE_ADD, index,
activity.getString(R.string.CFA_context_chain,
activity.getString(R.string.CFA_type_add)));
item.setChecked(viewHolder.item.type == CriterionInstance.TYPE_ADD);
item = menu.add(CustomFilterActivity.MENU_GROUP_CONTEXT_TYPE, CriterionInstance.TYPE_SUBTRACT, index,
activity.getString(R.string.CFA_context_chain,
activity.getString(R.string.CFA_type_subtract)));
item.setChecked(viewHolder.item.type == CriterionInstance.TYPE_SUBTRACT);
menu.setGroupCheckable(CustomFilterActivity.MENU_GROUP_CONTEXT_TYPE, true, true);
public boolean onMenuItemSelected(MenuItem item) { menu.add(CustomFilterActivity.MENU_GROUP_CONTEXT_DELETE, 0, index,
CriterionInstance instance = getItem(item.getItemId()); R.string.CFA_context_delete);
instance.selectedIndex = item.getOrder();
((CustomFilterActivity)activity).updateList();
return true;
} }
// --- view construction // --- view construction
@ -103,8 +106,8 @@ public class CustomFilterAdapter extends ArrayAdapter<CriterionInstance> {
initializeView(convertView); initializeView(convertView);
// listeners // listeners
convertView.setOnCreateContextMenuListener(activity);
convertView.setOnClickListener(filterClickListener); convertView.setOnClickListener(filterClickListener);
viewHolder.name.setOnCreateContextMenuListener(createContextMenuListener);
return convertView; return convertView;
} }
@ -123,29 +126,25 @@ public class CustomFilterAdapter extends ArrayAdapter<CriterionInstance> {
CriterionInstance item = viewHolder.item; CriterionInstance item = viewHolder.item;
String entryTitle = ""; String entryTitle = "";
if(item.selectedIndex >= 0 && item.selectedIndex < item.criterion.entryTitles.length) { if(item.selectedIndex >= 0 && item.criterion.entryTitles != null &&
item.selectedIndex < item.criterion.entryTitles.length) {
entryTitle = item.criterion.entryTitles[item.selectedIndex]; entryTitle = item.criterion.entryTitles[item.selectedIndex];
} }
String title = item.criterion.text.replace("%s", entryTitle); String title = item.criterion.text.replace("%s", entryTitle);
boolean notFirst = getPosition(item) > 1;
viewHolder.type.setVisibility(item.type == CriterionInstance.TYPE_UNIVERSE ? viewHolder.type.setVisibility(item.type == CriterionInstance.TYPE_UNIVERSE ?
View.GONE : View.VISIBLE); View.GONE : View.VISIBLE);
switch(item.type) { switch(item.type) {
case CriterionInstance.TYPE_ADD: case CriterionInstance.TYPE_ADD:
viewHolder.type.setImageResource(R.drawable.arrow_join); viewHolder.type.setImageResource(R.drawable.arrow_join);
if(notFirst)
title = activity.getString(R.string.CFA_type_add) + " " + title; title = activity.getString(R.string.CFA_type_add) + " " + title;
break; break;
case CriterionInstance.TYPE_SUBTRACT: case CriterionInstance.TYPE_SUBTRACT:
viewHolder.type.setImageResource(R.drawable.arrow_branch); viewHolder.type.setImageResource(R.drawable.arrow_branch);
if(notFirst)
title = activity.getString(R.string.CFA_type_subtract) + " " + title; title = activity.getString(R.string.CFA_type_subtract) + " " + title;
break; break;
case CriterionInstance.TYPE_INTERSECT: case CriterionInstance.TYPE_INTERSECT:
viewHolder.type.setImageResource(R.drawable.arrow_down); viewHolder.type.setImageResource(R.drawable.arrow_down);
if(notFirst)
title = activity.getString(R.string.CFA_type_intersect) + " " + title;
break; break;
} }

@ -11,8 +11,7 @@
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:hint="@string/CFA_filterName_hint" android:hint="@string/CFA_filterName_hint"/>
android:text="@string/CFA_filterName_new"/>
<!-- List --> <!-- List -->
<ListView android:id="@android:id/list" <ListView android:id="@android:id/list"
@ -40,7 +39,7 @@
android:text="@string/CFA_button_add" /> android:text="@string/CFA_button_add" />
<Button <Button
android:id="@+id/discard_basic" android:id="@+id/saveAndView"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"

@ -32,12 +32,12 @@
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:layout_weight="100" android:layout_weight="100"
android:paddingLeft="5dip" android:paddingLeft="5dip"
android:textSize="22sp" android:textSize="18sp"
android:gravity="center_vertical"/> android:gravity="center_vertical"/>
<!-- filter graphic --> <!-- filter graphic -->
<com.todoroo.astrid.core.FilterView android:id="@+id/filter" <com.todoroo.astrid.core.FilterView android:id="@+id/filter"
android:layout_width="64dip" android:layout_width="64px"
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:layout_weight="1" android:layout_weight="1"
android:paddingLeft="5dip" android:paddingLeft="5dip"

@ -41,8 +41,11 @@
<!-- Filter Criteria Type: intersect (at the begging of title of the criteria) --> <!-- Filter Criteria Type: intersect (at the begging of title of the criteria) -->
<string name="CFA_type_intersect">also</string> <string name="CFA_type_intersect">also</string>
<!-- Filter Criteria Context Menu: chaining (%s chain type as above) -->
<string name="CFA_context_chain">Chaining: %s</string>
<!-- Filter Criteria Context Menu: delete --> <!-- Filter Criteria Context Menu: delete -->
<string name="CFA_context_delete">Delete</string> <string name="CFA_context_delete">Delete Row</string>
<!-- Filter Button: add new --> <!-- Filter Button: add new -->
<string name="CFA_button_add">Add Criteria</string> <string name="CFA_button_add">Add Criteria</string>
@ -66,7 +69,7 @@
</string-array> </string-array>
<!-- Criteria: importance - display text --> <!-- Criteria: importance - display text -->
<string name="CFC_importance_text">Importance >= %s</string> <string name="CFC_importance_text">Importance: %s</string>
<!-- Criteria: importance - name of criteria --> <!-- Criteria: importance - name of criteria -->
<string name="CFC_importance_name">Importance...</string> <string name="CFC_importance_name">Importance...</string>

Loading…
Cancel
Save