diff --git a/app/src/main/java/unipd/se18/ocrcamera/AllergenListAdapter.java b/app/src/main/java/unipd/se18/ocrcamera/AllergenListAdapter.java new file mode 100644 index 00000000..33b9606a --- /dev/null +++ b/app/src/main/java/unipd/se18/ocrcamera/AllergenListAdapter.java @@ -0,0 +1,106 @@ +package unipd.se18.ocrcamera; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.CompoundButton; +import android.widget.TextView; +import android.widget.ToggleButton; + +import java.util.ArrayList; + +/* + * This class is used to initiate the listViews in MainAllergensActivity + * Also defined here are the instructions performed when a user selects a new allergen from the list + * @author Pietro Balzan + */ +public class AllergenListAdapter extends ArrayAdapter { + + private static final String TAG = "AllergenListAdapter"; + private Context mContext; + private int mResource; + private AllergensManager mAllergensManager; + private ArrayList selectedAllergens; + + /** + * Default constructor for an AllergensListAdapter + * @param context of the calling activity + * @param resource int of the resource layout file of the view to adapt + * @param objects an arraylist of objects to be adapted + */ + AllergenListAdapter(Context context, int resource, ArrayList objects) { + super(context, resource, objects); + mContext = context; + //in this case we will be using allergen_single.xml + mResource = resource; + //set an AllergenManager used to modify users' allergens list + mAllergensManager = InciSingleton.getInstance(context).getAllergensManager(); + selectedAllergens = mAllergensManager.getSelectedAllergensList(); + } + + /** + * this method deals with the adaptation of the single allergen view + * to the ListView of AllergensSearchFragment + * @param position of the Allergen + * @param convertView the view to be adapted + * @param parent viewGroup + * @return convertView the adapted View + */ + @NonNull + @Override + public View getView(final int position, View convertView, ViewGroup parent) { + try { + //Allergen information + final Allergen mAllergen= getItem(position); + String name = mAllergen.getCommonName(); + boolean selected = selectedAllergens.contains(mAllergen); + + //create Allergen in the layout + LayoutInflater inflater = LayoutInflater.from(mContext); + convertView = inflater.inflate(mResource, parent, false); + + //set TextView to name of the Allergen + Log.i(TAG, "Set allergen name to "+name); + TextView allergenTv = convertView.findViewById(R.id.singleAllergenTv); + allergenTv.setText(name); + + //set ToggleButton to checked or not depending on the boolean value "selected" + ToggleButton allergenToggleButton = convertView.findViewById(R.id.toggleButton); + Log.i(TAG, "Set button state to "+selected); + allergenToggleButton.setChecked(selected); + + //change allergen selection state and remove from/add to user's list if the button is clicked + allergenToggleButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + //check if it is still selected or not (user may press the button multiple times + boolean isSelected= selectedAllergens.contains(mAllergen); + //add or remove the one chosen by the user + if (isSelected){ + Log.i(TAG, "remove allergen from user's list"); + selectedAllergens.remove(mAllergen); + + //remove allergen to hide it from the view + remove(mAllergen); + notifyDataSetChanged(); + } + else { + Log.i(TAG, "add allergen to user's list"); + selectedAllergens.add(mAllergen); + } + Log.i(TAG, "Lista degli allergeni: "+selectedAllergens.toString()); + mAllergensManager.updateSelectedAllergens(selectedAllergens); + } + }); + } + catch (NullPointerException npe){ + Log.e(TAG, "Missing Parameters"); + npe.printStackTrace(); + } + return convertView; + } +} diff --git a/app/src/main/java/unipd/se18/ocrcamera/AllergensSearchFragment.java b/app/src/main/java/unipd/se18/ocrcamera/AllergensSearchFragment.java new file mode 100644 index 00000000..d3914701 --- /dev/null +++ b/app/src/main/java/unipd/se18/ocrcamera/AllergensSearchFragment.java @@ -0,0 +1,181 @@ +package unipd.se18.ocrcamera; + +import android.support.annotation.NonNull; +import android.support.v4.app.Fragment; +import android.os.Bundle; +import android.util.Log; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.AutoCompleteTextView; +import android.widget.Button; +import android.widget.ListView; + +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; + +/* + * @author Luca Moroldo + * @auhor Pietro Balzan + */ +public class AllergensSearchFragment extends Fragment { + + private final String TAG = "AllergensSearchFragment"; + private ArrayList allergensFullList; + private ListView allergensListView; + private AllergenListAdapter mAllergensListAdapter; + private Button mSearchButton; + + private AllergensManager mAllergensManager; + + private AutoCompleteTextView mAllergensAutoCompleteTextView; + //show the suggestions dropdown list with at leas 2 chars typed + private static final int SUGGESTION_THRESHOLD = 2; + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @android.support.annotation.Nullable ViewGroup container, @android.support.annotation.Nullable Bundle savedInstanceState) { + //the inflater is not considered as child of "parent" + final boolean isParent = false; + + return inflater.inflate(R.layout.fragment_allergens_search, container, false); + } + + /** + * This method is used to get the View that will make the fragment' layout in the Activity + * @param fragmentView the view that was inflated in onCreateView + * @param savedInstanceState + * @author Pietro Balzan + */ + @Override + public void onViewCreated(@NonNull View fragmentView, @android.support.annotation.Nullable Bundle savedInstanceState) { + super.onViewCreated(fragmentView, savedInstanceState); + + //Fragments Layout components + allergensListView = (ListView) fragmentView.findViewById(R.id.allergens_list_view); + mSearchButton= (Button) fragmentView.findViewById(R.id.allergens_search_button); + mAllergensAutoCompleteTextView = (AutoCompleteTextView) + fragmentView.findViewById(R.id.allergen_auto_complete_text_view); + + //initialize the manager used to manipulate the list of allergens + mAllergensManager = InciSingleton.getInstance(getActivity()).getAllergensManager(); + + //initialize the whole list of allergens + allergensFullList= mAllergensManager.getAllergensList(); + + mSearchButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + String searchedIngredient= mAllergensAutoCompleteTextView.getText().toString(); + Log.i(TAG, "The typed string is "+searchedIngredient); + //list of all allergens shown as result of the search + ArrayList searchResultList= search(searchedIngredient); + + //show list to user + mAllergensListAdapter= new AllergenListAdapter(getActivity(), + R.layout.allergen_single, searchResultList); + allergensListView.setAdapter(mAllergensListAdapter); + + //after a click hide dropdown suggestions + mAllergensAutoCompleteTextView.dismissDropDown(); + } + }); + + //setup allergens AutoCompleteTextView + new prepareAllergenAutoTextView().run(); + } + + /** + * This method returns an arraylist of allergens as a result of the search + * @param searchedIngredient a String to compare to the allergens names + * @return resultList an ArrayList + */ + private ArrayList search (String searchedIngredient) { + ArrayList resultList= new ArrayList(); + for (int i=0; i allergensList = mAllergensManager.getAllergensList(); + + //create a list of allergens names + ArrayList allergenNamesList = new ArrayList<>(); + for(Allergen allergen : allergensList) + allergenNamesList.add(allergen.getCommonName()); + + //create and set an adapter for allergen names for the autoCompleteTextView + ArrayAdapter allergenNamesAdapter = new ArrayAdapter<>( + getActivity().getApplicationContext(), + android.R.layout.simple_list_item_1, + allergenNamesList + ); + mAllergensAutoCompleteTextView.setAdapter(allergenNamesAdapter); + + //on suggestion click: update the view + mAllergensAutoCompleteTextView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + String allergenClicked = parent.getItemAtPosition(position).toString(); + + //update the textbox and set cursor at the end + mAllergensAutoCompleteTextView.setText(allergenClicked); + mAllergensAutoCompleteTextView.setSelection(allergenClicked.length()); + + //search for allergens with that name and update view + ArrayList searchResultList= search(allergenClicked); + mAllergensListAdapter= new AllergenListAdapter(getActivity(), + R.layout.allergen_single, searchResultList); + allergensListView.setAdapter(mAllergensListAdapter); + } + }); + + + + //if user press enter key then run a search + mAllergensAutoCompleteTextView.setOnKeyListener(new View.OnKeyListener() { + @Override + public boolean onKey(View v, int keyCode, KeyEvent event) { + if(KeyEvent.KEYCODE_ENTER == keyCode) { + mSearchButton.performClick(); + return true; + } + return false; + } + }); + + + //Show the allergens when the textView is clicked + mAllergensAutoCompleteTextView.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + // Perform action on click + mAllergensAutoCompleteTextView.showDropDown(); + } + }); + } + } +} diff --git a/app/src/main/java/unipd/se18/ocrcamera/BaseActivity.java b/app/src/main/java/unipd/se18/ocrcamera/BaseActivity.java new file mode 100644 index 00000000..5925331e --- /dev/null +++ b/app/src/main/java/unipd/se18/ocrcamera/BaseActivity.java @@ -0,0 +1,142 @@ +package unipd.se18.ocrcamera; + +import android.content.Intent; +import android.support.annotation.NonNull; +import android.support.design.widget.BottomNavigationView; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; + +import unipd.se18.ocrcamera.forum.Forum; + + +/** + * This class is used to define the common behavior that all activities that extend this one + * will have. They just have to define a BottomNavigationView with "bottom_navigation" as its id + * in their layout xml file; all the instructions that manage the bottom menu are defined here and + * made the same for all activities, removing the need to define a BottomNavigationView + * and the cases for every button every time, reducing as such the redundancy of the code. + * + * @author Pietro Balzan + */ +public abstract class BaseActivity extends AppCompatActivity implements BottomNavigationView.OnNavigationItemSelectedListener { + + protected BottomNavigationView navigationView; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + //set the content view as the layout of the activity that's currently active + setContentView(getContentViewId()); + + //get the BottomNavigationView from the layout that was just set + navigationView = findViewById(R.id.bottom_navigation); + navigationView.setOnNavigationItemSelectedListener(this); + } + + @Override + protected void onStart(){ + super.onStart(); + + //set the bottombaar menu correctly + updateNavigationBarState(); + } + + @Override + public boolean onNavigationItemSelected(@NonNull final MenuItem item) { + navigationView.post(new Runnable() { + @Override + public void run() { + Intent intent; + int itemId= item.getItemId(); + if (itemId == R.id.nav_result){ + intent= new Intent(BaseActivity.this, ResultActivity.class); + + /* + * this flag will cause the launched activity to be brought + * to the front of this task's history stack if it is already running + */ + intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); + + /* + * launch the activity only if a new actiity instance is needed + * to handle the given intent + */ + startActivityIfNeeded(intent, 0); + } + else if (itemId == R.id.nav_allergens){ + intent= new Intent(BaseActivity.this, MainAllergensActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); + startActivityIfNeeded(intent, 0); + } + else if (itemId == R.id.nav_picture){ + intent= new Intent(BaseActivity.this, CameraActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); + startActivityIfNeeded(intent, 0); + } + else if (itemId == R.id.nav_gallery){ + intent= new Intent(BaseActivity.this, GalleryActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); + startActivityIfNeeded(intent, 0); + } + else if (itemId == R.id.nav_forum){ + intent= new Intent(BaseActivity.this, Forum.class); + intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); + startActivityIfNeeded(intent, 0); + } + } + }); + + return false; + } + + /** + * This method is used to update the visuals of the BottomBar to show which item + * of the menu is selected + * + * @author Pietro Balzan + */ + private void updateNavigationBarState() { + int actionId = getNavigationMenuItemId(); + selectBottomNavigationBarItem(actionId); + } + + /** + * This method sets the correct item of the menu as selected depending on + * which actuvity we are in + * @param itemId the id int of the menu item to be set as selected + * + * @author Pietro Balzan + */ + void selectBottomNavigationBarItem(int itemId) { + Menu menu = navigationView.getMenu(); + for (int i=0, size = menu.size(); i upperBound){ // image is too bright + Log.d(TAG, "too bright image"); + result = 1; + } + else if (average < lowerBound){ //image is too dark + Log.d(TAG, "too dark image"); + result = -1; + } + else { + Log.d(TAG, "good image"); // image is neither too bright nor too dark + } + return result; + } +} \ No newline at end of file diff --git a/app/src/main/java/unipd/se18/ocrcamera/MainAllergensActivity.java b/app/src/main/java/unipd/se18/ocrcamera/MainAllergensActivity.java new file mode 100644 index 00000000..7877d2ec --- /dev/null +++ b/app/src/main/java/unipd/se18/ocrcamera/MainAllergensActivity.java @@ -0,0 +1,123 @@ +package unipd.se18.ocrcamera; + +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.design.widget.BottomNavigationView; +import android.support.design.widget.TabLayout; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; +import android.support.v4.view.ViewPager; +import android.support.v7.app.AppCompatActivity; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; + +import java.util.ArrayList; +import java.util.List; + +import unipd.se18.ocrcamera.forum.Forum; + +/* + * @author Pietro Balzan + */ +public class MainAllergensActivity extends BaseActivity { + + private static final String TAG= "MainAllergensActivity"; + private ViewPager mViewPager; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Log.i(TAG, "Starting construction of the layout"); + + //set up the ViewPager with the sections adapter + mViewPager = findViewById(R.id.container); + setupViewPager(mViewPager); + + //initialize the Tab Layout's content + TabLayout tabLayout = findViewById(R.id.tabs); + tabLayout.setupWithViewPager(mViewPager); + + } + + /** + * This method is used to set the viewPager up with the fragments and the layout elements + * @param viewPager the viewPager to be set up + * @author Pietro Balzan + */ + private void setupViewPager(ViewPager viewPager) { + SectionsPageAdapter mSectionsPageAdapter = new SectionsPageAdapter(getSupportFragmentManager()); + //get tab names to be shown in the activity + String searchFragmentName= getString(R.string.allergens_search_fragment); + String userFragmentName = getString(R.string.allergens_user_fragment); + + //add the two fragments + Log.i(TAG, "Set up adapter"); + mSectionsPageAdapter.addFragment(new AllergensSearchFragment() ,searchFragmentName); + mSectionsPageAdapter.addFragment(new UserAllergensFragment() ,userFragmentName); + viewPager.setAdapter(mSectionsPageAdapter); + } + + + /** + * this class is used to manage and add fragents to the activity + * @author Pietro Balzan + */ + private class SectionsPageAdapter extends FragmentPagerAdapter { + + private final List mFragmentList = new ArrayList<>(); + private final List mFragmentTitleList = new ArrayList<>(); + + //default constructor of FragmentPageAdapter + public SectionsPageAdapter(FragmentManager fm) { + super(fm); + } + + /** + * This method is used to add fragments to the list to be used in the layout of the Activity + * @param fragment to be added to the list + * @param title of the fragment to be shown in the activity + */ + public void addFragment(Fragment fragment, String title){ + mFragmentList.add(fragment); + mFragmentTitleList.add(title); + } + + //getter methods + + @Override + public CharSequence getPageTitle(int position){ + return mFragmentTitleList.get(position); + } + + @Override + public Fragment getItem(int position) { + return mFragmentList.get(position); + } + + @Override + public int getCount() { + return mFragmentList.size(); + } + + } + + /* + * override BaseActivity's abstract methods to give information + * about the layout and menu item that should be selected + */ + + @Override + int getContentViewId(){ + return R.layout.activity_allergens_main; + } + + @Override + int getNavigationMenuItemId(){ + return R.id.nav_allergens; + } + +} diff --git a/app/src/main/java/unipd/se18/ocrcamera/UserAllergensFragment.java b/app/src/main/java/unipd/se18/ocrcamera/UserAllergensFragment.java new file mode 100644 index 00000000..b310eda1 --- /dev/null +++ b/app/src/main/java/unipd/se18/ocrcamera/UserAllergensFragment.java @@ -0,0 +1,70 @@ +package unipd.se18.ocrcamera; + +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ListView; + +import java.util.ArrayList; + +/* + * @author Pietro Balzan + */ +public class UserAllergensFragment extends Fragment { + private static final String TAG = "UserAllergensFragment"; + private ListView mAllergensListView; + private AllergensManager mAllergensManager; + private AllergenListAdapter mAllergensListAdapter; + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + //the inflater is not considered as child of "parent" + final boolean isParent = false; + + return inflater.inflate(R.layout.fragment_users_allergens, container, isParent); + } + + /** + * This method is used to get the View that will make the fragment' layout in the Activity + * @param fragmentView the view that was inflated in onCreateView + * @param savedInstanceState + * @return fragmentView + * @author Pietro Balzan + */ + @Override + public void onViewCreated(@NonNull View fragmentView, @Nullable Bundle savedInstanceState) { + super.onViewCreated(fragmentView, savedInstanceState); + mAllergensListView = (ListView) fragmentView.findViewById(R.id.users_allergens_list_view); + + mAllergensManager = InciSingleton.getInstance(getActivity()).getAllergensManager(); + //initialize the user's own list + ArrayList userList= mAllergensManager.getSelectedAllergensList(); + //create mAllergensListAdapter with the list of the users' allergens + mAllergensListAdapter= new AllergenListAdapter(getActivity(), R.layout.allergen_single, userList); + mAllergensListView.setAdapter(mAllergensListAdapter); + } + + /** + * When the user focus the fragment, update mAllergensListView to show any change + * @param isVisibleToUser + * @author Luca Moroldo g3 + */ + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); + if(isVisibleToUser) { + mAllergensListAdapter.clear(); + + ArrayList userAllergensList = mAllergensManager.getSelectedAllergensList(); + mAllergensListAdapter = new AllergenListAdapter(getActivity(), R.layout.allergen_single, userAllergensList); + mAllergensListView.setAdapter(mAllergensListAdapter); + } + } +}