com.physphil.android.restaurantroulette.RestaurantSelectorFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.physphil.android.restaurantroulette.RestaurantSelectorFragment.java

Source

/**
 * Restaurant Roulette for Android
 * Copyright (C) 2014  Phil Shadlyn
 *
 * Restaurant Roulette is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @copyright 2014 Phil Shadlyn - physphil@gmail.com
 * @license GNU General Public License - https://www.gnu.org/licenses/gpl.html
 */

package com.physphil.android.restaurantroulette;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.graphics.Typeface;
import android.location.Location;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
import android.support.v4.content.LocalBroadcastManager;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.RatingBar;
import android.widget.RelativeLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.physphil.android.restaurantroulette.data.DatabaseHelper;
import com.physphil.android.restaurantroulette.models.Restaurant;
import com.physphil.android.restaurantroulette.models.RestaurantHistory;
import com.physphil.android.restaurantroulette.ui.CustomFontArrayAdapter;
import com.physphil.android.restaurantroulette.util.Constants;
import com.physphil.android.restaurantroulette.util.LocationHelper;
import com.physphil.android.restaurantroulette.util.Util;

import java.text.DateFormat;
import java.util.Date;
import java.util.List;

/**
 * Created by pshadlyn on 2/27/14.
 */
public class RestaurantSelectorFragment extends Fragment {

    public static String PREFS_GENRE_FILTER_SELECTOR = "genre_filter_selector";
    public static String PREFS_SHOW_HELP_RESTAURANT_SELECTOR = "show_help_selector";

