|
|
|
@ -6,35 +6,62 @@ package com.todoroo.astrid.adapter;
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
|
|
|
|
|
import android.app.Activity;
|
|
|
|
|
import android.content.BroadcastReceiver;
|
|
|
|
|
import android.content.Context;
|
|
|
|
|
import android.content.Intent;
|
|
|
|
|
import android.content.IntentFilter;
|
|
|
|
|
import android.graphics.Color;
|
|
|
|
|
import android.os.Parcelable;
|
|
|
|
|
import android.util.DisplayMetrics;
|
|
|
|
|
import android.view.Gravity;
|
|
|
|
|
import android.util.Log;
|
|
|
|
|
import android.view.LayoutInflater;
|
|
|
|
|
import android.view.View;
|
|
|
|
|
import android.view.ViewGroup;
|
|
|
|
|
import android.widget.AbsListView;
|
|
|
|
|
import android.widget.BaseExpandableListAdapter;
|
|
|
|
|
import android.widget.FrameLayout;
|
|
|
|
|
import android.widget.ExpandableListView;
|
|
|
|
|
import android.widget.ImageView;
|
|
|
|
|
import android.widget.LinearLayout;
|
|
|
|
|
import android.widget.TextView;
|
|
|
|
|
import android.widget.ImageView.ScaleType;
|
|
|
|
|
|
|
|
|
|
import com.timsu.astrid.R;
|
|
|
|
|
import com.todoroo.astrid.api.AstridApiConstants;
|
|
|
|
|
import com.todoroo.astrid.api.FilterCategory;
|
|
|
|
|
import com.todoroo.astrid.api.FilterListHeader;
|
|
|
|
|
import com.todoroo.astrid.api.FilterListItem;
|
|
|
|
|
|
|
|
|
|
public class FilterAdapter extends BaseExpandableListAdapter {
|
|
|
|
|
|
|
|
|
|
private final ArrayList<FilterListItem> items;
|
|
|
|
|
// --- style constants
|
|
|
|
|
|
|
|
|
|
public int filterStyle = R.style.TextAppearance_FLA_Filter;
|
|
|
|
|
public int categoryStyle = R.style.TextAppearance_FLA_Category;
|
|
|
|
|
public int headerStyle = R.style.TextAppearance_FLA_Header;
|
|
|
|
|
|
|
|
|
|
// --- instance variables
|
|
|
|
|
|
|
|
|
|
protected final Activity activity;
|
|
|
|
|
protected final ExpandableListView listView;
|
|
|
|
|
private final ArrayList<FilterListItem> items;
|
|
|
|
|
private final DisplayMetrics metrics = new DisplayMetrics();
|
|
|
|
|
private final FilterReceiver filterReceiver = new FilterReceiver();
|
|
|
|
|
private final int layout;
|
|
|
|
|
private final LayoutInflater inflater;
|
|
|
|
|
|
|
|
|
|
public FilterAdapter(Activity activity) {
|
|
|
|
|
public FilterAdapter(Activity activity, ExpandableListView listView,
|
|
|
|
|
int rowLayout) {
|
|
|
|
|
super();
|
|
|
|
|
this.activity = activity;
|
|
|
|
|
this.items = new ArrayList<FilterListItem>();
|
|
|
|
|
this.listView = listView;
|
|
|
|
|
this.layout = rowLayout;
|
|
|
|
|
|
|
|
|
|
inflater = (LayoutInflater) activity.getSystemService(
|
|
|
|
|
Context.LAYOUT_INFLATER_SERVICE);
|
|
|
|
|
|
|
|
|
|
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
|
|
|
|
|
listView.setGroupIndicator(
|
|
|
|
|
activity.getResources().getDrawable(R.drawable.expander_group));
|
|
|
|
|
|
|
|
|
|
getLists();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean hasStableIds() {
|
|
|
|
@ -49,6 +76,35 @@ public class FilterAdapter extends BaseExpandableListAdapter {
|
|
|
|
|
items.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Create or reuse a view
|
|
|
|
|
* @param convertView
|
|
|
|
|
* @param parent
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
|
|
|
|
protected View newView(View convertView, ViewGroup parent) {
|
|
|
|
|
if(convertView == null) {
|
|
|
|
|
convertView = inflater.inflate(layout, parent, false);
|
|
|
|
|
ViewHolder viewHolder = new ViewHolder();
|
|
|
|
|
viewHolder.view = convertView;
|
|
|
|
|
viewHolder.expander = (ImageView)convertView.findViewById(R.id.expander);
|
|
|
|
|
viewHolder.icon = (ImageView)convertView.findViewById(R.id.icon);
|
|
|
|
|
viewHolder.name = (TextView)convertView.findViewById(R.id.name);
|
|
|
|
|
viewHolder.selected = (ImageView)convertView.findViewById(R.id.selected);
|
|
|
|
|
convertView.setTag(viewHolder);
|
|
|
|
|
}
|
|
|
|
|
return convertView;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private class ViewHolder {
|
|
|
|
|
public FilterListItem item;
|
|
|
|
|
public ImageView expander;
|
|
|
|
|
public ImageView icon;
|
|
|
|
|
public TextView name;
|
|
|
|
|
public ImageView selected;
|
|
|
|
|
public View view;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ======================================================================
|
|
|
|
|
* ========================================================== child nodes
|
|
|
|
|
* ====================================================================== */
|
|
|
|
@ -74,9 +130,13 @@ public class FilterAdapter extends BaseExpandableListAdapter {
|
|
|
|
|
|
|
|
|
|
public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
|
|
|
|
|
View convertView, ViewGroup parent) {
|
|
|
|
|
FilterListItem item = (FilterListItem)getChild(groupPosition, childPosition);
|
|
|
|
|
View textView = getStandardView(item, true);
|
|
|
|
|
return textView;
|
|
|
|
|
|
|
|
|
|
convertView = newView(convertView, parent);
|
|
|
|
|
ViewHolder viewHolder = (ViewHolder) convertView.getTag();
|
|
|
|
|
viewHolder.item = (FilterListItem)getChild(groupPosition, childPosition);
|
|
|
|
|
populateView(viewHolder, true, false);
|
|
|
|
|
|
|
|
|
|
return convertView;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ======================================================================
|
|
|
|
@ -97,8 +157,11 @@ public class FilterAdapter extends BaseExpandableListAdapter {
|
|
|
|
|
|
|
|
|
|
public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
|
|
|
|
|
ViewGroup parent) {
|
|
|
|
|
View view = getView((FilterListItem)getGroup(groupPosition), false, isExpanded);
|
|
|
|
|
return view;
|
|
|
|
|
convertView = newView(convertView, parent);
|
|
|
|
|
ViewHolder viewHolder = (ViewHolder) convertView.getTag();
|
|
|
|
|
viewHolder.item = (FilterListItem) getGroup(groupPosition);
|
|
|
|
|
populateView(viewHolder, false, isExpanded);
|
|
|
|
|
return convertView;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean isChildSelectable(int groupPosition, int childPosition) {
|
|
|
|
@ -106,110 +169,156 @@ public class FilterAdapter extends BaseExpandableListAdapter {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ======================================================================
|
|
|
|
|
* ================================================================ views
|
|
|
|
|
* ============================================================ selection
|
|
|
|
|
* ====================================================================== */
|
|
|
|
|
|
|
|
|
|
public View getView(FilterListItem item, boolean isChild, boolean isExpanded) {
|
|
|
|
|
if(item instanceof FilterListHeader)
|
|
|
|
|
return getHeaderView((FilterListHeader)item, isChild);
|
|
|
|
|
else if(item instanceof FilterCategory)
|
|
|
|
|
return getCategoryView((FilterCategory)item, isExpanded);
|
|
|
|
|
private FilterListItem selection = null;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sets the selected item to this one
|
|
|
|
|
* @param picked
|
|
|
|
|
*/
|
|
|
|
|
public void setSelection(FilterListItem picked) {
|
|
|
|
|
if(picked == selection)
|
|
|
|
|
selection = null;
|
|
|
|
|
else
|
|
|
|
|
return getStandardView(item, isChild);
|
|
|
|
|
selection = picked;
|
|
|
|
|
int scroll = listView.getScrollY();
|
|
|
|
|
notifyDataSetInvalidated();
|
|
|
|
|
listView.scrollTo(0, scroll);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public View getCategoryView(FilterCategory filter, boolean isExpanded) {
|
|
|
|
|
AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
|
|
|
|
|
ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
|
|
|
|
|
|
|
|
|
FrameLayout layout = new FrameLayout(activity);
|
|
|
|
|
layout.setLayoutParams(lp);
|
|
|
|
|
/**
|
|
|
|
|
* Gets the currently selected item
|
|
|
|
|
* @return null if no item is to be selected
|
|
|
|
|
*/
|
|
|
|
|
public FilterListItem getSelection() {
|
|
|
|
|
return selection;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImageView image = new ImageView(activity);
|
|
|
|
|
if(isExpanded)
|
|
|
|
|
image.setImageResource(R.drawable.expander_ic_maximized);
|
|
|
|
|
else
|
|
|
|
|
image.setImageResource(R.drawable.expander_ic_minimized);
|
|
|
|
|
FrameLayout.LayoutParams expansionImageLayout = new FrameLayout.LayoutParams(
|
|
|
|
|
32, 32);
|
|
|
|
|
expansionImageLayout.gravity = Gravity.CENTER_VERTICAL;
|
|
|
|
|
image.setPadding(5, 0, 5, 0);
|
|
|
|
|
image.setLayoutParams(expansionImageLayout);
|
|
|
|
|
image.setScaleType(ScaleType.FIT_CENTER);
|
|
|
|
|
layout.addView(image);
|
|
|
|
|
/* ======================================================================
|
|
|
|
|
* ============================================================= receiver
|
|
|
|
|
* ====================================================================== */
|
|
|
|
|
|
|
|
|
|
TextView textView = new TextView(activity);
|
|
|
|
|
textView.setGravity(Gravity.CENTER_VERTICAL);
|
|
|
|
|
textView.setText(filter.listingTitle);
|
|
|
|
|
textView.setTextAppearance(activity, R.style.TextAppearance_FLA_Category);
|
|
|
|
|
/**
|
|
|
|
|
* Receiver which receives intents to add items to the filter list
|
|
|
|
|
*
|
|
|
|
|
* @author Tim Su <tim@todoroo.com>
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public class FilterReceiver extends BroadcastReceiver {
|
|
|
|
|
@Override
|
|
|
|
|
public void onReceive(Context context, Intent intent) {
|
|
|
|
|
try {
|
|
|
|
|
final Parcelable[] filters = intent.getExtras().
|
|
|
|
|
getParcelableArray(AstridApiConstants.EXTRAS_RESPONSE);
|
|
|
|
|
for (Parcelable item : filters) {
|
|
|
|
|
add((FilterListItem)item);
|
|
|
|
|
onReceiveFilter((FilterListItem)item);
|
|
|
|
|
}
|
|
|
|
|
notifyDataSetChanged();
|
|
|
|
|
|
|
|
|
|
View view = augmentView(textView, filter);
|
|
|
|
|
view.setPadding((int) (33 * metrics.density), 5, 0, 5);
|
|
|
|
|
FrameLayout.LayoutParams rowLayout = new FrameLayout.LayoutParams(
|
|
|
|
|
ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
|
|
|
|
rowLayout.gravity = Gravity.CENTER_VERTICAL;
|
|
|
|
|
view.setLayoutParams(rowLayout);
|
|
|
|
|
activity.runOnUiThread(new Runnable() {
|
|
|
|
|
@Override
|
|
|
|
|
public void run() {
|
|
|
|
|
expandList(filters);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
Log.e("receive-filter-" + //$NON-NLS-1$
|
|
|
|
|
intent.getStringExtra(AstridApiConstants.EXTRAS_ADDON),
|
|
|
|
|
e.toString(), e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
layout.addView(view);
|
|
|
|
|
/**
|
|
|
|
|
* Expand the first category filter in this group
|
|
|
|
|
* @param filters
|
|
|
|
|
*/
|
|
|
|
|
protected void expandList(Parcelable[] filters) {
|
|
|
|
|
for(Parcelable filter : filters) {
|
|
|
|
|
if(filter instanceof FilterCategory) {
|
|
|
|
|
for(int i = 0; i < getGroupCount(); i++)
|
|
|
|
|
if(getGroup(i) == filter) {
|
|
|
|
|
listView.expandGroup(i);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return layout;
|
|
|
|
|
/**
|
|
|
|
|
* Broadcast a request for lists. The request is sent to every
|
|
|
|
|
* application registered to listen for this broadcast. Each application
|
|
|
|
|
* can then add lists to this activity
|
|
|
|
|
*/
|
|
|
|
|
protected void getLists() {
|
|
|
|
|
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_REQUEST_FILTERS);
|
|
|
|
|
activity.sendOrderedBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Decorate textview and add an image if the filter requests it
|
|
|
|
|
* @param textView
|
|
|
|
|
* @param filter
|
|
|
|
|
* @return final view ready to be added
|
|
|
|
|
* Call this method from your activity's onResume() method
|
|
|
|
|
*/
|
|
|
|
|
private View augmentView(TextView textView, FilterListItem filter) {
|
|
|
|
|
if(filter.listingIcon != null) {
|
|
|
|
|
LinearLayout layout = new LinearLayout(activity);
|
|
|
|
|
layout.setGravity(textView.getGravity());
|
|
|
|
|
layout.setOrientation(LinearLayout.HORIZONTAL);
|
|
|
|
|
public void registerRecevier() {
|
|
|
|
|
activity.registerReceiver(filterReceiver,
|
|
|
|
|
new IntentFilter(AstridApiConstants.BROADCAST_SEND_FILTERS));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImageView icon = new ImageView(activity);
|
|
|
|
|
icon.setImageBitmap(filter.listingIcon);
|
|
|
|
|
icon.setScaleType(ScaleType.CENTER);
|
|
|
|
|
icon.setPadding(0, 0, 15, 0);
|
|
|
|
|
layout.addView(icon);
|
|
|
|
|
layout.addView(textView);
|
|
|
|
|
return layout;
|
|
|
|
|
/**
|
|
|
|
|
* Call this method from your activity's onResume() method
|
|
|
|
|
*/
|
|
|
|
|
public void unregisterRecevier() {
|
|
|
|
|
activity.unregisterReceiver(filterReceiver);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return textView;
|
|
|
|
|
/**
|
|
|
|
|
* Called when an item comes through. Override if you like
|
|
|
|
|
* @param item
|
|
|
|
|
*/
|
|
|
|
|
public void onReceiveFilter(FilterListItem item) {
|
|
|
|
|
// do nothing
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public View getStandardView(FilterListItem filter, boolean isChild) {
|
|
|
|
|
AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
|
|
|
|
|
ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
|
|
|
|
/* ======================================================================
|
|
|
|
|
* ================================================================ views
|
|
|
|
|
* ====================================================================== */
|
|
|
|
|
|
|
|
|
|
TextView textView = new TextView(activity);
|
|
|
|
|
textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
|
|
|
|
|
textView.setText(filter.listingTitle);
|
|
|
|
|
textView.setTextAppearance(activity, R.style.TextAppearance_FLA_Filter);
|
|
|
|
|
public void populateView(ViewHolder viewHolder, boolean isChild, boolean isExpanded) {
|
|
|
|
|
FilterListItem filter = viewHolder.item;
|
|
|
|
|
|
|
|
|
|
View view = augmentView(textView, filter);
|
|
|
|
|
view.setBackgroundDrawable(null);
|
|
|
|
|
view.setLayoutParams(lp);
|
|
|
|
|
view.setPadding((int) ((isChild ? 27 : 7) * metrics.density), 8, 0, 8);
|
|
|
|
|
viewHolder.view.setBackgroundResource(0);
|
|
|
|
|
viewHolder.expander.setVisibility(View.GONE);
|
|
|
|
|
|
|
|
|
|
return view;
|
|
|
|
|
if(viewHolder.item instanceof FilterListHeader) {
|
|
|
|
|
viewHolder.name.setTextAppearance(activity, headerStyle);
|
|
|
|
|
viewHolder.view.setBackgroundResource(R.drawable.edit_titlebar);
|
|
|
|
|
viewHolder.view.setPadding((int) ((isChild ? 33 : 7) * metrics.density), 5, 0, 5);
|
|
|
|
|
} else if(viewHolder.item instanceof FilterCategory) {
|
|
|
|
|
viewHolder.expander.setVisibility(View.VISIBLE);
|
|
|
|
|
if(isExpanded)
|
|
|
|
|
viewHolder.expander.setImageResource(R.drawable.expander_ic_maximized);
|
|
|
|
|
else
|
|
|
|
|
viewHolder.expander.setImageResource(R.drawable.expander_ic_minimized);
|
|
|
|
|
viewHolder.name.setTextAppearance(activity, categoryStyle);
|
|
|
|
|
viewHolder.view.setPadding((int)(7 * metrics.density), 8, 0, 8);
|
|
|
|
|
} else {
|
|
|
|
|
viewHolder.name.setTextAppearance(activity, filterStyle);
|
|
|
|
|
viewHolder.view.setPadding((int) ((isChild ? 27 : 7) * metrics.density), 8, 0, 8);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public View getHeaderView(FilterListHeader header, boolean isChild) {
|
|
|
|
|
AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
|
|
|
|
|
ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
|
|
|
|
|
|
|
|
|
TextView textView = new TextView(activity);
|
|
|
|
|
textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
|
|
|
|
|
textView.setTextAppearance(activity, R.style.TextAppearance_FLA_Header);
|
|
|
|
|
textView.setText(header.listingTitle);
|
|
|
|
|
viewHolder.icon.setVisibility(filter.listingIcon != null ? View.VISIBLE : View.GONE);
|
|
|
|
|
viewHolder.icon.setImageBitmap(filter.listingIcon);
|
|
|
|
|
|
|
|
|
|
View view = augmentView(textView, header);
|
|
|
|
|
view.setBackgroundResource(R.drawable.edit_titlebar);
|
|
|
|
|
view.setLayoutParams(lp);
|
|
|
|
|
view.setPadding((int) ((isChild ? 33 : 7) * metrics.density), 5, 0, 5);
|
|
|
|
|
viewHolder.name.setText(filter.listingTitle);
|
|
|
|
|
|
|
|
|
|
return view;
|
|
|
|
|
// selection
|
|
|
|
|
if(selection == viewHolder.item) {
|
|
|
|
|
viewHolder.selected.setVisibility(View.VISIBLE);
|
|
|
|
|
viewHolder.view.setBackgroundColor(Color.rgb(128, 230, 0));
|
|
|
|
|
} else
|
|
|
|
|
viewHolder.selected.setVisibility(View.GONE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|