/**
* Filename: GroupedListAdapter.java (in org.repin.android.ui.list)
* This file is part of the Redpin project.
*
* Redpin is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* Redpin 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Redpin. If not, see <http://www.gnu.org/licenses/>.
*
* (c) Copyright ETH Zurich, Luba Rogoleva, Pascal Brogle, Philipp Bolliger, 2010, ALL RIGHTS RESERVED.
*
* www.redpin.org
*/
package org.redpin.android.ui.list;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import org.redpin.android.R;
import org.redpin.android.provider.RedpinContract;
import android.app.ListActivity;
import android.database.Cursor;
import android.net.Uri;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Adapter;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
/**
* Extended {@link Adapter} that is the bridge between a grouped
* {@link ListView} and the data that backs the list
*
* @author Luba Rogoleva (lubar@student.ethz.ch)
* @author Pascal Brogle (broglep@student.ethz.ch)
*
*/
public class GroupedListAdapter extends BaseAdapter {
private final LinkedHashMap<String, SimpleCursorAdapter> sections;
private final SimpleCursorAdapter maps;
private ListActivity activity;
public final static int TYPE_SECTION_HEADER = 0;
public GroupedListAdapter(ListActivity activity, String filterOnMap,
String filterOnLocation) {
super();
this.activity = activity;
Uri uri = RedpinContract.Map.CONTENT_URI;
List<Long> additionalMaps = getMapsToConsider(filterOnMap,
filterOnLocation);
int additionalMapsNum = additionalMaps.size();
if (additionalMapsNum != 0) {
String listAsString = getListAsString(additionalMaps, ",");
String where = "(" + filterOnMap + ") OR " + RedpinContract.Map._ID
+ " IN (" + listAsString + ")";
maps = new SimpleCursorAdapter(activity, R.layout.list_row_header,
activity.managedQuery(uri, null, where, null, null),
new String[] { RedpinContract.Map.NAME },
new int[] { R.id.list_row_label });
} else {
maps = new SimpleCursorAdapter(activity, R.layout.list_row_header,
activity.managedQuery(uri, null, filterOnMap, null, null),
new String[] { RedpinContract.Map.NAME },
new int[] { R.id.list_row_label });
}
Cursor c = maps.getCursor();
sections = new LinkedHashMap<String, SimpleCursorAdapter>(c.getCount());
while (c.moveToNext()) {
System.out.println(c.getString(c
.getColumnIndex(RedpinContract.Map.NAME)));
long mapId = c.getLong(c.getColumnIndex(RedpinContract.Map._ID));
String where = null;
if (additionalMaps.contains(mapId)) { // only one or more locations
// match
where = filterOnLocation;
}
SimpleCursorAdapter a = new SimpleCursorAdapter(activity,
R.layout.list_row, activity.managedQuery(
RedpinContract.Location.buildFilterUri(mapId),
null, where, null, null),
new String[] { RedpinContract.Location.SYMBOLIC_ID },
new int[] { R.id.list_row_label });
System.out.println(c.getString(c
.getColumnIndex(RedpinContract.Map.NAME))
+ ": " + a.getCount());
sections.put(
c.getString(c.getColumnIndex(RedpinContract.Map.NAME)), a);
}
}
// for all maps that do not match the query look for all locations that
// match
private List<Long> getMapsToConsider(String filterOnMap,
String filterOnLocation) {
List<Long> mapsToConsider = new ArrayList<Long>();
SimpleCursorAdapter notmatchmaps = null;
if (filterOnMap != null && filterOnLocation != null) {
notmatchmaps = new SimpleCursorAdapter(activity,
R.layout.list_row_header, activity.managedQuery(
RedpinContract.Map.CONTENT_URI, null, " NOT ("
+ filterOnMap + ")", null, null),
new String[] { RedpinContract.Map.NAME },
new int[] { R.id.list_row_label });
Cursor cursor = notmatchmaps.getCursor();
while (cursor.moveToNext()) {
long mapId = cursor.getLong(cursor
.getColumnIndex(RedpinContract.Map._ID));
SimpleCursorAdapter a = new SimpleCursorAdapter(activity,
R.layout.list_row, activity.managedQuery(
RedpinContract.Location.buildFilterUri(mapId),
null, filterOnLocation, null, null),
new String[] { RedpinContract.Location.SYMBOLIC_ID },
new int[] { R.id.list_row_label });
if (a.getCount() > 0)
mapsToConsider.add(mapId);
}
}
return mapsToConsider;
}
private String getListAsString(List<Long> list, String separator) {
String listAsString = "";
for (Long item : list) {
if (listAsString.length() != 0)
listAsString += ",";
listAsString += item;
}
return listAsString;
}
/**
* {@inheritDoc}
*/
@Override
public int getCount() {
int total = 0;
for (Adapter adapter : this.sections.values()) {
total += adapter.getCount() + 1;
}
return total;
}
/**
* {@inheritDoc}
*/
@Override
public int getViewTypeCount() {
int total = 1;
for (Adapter adapter : this.sections.values()) {
total += adapter.getViewTypeCount();
}
return total;
}
/**
* {@inheritDoc}
*/
@Override
public int getItemViewType(int position) {
int type = 1;
for (Object section : this.sections.keySet()) {
SimpleCursorAdapter adapter = sections.get(section);
int size = adapter.getCount() + 1;
// check if position inside this section
if (position == 0)
return TYPE_SECTION_HEADER;
if (position < size)
return type + adapter.getItemViewType(position - 1);
// otherwise jump into next section
position -= size;
type += adapter.getViewTypeCount();
}
return -1;
}
/**
* {@inheritDoc}
*/
@Override
public Object getItem(int position) {
for (String section : this.sections.keySet()) {
SimpleCursorAdapter adapter = sections.get(section);
int size = adapter.getCount() + 1;
// check if position inside this section
if (position == 0)
return section;
if (position < size)
return adapter.getItem(position - 1);
// otherwise jump into next section
position -= size;
}
return null;
}
public boolean areAllItemsSelectable() {
return false;
}
/**
* {@inheritDoc}
*/
@Override
public boolean isEnabled(int position) {
return (getItemViewType(position) != TYPE_SECTION_HEADER);
}
/**
* {@inheritDoc}
*/
@Override
public long getItemId(int position) {
for (String section : this.sections.keySet()) {
SimpleCursorAdapter adapter = sections.get(section);
int size = adapter.getCount() + 1;
// check if position inside this section
if (position == 0)
return 0;
if (position < size)
return adapter.getItemId(position - 1);
// otherwise jump into next section
position -= size;
}
return 0;
}
/**
* {@inheritDoc}
*/
@Override
public View getView(int position, View convertView, ViewGroup parent) {
int sectionnum = 0;
for (Object section : this.sections.keySet()) {
SimpleCursorAdapter adapter = sections.get(section);
int size = adapter.getCount() + 1;
// check if position inside this section
if (position == 0)
return maps.getView(sectionnum, convertView, parent);
if (position < size)
return adapter.getView(position - 1, convertView, parent);
// otherwise jump into next section
position -= size;
sectionnum++;
}
return null;
}
}