MealViewActivity.java
/*
* Copyright 2016 the Cook-E development team
*
* This file is part of Cook-E.
*
* Cook-E 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.
*
* Cook-E 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 Cook-E. If not, see <http://www.gnu.org/licenses/>.
*/
package org.cook_e.cook_e;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.databinding.ObservableArrayList;
import android.databinding.ObservableList;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ListView;
import org.cook_e.data.Bunch;
import org.cook_e.data.DatabaseObject;
import org.cook_e.data.Objects;
import org.cook_e.data.Recipe;
import org.cook_e.data.StorageAccessor;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class MealViewActivity extends AppCompatActivity {
@SuppressWarnings("unused")
private static final String TAG = MealViewActivity.class.getSimpleName();
/**
* The extra key used when sending a meal to display in an Intent
*/
public static final String EXTRA_MEAL = MealViewActivity.class.getName() + ".EXTRA_MEAL";
/**
* The recipes in the meal being displayed
*/
private ObservableArrayList<Recipe> mRecipes;
/**
* The meal being displayed
*/
private Bunch mMeal;
/**
* The accessor used to access storage
*/
private StorageAccessor mAccessor;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mMeal = unpackMeal();
setContentView(R.layout.activity_meal_view);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
setUpActionBar();
// Get recipes
mRecipes = new ObservableArrayList<>();
mRecipes.addAll(mMeal.getRecipes());
// Set up recipe list
final ListView recipeList = (ListView) findViewById(R.id.recipe_list);
recipeList.setAdapter(new MealRecipeListAdapter(this, mRecipes));
// Set up floating action button
final FloatingActionButton floatingButton = (FloatingActionButton) findViewById(R.id.add_button);
floatingButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// Open item add view
final Intent intent = new Intent(MealViewActivity.this, MealRecipeAddActivity.class);
try {
final List<Recipe> availableRecipes = mAccessor.loadAllRecipes();
intent.putExtra(MealRecipeAddActivity.EXIST_RECIPES,
mRecipes.toArray(new Recipe[mRecipes.size()]));
intent.putExtra(MealRecipeAddActivity.EXTRA_RECIPES,
availableRecipes.toArray(new Recipe[availableRecipes.size()]));
startActivityForResult(intent, MealRecipeAddActivity.REQUEST_ADD_RECIPES);
}
catch (Exception e) {
new AlertDialog.Builder(MealViewActivity.this)
.setTitle("Failed to load recipes")
.setMessage(e.getLocalizedMessage())
.show();
}
}
});
// Set up accessor
mAccessor = App.getAccessor();
// Save meal when recipe list changes
mRecipes.addOnListChangedCallback(new ObservableList.OnListChangedCallback() {
@Override
public void onChanged(ObservableList sender) {
updateRecipes();
}
@Override
public void onItemRangeChanged(ObservableList sender, int positionStart, int itemCount) {
updateRecipes();
}
@Override
public void onItemRangeInserted(ObservableList sender, int positionStart, int itemCount) {
updateRecipes();
}
@Override
public void onItemRangeMoved(ObservableList sender, int fromPosition, int toPosition, int itemCount) {
updateRecipes();
}
@Override
public void onItemRangeRemoved(ObservableList sender, int positionStart, int itemCount) {
updateRecipes();
}
});
}
/**
* Sets the recipes in {@link #mMeal} to {@link #mRecipes}, then saves the meal
*/
private void updateRecipes() {
saveMeal();
}
/**
* Tries to save the meal
*/
private void saveMeal() {
try {
// Save recipes that were copied from the remote database but are not saved locally
// yet
for (Recipe recipe : mRecipes) {
if (!mAccessor.containsLocalRecipe(recipe.getObjectId())) {
mAccessor.storeRecipe(recipe);
}
}
mMeal.setRecipes(mRecipes);
mAccessor.persistBunch(mMeal);
}
catch (Exception e) {
new AlertDialog.Builder(MealViewActivity.this)
.setTitle("Failed to save meal")
.setMessage(e.getLocalizedMessage())
.show();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == MealRecipeAddActivity.REQUEST_ADD_RECIPES && resultCode == RESULT_OK) {
final Parcelable[] parcelables = data.getParcelableArrayExtra(MealRecipeAddActivity.EXTRA_RECIPES);
final Recipe[] recipesToAdd = Objects.castArray(parcelables, Recipe[].class);
// Add recipes
final List<Recipe> addedRecipes = new ArrayList<>();
for (Recipe newRecipe : recipesToAdd) {
if (!mRecipes.contains(newRecipe)) {
addedRecipes.add(newRecipe);
}
}
mRecipes.addAll(addedRecipes);
}
}
private void setUpActionBar() {
final ActionBar bar = getSupportActionBar();
assert bar != null;
bar.setTitle(mMeal.getTitle());
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.meal_view, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.start:
// User chose the "schedule" item,
int amount = mMeal.getNumOfRecipes();
if (amount > 0) {
final Intent intent = new Intent(MealViewActivity.this, CookActivity.class);
intent.putExtra(CookActivity.EXTRA_BUNCH, mMeal);
startActivity(intent);
} else {
new AlertDialog.Builder(MealViewActivity.this)
.setMessage("You should have at least one recipe to start cooking.")
.show();
}
return true;
case R.id.meal_delete_item:
// Show a confirmation dialog
new AlertDialog.Builder(MealViewActivity.this)
.setTitle(R.string.question_delete_meal)
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
deleteMeal();
}
})
.setNegativeButton(android.R.string.cancel, null)
.show();
default:
// If we got here, the user's action was not recognized.
// Invoke the superclass to handle it.
return super.onOptionsItemSelected(item);
}
}
/**
* Deletes the meal, then exits
*/
private void deleteMeal() {
try {
App.getAccessor().deleteBunch(mMeal);
finish();
} catch (SQLException e) {
new AlertDialog.Builder(this)
.setTitle("Failed to delete meal")
.setMessage(e.getLocalizedMessage())
.show();
}
}
/**
* Saves the current menu
* @param outState the state to save to
*/
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// TODO
}
private Bunch unpackMeal() {
final Intent intent = getIntent();
final Bunch meal = intent.getParcelableExtra(EXTRA_MEAL);
if (meal == null) {
throw new IllegalStateException("No meal extra in intent");
}
return meal;
}
}