package com.realtrackandroid.views.participationsdonesummaries; import java.util.Calendar; import java.util.Collections; import java.util.Comparator; import java.util.List; import org.achartengine.ChartFactory; import org.achartengine.GraphicalView; import org.achartengine.model.XYMultipleSeriesDataset; import org.achartengine.model.XYSeries; import org.achartengine.renderer.XYMultipleSeriesRenderer; import org.achartengine.renderer.XYSeriesRenderer; import org.achartengine.renderer.XYSeriesRenderer.FillOutsideLine; import android.app.Activity; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseExpandableListAdapter; import android.widget.ExpandableListView; import android.widget.LinearLayout; import android.widget.TextView; import com.realtrackandroid.R; import com.realtrackandroid.common.StyledButton; import com.realtrackandroid.models.activities.Activities; import com.realtrackandroid.models.activities.Participation; import com.realtrackandroid.models.projects.Project; import com.realtrackandroid.views.participationsdonesummaries.ParticipationSummaryActivity.ActivityHolder; import com.realtrackandroid.views.participationsdonesummaries.ParticipationSummaryActivity.ParticipationHolder; import com.realtrackandroid.views.participationsdonesummaries.ParticipationSummaryActivity.ProjectHolder; public class ParticipationSummaryListAdapter extends BaseExpandableListAdapter { private Context context; private int groupLayoutResourceId; private int childLayoutResourceId; private List<ProjectHolder> projectHolderData = null; private View row; private LayoutInflater inflater; private ExpandableListView listView; private XYSeries mCurrentSeries; private XYMultipleSeriesDataset mDataset; private GraphicalView mChartView; private XYMultipleSeriesRenderer mRenderer; private Calendar activityCal, participationCal; public ParticipationSummaryListAdapter(Context context, int groupLayoutResourceId, int childLayoutResourceId, ExpandableListView expandableListView, List<ProjectHolder> projectHolderData) { super(); this.groupLayoutResourceId = groupLayoutResourceId; this.childLayoutResourceId = childLayoutResourceId; this.context = context; listView = expandableListView; this.projectHolderData = projectHolderData; participationCal = Calendar.getInstance(); activityCal = Calendar.getInstance(); } public void setInflater(LayoutInflater inflater) { this.inflater = inflater; } @Override public int getGroupCount() { return projectHolderData.size(); } @Override public int getChildrenCount(int groupPosition) { return projectHolderData.get(groupPosition).activityHolderList.size(); } @Override public Object getGroup(int groupPosition) { return projectHolderData.get(groupPosition); } @Override public Object getChild(int groupPosition, int childPosition) { return projectHolderData.get(groupPosition).activityHolderList.get(childPosition); } @Override public long getGroupId(int groupPosition) { return groupPosition; } @Override public long getChildId(int groupPosition, int childPosition) { return childPosition; } @Override public boolean hasStableIds() { return false; } @Override public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { final int groupPos = groupPosition; final boolean isExp = isExpanded; row = convertView; ParentViewHolder holder = null; if (row == null) { LayoutInflater inflater = ((Activity) context).getLayoutInflater(); row = inflater.inflate(groupLayoutResourceId, parent, false); holder = new ParentViewHolder(); holder.projectSummaryLayout = (LinearLayout) row.findViewById(R.id.projectSummaryLayout); holder.projectTitle = (TextView) row.findViewById(R.id.projectTitle); holder.expandCollapseProjectBtn = (StyledButton) row .findViewById(R.id.expandCollapseProjectBtn); row.setTag(holder); } else holder = (ParentViewHolder) row.getTag(); ProjectHolder pHolder = (ProjectHolder) getGroup(groupPosition); final Project project = pHolder.p; holder.projectTitle.setText(project.getTitle()); // hide this group if it has no participations boolean hasParticipations = false; for (ActivityHolder aHolder : pHolder.activityHolderList) { if (!aHolder.participationHolderList.isEmpty()) { hasParticipations = true; break; } } if (!hasParticipations) { holder.projectSummaryLayout.removeAllViews(); return row; } // make sure these views show or else scrolling down all the way and then scrolling up screws // them up if (isExp) holder.expandCollapseProjectBtn.setText(context.getResources().getString( R.string.fa_downchevroncircle)); else holder.expandCollapseProjectBtn.setText(context.getResources().getString( R.string.fa_rightchevroncircle)); // expand and collapse groups final ParentViewHolder holderFinal = holder; holder.expandCollapseProjectBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (isExp) { listView.collapseGroup(groupPos); holderFinal.expandCollapseProjectBtn.setText(context.getResources().getString( R.string.fa_rightchevroncircle)); } else { listView.expandGroup(groupPos); holderFinal.expandCollapseProjectBtn.setText(context.getResources().getString( R.string.fa_downchevroncircle)); } } }); return row; } @Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { row = convertView; ChildViewHolder holder = null; if (row == null) { row = inflater.inflate(childLayoutResourceId, parent, false); holder = new ChildViewHolder(); holder.activitySummaryLayout = (LinearLayout) row.findViewById(R.id.activitySummaryLayout); holder.activityTitle = (TextView) row.findViewById(R.id.activityTitle); holder.numEvents = (TextView) row.findViewById(R.id.numEvents); holder.totalParticipants = (TextView) row.findViewById(R.id.totalParticipants); holder.activityGraphLinearLayout = (LinearLayout) row .findViewById(R.id.activityGraphLinearLayout); holder.expandCollapseActivityBtn = (StyledButton) row .findViewById(R.id.expandCollapseActivityBtn); holder.isExp = true; row.setTag(holder); } else holder = (ChildViewHolder) row.getTag(); ActivityHolder aHolder = (ActivityHolder) getChild(groupPosition, childPosition); holder.activityGraphLinearLayout.removeAllViews(); // required because views are reused. final List<ParticipationHolder> participationHolderList = aHolder.participationHolderList; if (participationHolderList.isEmpty()) { holder.activitySummaryLayout.removeAllViews(); return row; // collapseChild(holder); } int sumParticipants = 0; mCurrentSeries = new XYSeries(""); final Activities a = aHolder.a; activityCal.setTimeInMillis(a.getStartDate()); mCurrentSeries.add(0, 0); activityCal.add(Calendar.DAY_OF_WEEK, 7); int weekNum = 1; // sort the participation list first because there's no guarantee participations were added // to the database in the order of their dates e.g. a quick add participation could easily // be out of order Collections.sort(aHolder.participationHolderList, new Comparator<ParticipationHolder>() { @Override public int compare(ParticipationHolder pa1, ParticipationHolder pa2) { long date1 = pa1.pa.getDate(); long date2 = pa2.pa.getDate(); if (date1 == date2) return 0; else if (date1 > date2) return 1; else return -1; } }); for (int i = 0; i < aHolder.participationHolderList.size(); ++i) { Participation participation = aHolder.participationHolderList.get(i).pa; participationCal.setTimeInMillis(participation.getDate()); if (participationCal.before(activityCal)) { sumParticipants += participation.getTotalParticipants(); if (weekNum == mCurrentSeries.getMaxX()) mCurrentSeries.remove(mCurrentSeries.getItemCount() - 1); mCurrentSeries.add(weekNum, sumParticipants); } else { // sumParticipants += participation.getTotalParticipants(); // mCurrentSeries.add(++weekNum, sumParticipants); activityCal.add(Calendar.DAY_OF_WEEK, 7); weekNum++; i--; } } holder.activityTitle.setText(a.getTitle()); holder.numEvents.setText("[" + aHolder.participationHolderList.size() + "] event(s)"); holder.totalParticipants.setText("[" + sumParticipants + "] participants"); createGraph(row, mCurrentSeries); // simulate expand collapse clicks for activities final ChildViewHolder holderFinal = holder; holder.expandCollapseActivityBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (holderFinal.isExp) { // "collapse" collapseChild(holderFinal); holderFinal.activityGraphLinearLayout.setVisibility(View.GONE); } else if (!participationHolderList.isEmpty()) { // "expand". Only if there actually are // participations expandChild(holderFinal); holderFinal.activityGraphLinearLayout.setVisibility(View.VISIBLE); } } }); return row; } private void createGraph(View view, XYSeries mCurrentSeries) { mRenderer = getMultipleSeriesRenderer(); mRenderer.addSeriesRenderer(getSeriesRenderer()); mDataset = getMultipleSeriesDataset(mCurrentSeries); mChartView = ChartFactory.getLineChartView(context, mDataset, mRenderer); LinearLayout graphView = (LinearLayout) view.findViewById(R.id.activityGraphLinearLayout); graphView.addView(mChartView); } private XYMultipleSeriesDataset getMultipleSeriesDataset(XYSeries mCurrentSeries) { mDataset = new XYMultipleSeriesDataset(); mDataset.addSeries(mCurrentSeries); return mDataset; } private XYMultipleSeriesRenderer getMultipleSeriesRenderer() { mRenderer = new XYMultipleSeriesRenderer(); mRenderer.setClickEnabled(false); mRenderer.setShowLegend(false); mRenderer.setAntialiasing(true); mRenderer.setAxisTitleTextSize(15f); mRenderer.setXLabelsColor(context.getResources().getColor(R.color.darkgrey)); mRenderer.setYLabelsColor(0, context.getResources().getColor(R.color.darkgrey)); mRenderer.setLabelsTextSize(15f); mRenderer.setXLabelsPadding(2f); mRenderer.setYLabelsPadding(10f); mRenderer.setXTitle("Weeks"); mRenderer.setYTitle("Participants"); mRenderer.setYLabels(3); mRenderer.setInScroll(true); mRenderer.setMargins(new int[] { 25, 45, 25, 25 }); mRenderer.setMarginsColor(context.getResources().getColor(R.color.white)); mRenderer.setZoomEnabled(false); mRenderer.setPanEnabled(false); return mRenderer; } private XYSeriesRenderer getSeriesRenderer() { XYSeriesRenderer renderer = new XYSeriesRenderer(); renderer.setFillPoints(false); renderer.setDisplayChartValues(false); renderer.setColor(context.getResources().getColor(R.color.darkorange)); FillOutsideLine fill = new FillOutsideLine(FillOutsideLine.Type.BOUNDS_ALL); fill.setColor(context.getResources().getColor(R.color.orange)); renderer.addFillOutsideLine(fill); return renderer; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return false; // must be true if you want child to be clickable! } private void expandChild(ChildViewHolder holder) { holder.isExp = true; holder.expandCollapseActivityBtn.setText(context.getResources().getString( R.string.fa_downchevroncircle)); } private void collapseChild(ChildViewHolder holder) { holder.isExp = false; holder.expandCollapseActivityBtn.setText(context.getResources().getString( R.string.fa_rightchevroncircle)); } private class ParentViewHolder { LinearLayout projectSummaryLayout; StyledButton expandCollapseProjectBtn; TextView projectTitle; } private class ChildViewHolder { LinearLayout activitySummaryLayout; LinearLayout activityGraphLinearLayout; boolean isExp; StyledButton expandCollapseActivityBtn; TextView activityTitle; TextView numEvents; TextView totalParticipants; } }