package edu.vanderbilt.vm.guide.ui; import java.util.LinkedList; import java.util.List; import edu.vanderbilt.vm.guide.R; import edu.vanderbilt.vm.guide.util.GuideConstants.PlaceCategories; import android.os.Bundle; import android.support.v4.app.DialogFragment; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.CheckBox; import android.widget.LinearLayout; import android.widget.TextView; /** * <p> * A dialog that presents to the user three options: * </p> * <code> * { NameSnippet, * Categories, * Distance } * </code> * <p> * as search criteria. User can choose which one is relevant and give * appropriate values, and press "Search", upon which the dialog fragment will * pass the selections to the calling Activity which implements * <code>SearchConfigReceiver</code> and promptly dissapear. The calling * Activity should update its content to reflect the user's choice based on the * information passed in <code>SearchConfig</code>. * </p> * * @author athran */ public class SearchDialog extends DialogFragment { /** * Create a new instance of SearchDialog. The caller should implement * <code>SearchConfigReceiver</code>, or have another object implement it, * so that it can receive the user's choice the finishing button is pressed. * * @param receiver * @return */ public static SearchDialog newInstance(SearchConfigReceiver receiver) { if (receiver == null) { throw new IllegalArgumentException("Must provide a receiver"); } return newInstance(receiver, null); } /** * Same as <code>newInstance(SearchConfigReceiver receiver)</code>, but with * the option to set an initial selection. Use this if there is an option * for the user to repeat and refine the search based on the previous * search. Just pass in the <code>SearchConfig</code> instance passed in * from the previous search. * * @param receiver * @param config * @return */ public static SearchDialog newInstance(SearchConfigReceiver receiver, SearchConfig config) { SearchDialog frag = new SearchDialog(); frag.mReceiver = receiver; frag.mInitialSearchConfig = config; return frag; } public interface SearchConfigReceiver { void receiveSearchConfig(SearchConfig config); } public interface SearchConfig { /** * The user might not remember exactly what the building's name is. * * @return */ String getNameSnippet(); /** * <code>PlaceCategories</code> is a enum of the set of Categories found * in the database. An empty list is equivalent to "Any". * * @return */ List<PlaceCategories> getCategories(); /** * How far from the current location should be included, in feet. * <code>Double.MAX_VALUE</code> means do not consider distance. * * @return */ Double getSearchRadius(); } // ---------- END public interface ---------- // private SearchConfig mInitialSearchConfig; private SearchConfigReceiver mReceiver; private View mRoot; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mRoot = inflater.inflate(edu.vanderbilt.vm.guide.R.layout.search_dialog, container, false); return mRoot; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); this.getDialog().setTitle("Search Criteria"); ((TextView)mRoot.findViewById(R.id.search_btn1)).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { final String snippet = ((TextView) mRoot.findViewById(R.id.search_et1)).getText().toString(); String distanceStr = ((TextView) mRoot.findViewById(R.id.search_et2)).getText().toString(); final Double distance; if (distanceStr == null || distanceStr.equals("")) { distance = Double.MAX_VALUE; } else { distance = Double.valueOf(distanceStr); } final List<PlaceCategories> list = new LinkedList<PlaceCategories>(); LinearLayout ll = (LinearLayout) mRoot.findViewById(R.id.search_category_list); CheckBox cb; for (int i = 0; i < ll.getChildCount(); i++) { cb = (CheckBox) ll.getChildAt(i); if (cb.isChecked()) { list.add(PlaceCategories.values()[i]); // I forgot how to work with enum // has it really been two years since // I last do that? } } mReceiver.receiveSearchConfig(new SearchConfig() { @Override public String getNameSnippet() { return snippet; } @Override public List<PlaceCategories> getCategories() { return list; } @Override public Double getSearchRadius() { return distance; } }); dismiss(); } }); ((TextView)mRoot.findViewById(R.id.search_btn2)).setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { ((TextView) mRoot.findViewById(R.id.search_et1)).setText(null); ((TextView) mRoot.findViewById(R.id.search_et2)).setText(null); LinearLayout ll = (LinearLayout) mRoot.findViewById(R.id.search_category_list); for (int i = 0; i < ll.getChildCount(); i++) { ((CheckBox) ll.getChildAt(i)).setChecked(false); } ll.setVisibility(View.GONE); ((TextView) mRoot.findViewById(R.id.search_tv3)).setText("Any"); } }); OnClickListener categoryListener = new OnClickListener() { @Override public void onClick(View v) { LinearLayout ll = (LinearLayout) mRoot.findViewById(R.id.search_category_list); if (ll.getVisibility() == View.GONE) { ll.setVisibility(View.VISIBLE); } else { ll.setVisibility(View.GONE); StringBuilder builder = new StringBuilder(); CheckBox cb; for (int i = 0; i < ll.getChildCount() && builder.length() < 20; i++) { cb = (CheckBox) ll.getChildAt(i); if (cb.isChecked()) { builder.append(cb.getText()); builder.append(", "); } } ((TextView) mRoot.findViewById(R.id.search_tv3)).setText(builder.toString()); } } }; mRoot.findViewById(R.id.search_tv2).setOnClickListener(categoryListener); mRoot.findViewById(R.id.search_tv3).setOnClickListener(categoryListener); } @Override public void onResume() { super.onResume(); if (mInitialSearchConfig != null) { ((TextView) mRoot.findViewById(R.id.search_et1)).setText(mInitialSearchConfig.getNameSnippet()); ((TextView) mRoot.findViewById(R.id.search_et2)).setText(Double.toString(mInitialSearchConfig.getSearchRadius())); } } }