ics4u.ics4u_final_project.RecipeCreateActivity.java Source code

Java tutorial

Introduction

Here is the source code for ics4u.ics4u_final_project.RecipeCreateActivity.java

Source

/*
This is the class for the activity that allows the user to make a new or edit an existing recipe
 */
/*
Copyright (C) 2016 Isaac Wismer & Andrew Xu
    
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero 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 Affero General Public License for more details.
    
You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package ics4u.ics4u_final_project;

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

public class RecipeCreateActivity extends AppCompatActivity {
    static Recipe recipe;
    static boolean addedIngred;
    static boolean onRecipe, search;
    static RecyclerView rView;
    ImageView iconContextMenu;
    EditText quanAmt, quanNm;
    int index = -1;
    RecipeCreateAdapter rcAdapter;
    Stack<Ingredient> deleted = new Stack<>();
    private Toolbar mToolbar;
    private LinearLayoutManager lLayoutIngredient;

    /**
     * Runs when the activity first loads or whenever it reloads from scratch
     *
     * @param savedInstanceState
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //Update variable stating user is on recipe creating activity
        onRecipe = true;
        //Links .java file with the corresponding xml file
        setContentView(R.layout.rv_recipecreate);
        //Create toolbar with corresponding values
        mToolbar = (Toolbar) findViewById(R.id.toolbar);
        mToolbar.setTitle("Create A Recipe");
        setSupportActionBar(mToolbar);
        //Update variable stating user isn't adding ingredients yet
        addedIngred = false;
        //Find reference location of button
        final Button button = (Button) findViewById(R.id.instructions_button);
        //checks for button click event
        button.setOnClickListener(
                //Launch instruction creator activity
                new Button.OnClickListener() {
                    public void onClick(View v) {
                        launchInstructions();
                    }
                });
        //FLOATING BUTTON
        FloatingActionButton FAB = (FloatingActionButton) findViewById(R.id.add_ingredient_button);
        //Checks for click event of the floating button
        FAB.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                search = true;
                launchIngredients();
            }
        });
        //list for the cards
        final List<Ingredient> rowListItem;
        //Find reference locations of combo boxes
        quanAmt = (EditText) findViewById(R.id.quantity_amount);
        quanNm = (EditText) findViewById(R.id.quantity_type);
        if (RecyclerViewHolders.edit) {
            index = RecyclerViewHolders.location;
            //get the recipe that was clicked on
            recipe = MainActivity.importedRecipes.get(index);
            //set each of the elements to the specified ones in the recipe
            TextView name = (TextView) findViewById(R.id.recipe_name);
            name.setText(recipe.getTitle());
            ImageView recipeIcon = (ImageView) findViewById(R.id.recipe_icon);
            recipeIcon.setImageDrawable(getResources().getDrawable(recipe.getPhoto()));
            if (recipe.getIngredients().size() > 0) {
                addedIngred = true;
            }
            quanAmt.setText(String.valueOf(recipe.getServings()));
            quanNm.setText(recipe.getServingName());
            rcAdapter = new RecipeCreateAdapter(RecipeCreateActivity.this, recipe.getIngredients());
        } else {
            //create a new recipe
            recipe = new Recipe();
            //set a default photo
            recipe.setPhoto(R.drawable.banana);
            rowListItem = getAllItemList();
            rcAdapter = new RecipeCreateAdapter(RecipeCreateActivity.this, rowListItem);

        }
        //LLM for recycler view container
        lLayoutIngredient = new LinearLayoutManager(RecipeCreateActivity.this);
        //Find reference location of the Rview
        rView = (RecyclerView) findViewById(R.id.recycler_view_recipe);
        //Populate container with data inserted into the adapter
        rView.setLayoutManager(lLayoutIngredient);
        rView.setAdapter(rcAdapter);
        //Checks to see if user clicked the icon
        clickingIcon();
        //Listener to see when user swipes one of the cards
        SwipeableRecyclerViewTouchListener swipeTouchListener = new SwipeableRecyclerViewTouchListener(rView,
                new SwipeableRecyclerViewTouchListener.SwipeListener() {
                    /**
                     * Allows cards to be swipeable
                     * @param position
                     * @return
                     */
                    @Override
                    public boolean canSwipe(int position) {
                        return true;
                    }

                    //When user swipes left to dismiss cards
                    @Override
                    public void onDismissedBySwipeLeft(RecyclerView recyclerView, int[] reverseSortedPositions) {
                        for (int position : reverseSortedPositions) {
                            //move deleted ingredient to a temporary array
                            //Delete ingredient from screen
                            if (recipe.getIngredients().size() > 0) {
                                deleted.push(recipe.getIngredients().get(position));
                                recipe.getIngredients().remove(position);
                                rcAdapter.notifyItemRemoved(position);
                            }
                        }
                        rcAdapter.notifyDataSetChanged();
                    }

                    //when user swipes right to dismiss cards
                    @Override
                    public void onDismissedBySwipeRight(RecyclerView recyclerView, int[] reverseSortedPositions) {
                        for (int position : reverseSortedPositions) {
                            //move deleted ingredient to a temporary array
                            //Delete ingredient from screen
                            if (recipe.getIngredients().size() > 0) {
                                deleted.push(recipe.getIngredients().get(position));
                                recipe.getIngredients().remove(position);
                                rcAdapter.notifyItemRemoved(position);
                            }
                        }
                        rcAdapter.notifyDataSetChanged();
                    }
                });

        rView.addOnItemTouchListener(swipeTouchListener);
    }

    /**
     * creates a default card in the list to promt the user
     *
     * @return the list with the default card
     */
    private List<Ingredient> getAllItemList() {
        //add a default ingredient
        List<Ingredient> allItems = new ArrayList<>();
        allItems.add(new Ingredient(-1, "Add Ingredients"));
        allItems.get(0).setFormattedName("Add Ingredients using the floating button.");
        return allItems;
    }

    /**
     * launches the instructions activity
     */
    public void launchInstructions() {
        Intent intent = new Intent(this, InstructionCreator.class);
        startActivity(intent);
    }

    /**
     * launches the ingredient selection activity
     */
    public void launchIngredients() {
        Intent intent = new Intent(this, IngredientSelectionActivity.class);
        startActivity(intent);
    }

    //    public static void updateAdapter(){
    //        RecipeCreateAdapter rcAdapter = new RecipeCreateAdapter(this.getApplicationContext(), recipe.getIngredients());
    //        rView.setAdapter(rcAdapter);
    //    }

    /**
     * Instantiates menu and populates it with corresponding items
     *
     * @param menu
     * @return
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_recipe, menu);
        return true;
    }

    /**
     * When user clicks an item on the menu
     *
     * @param item
     * @return
     */
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        //When user clicks print
        if (id == R.id.action_print) {
            //save the recipe
            saveRecipe();
            File pdfFolder = new File("/sdcard/Recipes/");

            int permissionCheck = ContextCompat.checkSelfPermission(this,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE);
            if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
                if (!pdfFolder.isDirectory()) {
                    pdfFolder.mkdir();
                }
                //export to PDF
                recipe.export(new File("/sdcard/Recipes/", recipe.getTitle() + ".pdf"));
                //open the PDF
                Intent i = new Intent(Intent.ACTION_VIEW);
                System.out.println(getFilesDir().toString());
                i.setDataAndType(Uri.fromFile(new File("/sdcard/Recipes/" + recipe.getTitle() + ".pdf")),
                        "application/pdf");
                startActivity(i);
            } else {
                Toast.makeText(this, "Permission denied. Please grant storage permissions", Toast.LENGTH_LONG)
                        .show();
            }
            //When user clicks undo
        } else if (id == R.id.action_undo) {
            //they haven't deleted anything
            if (deleted.isEmpty()) {
                Toast.makeText(this, "No ingredients to restore", Toast.LENGTH_LONG).show();
            } else {
                recipe.getIngredients().add(deleted.pop());
                RecipeCreateAdapter rcAdapter = new RecipeCreateAdapter(RecipeCreateActivity.this,
                        recipe.getIngredients());
                rView.setAdapter(rcAdapter);
                //save the recipe
                saveRecipe();
                Toast.makeText(this, "Last deleted ingredient restored", Toast.LENGTH_LONG).show();
            }
        }

        return super.onOptionsItemSelected(item);

    }

    /**
     * Creates context menu to allow user to choose icon
     * Context menus are the pop up menus
     *
     * @param menu
     * @param v
     * @param menuInfo
     */
    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        //Inflate menu with values in corresponding menu xml file
        MenuInflater inflater = getMenuInflater();
        //Set header
        menu.setHeaderTitle("Change recipe icon");
        inflater.inflate(R.menu.menu_icon, menu);
    }

    /**
     * Called when an item on the photo menu is selected
     *
     * @param item
     * @return
     */
    @Override
    public boolean onContextItemSelected(MenuItem item) {
        super.onContextItemSelected(item);
        //Checks to see which photo was selected and update the photo
        switch (item.getItemId()) {
        case R.id.icon1:
            iconContextMenu.setImageResource(R.drawable.banana);
            recipe.setPhoto(R.drawable.banana);
            return true;
        case R.id.icon2:
            iconContextMenu.setImageResource(R.drawable.fish);
            recipe.setPhoto(R.drawable.fish);
            return true;
        case R.id.icon3:
            iconContextMenu.setImageResource(R.drawable.cake);
            recipe.setPhoto(R.drawable.cake);
            return true;
        case R.id.icon4:
            iconContextMenu.setImageResource(R.drawable.cookies);
            recipe.setPhoto(R.drawable.cookies);
            return true;
        case R.id.icon5:
            iconContextMenu.setImageResource(R.drawable.dairy);
            recipe.setPhoto(R.drawable.dairy);
            return true;
        case R.id.icon6:
            iconContextMenu.setImageResource(R.drawable.muffin);
            recipe.setPhoto(R.drawable.muffin);
            return true;
        case R.id.icon7:
            iconContextMenu.setImageResource(R.drawable.sandwich);
            recipe.setPhoto(R.drawable.sandwich);
            return true;
        case R.id.icon8:
            iconContextMenu.setImageResource(R.drawable.soup);
            recipe.setPhoto(R.drawable.soup);
            return true;
        case R.id.icon9:
            iconContextMenu.setImageResource(R.drawable.wheat);
            recipe.setPhoto(R.drawable.wheat);
            return true;
        default:
            return false;
        }
    }

    /**
     * Checks to see user clicks the recipe icon
     */
    public void clickingIcon() {
        //find the reference location
        iconContextMenu = (ImageView) findViewById(R.id.recipe_icon);
        //Checks for click event, and open the context menu
        iconContextMenu.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                registerForContextMenu(iconContextMenu);
                return false;
            }
        });
    }

    /**
     * Method runs every time the user returns to this activity that is already open
     * refreshes the ingredients and saves the recipe
     */
    @Override
    protected void onRestart() {
        //update the ingredients
        super.onRestart();
        RecipeCreateAdapter rcAdapter = new RecipeCreateAdapter(RecipeCreateActivity.this, recipe.getIngredients());
        rView.setAdapter(rcAdapter);
        //save the recipe
        saveRecipe();
        //Update variable stating user is on the recipe create activity
        onRecipe = true;
    }

    /**
     * deletes all the save files and saves the recies currently in memory
     */
    public void saveRecipe() {
        //get the name of the recipe
        EditText nameBox = (EditText) findViewById(R.id.recipe_name);
        recipe.setTitle(nameBox.getText().toString());
        recipe.setServings(Integer.parseInt(quanAmt.getText().toString()));
        recipe.setServingName(quanNm.getText().toString());
        //save the recipe to the correct spot on the imported recipes
        if (index >= 0) {
            MainActivity.importedRecipes.set(index, recipe);
        } else {
            //add it as a new recipe if it's new, and set the edit to the correct ingredient
            MainActivity.importedRecipes.add(recipe);
            index = MainActivity.importedRecipes.size() - 1;
            //            //save it
            //            try {
            //                recipe.save(new File(getFilesDir() + "/recipes/" + recipe.getTitle() + ".xml"));
            //            } catch (FileNotFoundException e) {
            //                e.printStackTrace();
            //            }
        }
        //rebuild saves
        //rebuild imported recipes
        // TODO: 1/18/2016 find a way to link this with the duplicate method in the main activity
        File recipeFolder = new File(this.getFilesDir() + "/recipes/");
        File[] listOfFiles = recipeFolder.listFiles();
        //delete all the files in the folder
        for (File file : listOfFiles) {
            System.out.println(file.delete());
        }
        //resave all the recipes that are in memory
        for (int i = 0; i < MainActivity.importedRecipes.size(); i++) {
            try {
                MainActivity.importedRecipes.get(i).save(new File(this.getFilesDir() + "/recipes/" + i + ".xml"));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * called when the back button is pressed on a recipe
     */
    @Override
    public void onBackPressed() {
        super.onBackPressed();
        //refresh the saves
        saveRecipe();
    }

}