package com.mehmetakiftutuncu.eshotroid.adapters; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Locale; import java.util.Set; import android.content.Context; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.Filter; import android.widget.SectionIndexer; import android.widget.TextView; import com.mehmetakiftutuncu.eshotroid.Main; import com.mehmetakiftutuncu.eshotroid.R; import com.mehmetakiftutuncu.eshotroid.database.MyDatabase; import com.mehmetakiftutuncu.eshotroid.model.Bus; import com.mehmetakiftutuncu.eshotroid.tasks.GetTimesPageTask; /** * Bus list adapter class is the adapter that supplies the bus list with items from an ArrayList of Bus items * * @author Mehmet Akif Tütüncü */ public class BusListAdapter extends ArrayAdapter<Bus> implements SectionIndexer { private Context myContext; private HashMap<String, Integer> myIndexer; private String[] mySections; private ArrayList<Bus> myOriginalItems; private ArrayList<Bus> myCurrentItems; /** * Tag for debugging */ public static final String LOG_TAG = "Eshotroid_BusListAdapter"; /** * Holder class for each item */ static class ViewHolder { public CheckBox favorite; public TextView number; public TextView name; } public BusListAdapter(Context context, ArrayList<Bus> items) { super(context, R.layout.busses_row, items); myContext = context; myOriginalItems = items; myCurrentItems = new ArrayList<Bus>(); myCurrentItems.addAll(myOriginalItems); updateSectionlist(); } @Override public Filter getFilter() { return new Filter() { @Override protected FilterResults performFiltering(CharSequence constraint) { FilterResults result = new FilterResults(); if(constraint != null && constraint.toString().length() > 0) { Locale trLocale = new Locale("tr"); constraint = constraint.toString().toLowerCase(trLocale); ArrayList<Bus> filteredItems = new ArrayList<Bus>(); for(int i = 0, l = myOriginalItems.size(); i < l; i++) { Bus bus = myOriginalItems.get(i); /* Custom search logic here; bus number, source, destination and route are checked for matching */ String number = String.valueOf(bus.getNumber()); String source = bus.getSource() != null ? bus.getSource() : ""; String destination = bus.getDestination() != null ? bus.getDestination() : ""; String route = bus.getRoute() != null ? bus.getRoute() : ""; if( number.contains(constraint) || source.toLowerCase(trLocale).contains(constraint) || destination.toLowerCase(trLocale).contains(constraint) || route.toLowerCase(trLocale).contains(constraint)) { filteredItems.add(bus); } } result.count = filteredItems.size(); result.values = filteredItems; } else { result.count = -1; } return result; } @SuppressWarnings("unchecked") @Override protected void publishResults(CharSequence constraint, FilterResults results) { if(results != null && results.count >= 0) { myCurrentItems = (ArrayList<Bus>) results.values; } else { myCurrentItems = myOriginalItems; } notifyDataSetInvalidated(); } }; } @Override public int getCount() { // This is important, if not checked here, the list will never know how many items it has causing crashes return myCurrentItems != null ? myCurrentItems.size() : 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { View row = convertView; if(row == null) { LayoutInflater inflater = (LayoutInflater) myContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); row = inflater.inflate(R.layout.busses_row, parent, false); ViewHolder myViewHolder = new ViewHolder(); myViewHolder.favorite = (CheckBox) row.findViewById(R.id.checkBox_busses_row); myViewHolder.number = (TextView) row.findViewById(R.id.textView_busses_row_number); myViewHolder.name = (TextView) row.findViewById(R.id.textView_busses_row_name); row.setTag(myViewHolder); } ViewHolder holder = (ViewHolder) row.getTag(); final Bus bus = myCurrentItems.get(position); holder.favorite.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { // Do stuff only if the status is changed (^ is XOR which gives true if the boolean values are not the same) if(bus.isFavorited() ^ isChecked) { if(isChecked) { Log.d(LOG_TAG, "Adding " + bus.getNumber() + " to favorited busses..."); } else { Log.d(LOG_TAG, "Removing " + bus.getNumber() + " from favorited busses..."); } bus.setFavorited(isChecked); ((Main) myContext).updateListHeader(); MyDatabase db = new MyDatabase(myContext); db.openDB(); db.addOrUpdate(bus); db.closeDB(); if(isChecked) { db.openDB(); Bus newBus = db.get(bus.getNumber()); db.closeDB(); if(newBus.getTimesH() == null) { GetTimesPageTask task = new GetTimesPageTask(myContext, newBus, "H"); task.execute(); } if(newBus.getTimesC() == null) { GetTimesPageTask task = new GetTimesPageTask(myContext, newBus, "C"); task.execute(); } if(newBus.getTimesP() == null) { GetTimesPageTask task = new GetTimesPageTask(myContext, newBus, "P"); task.execute(); } } } } }); holder.favorite.setChecked(bus.isFavorited()); holder.number.setText("" + bus.getNumber()); holder.name.setText(bus.getSource() + " - " + bus.getDestination()); return row; } /** * Updates the section list so that sections can be seen during fast scrolling */ public void updateSectionlist() { myIndexer = new HashMap<String, Integer>(); int size = myOriginalItems.size(); for(int i = 0; i < size; i++) { myIndexer.put("" + myOriginalItems.get(i).getNumber(), i); } Set<String> sectionLetters = myIndexer.keySet(); ArrayList<String> sectionList = new ArrayList<String>(sectionLetters); Collections.sort(sectionList, new Comparator<String>() { @Override public int compare(String lhs, String rhs) { if(lhs.length() < rhs.length()) { return -1; } else if(lhs.length() > rhs.length()) { return 1; } else { int l = Integer.parseInt(lhs); int r = Integer.parseInt(rhs); if(l < r) { return -1; } else if(l > r) { return 1; } else { return 0; } } } }); mySections = new String[sectionList.size()]; sectionList.toArray(mySections); } public int getPositionForSection(int section) { return myIndexer.get(mySections[section]); } public int getSectionForPosition(int position) { return 0; } public Object[] getSections() { return mySections; } }