    private Restaurant mRestaurant;
    private List<RestaurantHistory> mHistory;
    private DatabaseHelper mDatabaseHelper;
    private LocationHelper mLocationHelper;
    private Spinner spinnerGenre;
    private RelativeLayout rlAnswer;
    private RelativeLayout rlNumberVisits;
    private RelativeLayout rlLastVisit;
    private Button btnSelectRestaurant;
    private Button btnGetDirections;
    private TextView tvHeader;
    private TextView tvAnswer;
    private RatingBar rbRating;
    private RatingBar rbPrice;
    private TextView tvLastVisit;
    private TextView tvNumberOfVisits;
    private int mFilter;
    private SharedPreferences prefs;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        LocalBroadcastManager.getInstance(getActivity()).registerReceiver(mLifetimeReceiver,
                new IntentFilter(RestaurantFragment.ACTION_RESTAURANT_UPDATED));
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_restaurant_selector, container, false);

        rlAnswer = (RelativeLayout) v.findViewById(R.id.restaurant_answer_layout);
        rlLastVisit = (RelativeLayout) v.findViewById(R.id.answer_summary_last_visit_layout);
        rlNumberVisits = (RelativeLayout) v.findViewById(R.id.answer_summary_number_visits_layout);
        btnSelectRestaurant = (Button) v.findViewById(R.id.btn_select_restaurant);
        btnGetDirections = (Button) v.findViewById(R.id.btn_get_directions);
        spinnerGenre = (Spinner) v.findViewById(R.id.spinner_restaurant_genre);
        tvHeader = (TextView) v.findViewById(R.id.restaurant_selector_header);
        tvAnswer = (TextView) v.findViewById(R.id.restaurant_selector_answer);
        rbRating = (RatingBar) v.findViewById(R.id.answer_summary_rating_bar);
        rbPrice = (RatingBar) v.findViewById(R.id.answer_summary_price_bar);
        tvLastVisit = (TextView) v.findViewById(R.id.answer_summary_last_visit);
        tvNumberOfVisits = (TextView) v.findViewById(R.id.answer_summary_number_visits);

        setFonts(v);

        return v;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        setRetainInstance(true);
        setHasOptionsMenu(true);

        prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
        mDatabaseHelper = DatabaseHelper.getInstance(getActivity());
        mLocationHelper = new LocationHelper(getActivity());
        mFilter = prefs.getInt(PREFS_GENRE_FILTER_SELECTOR, Restaurant.GENRE_ALL);

        initViewContent();

        // Set answer through fragment objects mRestaurant and mHistory. Don't save to history as no new selection was made
        setAnswer(false);
    }

    @Override
    public void onResume() {
        super.onResume();

        LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(getActivity());
        lbm.registerReceiver(mVisibleReceiver, new IntentFilter(HistoryListFragment.ACTION_HISTORY_CLEARED));
        lbm.registerReceiver(mVisibleReceiver, new IntentFilter(LocationHelper.ACTION_LOCATION_RETRIEVED));
        lbm.registerReceiver(mVisibleReceiver, new IntentFilter(NavigationDrawerFragment.ACTION_DRAWER_CLOSED));
    }

    @Override
    public void onPause() {
        super.onPause();

        LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(mVisibleReceiver);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(mLifetimeReceiver);
    }

    private void initViewContent() {

        btnSelectRestaurant.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

                selectRestaurant();
            }
        });

        btnGetDirections.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

                //                Util.showOnMap(getActivity(), mRestaurant.getName());
                mLocationHelper.connectAndGetLocation();
            }
        });

        List<String> genres = Restaurant.getGenresForAdapter(getActivity());

        // Override adapter to set font
        spinnerGenre.setAdapter(
                new CustomFontArrayAdapter(getActivity(), android.R.layout.simple_spinner_dropdown_item, genres));
        spinnerGenre.setSelection(prefs.getInt(PREFS_GENRE_FILTER_SELECTOR, Restaurant.GENRE_ALL), false); // use false for animate to not trigger listener when setting initial selection. Weird, but works.
        spinnerGenre.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {

            @Override
            public void onItemSelected(AdapterView<?> spinner, View view, int position, long id) {

                mFilter = position;
                prefs.edit().putInt(PREFS_GENRE_FILTER_SELECTOR, position).commit();
                clearAnswer();
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });

        rlAnswer.setOnClickListener(new View.OnClickListener() {

            // Open restaurant detail view when touched
            @Override
            public void onClick(View v) {

                Intent i = RestaurantActivity.getLaunchingIntent(getActivity(), mRestaurant.getRestaurantId());
                startActivity(i);
            }
        });
    }

    /**
     * Set fonts for all text views in layout
     * @param v parent view containing all views which need font to be set
     */
    private void setFonts(View v) {

        Typeface tf = Typeface.createFromAsset(getActivity().getAssets(), Constants.FONT_DEFAULT);
        btnSelectRestaurant.setTypeface(tf);
        btnGetDirections.setTypeface(tf);
        tvHeader.setTypeface(tf);
        tvAnswer.setTypeface(tf);
        tvLastVisit.setTypeface(tf);
        tvNumberOfVisits.setTypeface(tf);

        // change font of static text
        ((TextView) v.findViewById(R.id.selector_filter_text)).setTypeface(tf);
        ((TextView) v.findViewById(R.id.restaurant_genre_text)).setTypeface(tf);
        ((TextView) v.findViewById(R.id.answer_summary_last_visit_text)).setTypeface(tf);
        ((TextView) v.findViewById(R.id.answer_summary_number_visits_text)).setTypeface(tf);
        ((TextView) v.findViewById(R.id.answer_summary_rating_text)).setTypeface(tf);
        ((TextView) v.findViewById(R.id.answer_summary_price_text)).setTypeface(tf);
    }

    private void selectRestaurant() {

        // Get list of restaurants to choose from based on filter
        List<Restaurant> restaurants;

        if (mFilter == Restaurant.GENRE_ALL) {

            restaurants = mDatabaseHelper.getAllRestaurants();
        } else {

            String genre = Restaurant.getGenresForAdapter(getActivity()).get(mFilter);
            restaurants = mDatabaseHelper.getRestaurantsByGenre(genre);
        }

        // Pick one at random and record history
        if (restaurants.size() > 0) {
            int randomIndex = (int) (Math.floor(Math.random() * restaurants.size()));
            mRestaurant = restaurants.get(randomIndex);
            mHistory = mDatabaseHelper.getHistoryByRestaurant(mRestaurant.getRestaurantId());
            setAnswer(true);
        } else {

            Toast.makeText(getActivity(), R.string.toast_no_restaurants_found, Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * Use values of mRestaurant and mHistory to set answer.  If objects are null then answer fields are hidden
     * @param addToHistory whether to add this selection to selection history
     */
    private void setAnswer(boolean addToHistory) {

        if (mRestaurant != null) {

            rlAnswer.setVisibility(View.VISIBLE);
            btnSelectRestaurant.setText(R.string.restaurant_selector_button_pick_another);
            tvAnswer.setText(mRestaurant.getName());
            rbRating.setRating(mRestaurant.getUserRating());
            rbPrice.setRating(mRestaurant.getPriceLevel());

            // Only show Get Directions button if restaurant has a valid name to search for
            if (mRestaurant.hasName()) {
                btnGetDirections.setVisibility(View.VISIBLE);
            } else {
                btnGetDirections.setVisibility(View.GONE);
            }

            if (mHistory.size() > 0) {

                // set summary fields
                setSummaryFieldsVisibility(true);
                tvNumberOfVisits.setText(Integer.toString(mHistory.size()));

                // Objects returned from db sorted by date. Entry 0 is the most recent
                Date recentVisit = mHistory.get(0).getDate();
                DateFormat df = DateFormat.getDateInstance();
                tvLastVisit.setText(df.format(recentVisit));
            } else {

                // Hide summary fields
                setSummaryFieldsVisibility(false);
            }

            // Add selection to history
            if (addToHistory) {
                mDatabaseHelper.addRestaurantHistory(mRestaurant.getRestaurantId());
            }
        } else {

            // No answer
            rlAnswer.setVisibility(View.INVISIBLE);
            btnGetDirections.setVisibility(View.GONE);
            btnSelectRestaurant.setText(R.string.restaurant_selector_button);
        }
    }

    /**
     * Set visibility of summary fields.  If there is no history then they need to be hidden
     * @param isVisible If the fields should be visible or not
     */
    private void setSummaryFieldsVisibility(boolean isVisible) {

        if (isVisible) {
            rlNumberVisits.setVisibility(View.VISIBLE);
            rlLastVisit.setVisibility(View.VISIBLE);
            //            rlRating.setVisibility(View.VISIBLE);
        } else {
            rlNumberVisits.setVisibility(View.GONE);
            rlLastVisit.setVisibility(View.GONE);
            //            rlRating.setVisibility(View.GONE);
        }
    }

    /**
     * Reset restaurant selection
     */
    private void clearAnswer() {

        mRestaurant = null;
        mHistory = null;
        setAnswer(false);
    }

    private void showHelpDialog() {

        Util.showHelpDialog(getActivity(), R.string.title_restaurant_selector,
                R.string.dialog_restaurant_selector_help, PREFS_SHOW_HELP_RESTAURANT_SELECTOR);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId()) {

        case R.id.menu_help:
            showHelpDialog();
            return true;

        default:
            return super.onOptionsItemSelected(item);
        }
    }

    /**
     * Broadcast receiver to be active only while the fragment is visible
     */
    private BroadcastReceiver mVisibleReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {

            if (intent.getAction().equals(HistoryListFragment.ACTION_HISTORY_CLEARED)) {

                // Clear answer if restaurant history has been erased
                clearAnswer();
            } else if (intent.getAction().equals(LocationHelper.ACTION_LOCATION_RETRIEVED)) {

                Location location = intent.getParcelableExtra(LocationHelper.EXTRA_LOCATION);
                Util.showOnMap(getActivity(), mRestaurant.getName(), location);
                mLocationHelper.disconnect();
            } else if (intent.getAction().equals(NavigationDrawerFragment.ACTION_DRAWER_CLOSED)) {

                // Show help menu if never been shown
                boolean showHelp = prefs.getBoolean(PREFS_SHOW_HELP_RESTAURANT_SELECTOR, true);
                if (showHelp) {

                    showHelpDialog();
                }
            }
        }
    };

    /**
     * Broadcast Receiver to be active for the lifetime of the fragment
     */
    private BroadcastReceiver mLifetimeReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {

            if (intent.getAction().equals(RestaurantFragment.ACTION_RESTAURANT_UPDATED)) {

                // TODO - replace with don't update if returned broadcast indicates a new entry
                // Update restaurant info from db, update fields in answer card
                if (mRestaurant != null) {
                    String id = mRestaurant.getRestaurantId();
                    mRestaurant = mDatabaseHelper.getRestaurantById(id);
                    setAnswer(false);
                }
            }
        }
    };

}