From d8bf4e02f863d2ce50d963f72632fcf56d1d23b5 Mon Sep 17 00:00:00 2001 From: Clayton Wilson Date: Mon, 26 Oct 2020 00:25:47 -0400 Subject: [PATCH 01/12] Add menu to search and rename SortDialogFragment to FilterDialogFragment --- ...ragment.java => FilterDialogFragment.java} | 18 +++++----- .../com/example/listify/SearchResults.java | 34 ++++++++++++++----- .../res/layout/activity_search_results.xml | 14 ++++---- .../{dialog_sort.xml => dialog_filter.xml} | 0 Listify/app/src/main/res/menu/search.xml | 14 ++++++++ 5 files changed, 55 insertions(+), 25 deletions(-) rename Listify/app/src/main/java/com/example/listify/{SortDialogFragment.java => FilterDialogFragment.java} (89%) rename Listify/app/src/main/res/layout/{dialog_sort.xml => dialog_filter.xml} (100%) create mode 100644 Listify/app/src/main/res/menu/search.xml diff --git a/Listify/app/src/main/java/com/example/listify/SortDialogFragment.java b/Listify/app/src/main/java/com/example/listify/FilterDialogFragment.java similarity index 89% rename from Listify/app/src/main/java/com/example/listify/SortDialogFragment.java rename to Listify/app/src/main/java/com/example/listify/FilterDialogFragment.java index 7cc71a4..f61ea60 100644 --- a/Listify/app/src/main/java/com/example/listify/SortDialogFragment.java +++ b/Listify/app/src/main/java/com/example/listify/FilterDialogFragment.java @@ -22,13 +22,13 @@ import com.crystal.crystalrangeseekbar.widgets.CrystalRangeSeekbar; import java.util.ArrayList; -public class SortDialogFragment extends DialogFragment { +public class FilterDialogFragment extends DialogFragment { - public interface OnSortingListener { + public interface OnFilterListener { void sendSort(int storeSelection, int sortMode, boolean descending, double minPrice, double maxPrice); } - public OnSortingListener onSortingListener; + public OnFilterListener onFilterListener; CrystalRangeSeekbar priceSeekbar; @@ -40,7 +40,7 @@ public class SortDialogFragment extends DialogFragment { private double minPrice; // The selected min price private double maxPrice; // The selected max price - public SortDialogFragment(int storeSelection, ArrayList stores, int sortMode, boolean descending, double maxProductPrice, double minPrice, double maxPrice) { + public FilterDialogFragment(int storeSelection, ArrayList stores, int sortMode, boolean descending, double maxProductPrice, double minPrice, double maxPrice) { this.storeSelection = storeSelection; this.stores = stores; this.sortMode = sortMode; @@ -59,18 +59,18 @@ public class SortDialogFragment extends DialogFragment { // Inflate and set the layout for the dialog // Pass null as the parent view because its going in the dialog layout - View root = inflater.inflate(R.layout.dialog_sort, null); + View root = inflater.inflate(R.layout.dialog_filter, null); builder.setView(root) // Add action buttons .setPositiveButton("OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { - onSortingListener.sendSort(storeSelection, sortMode, descending, priceSeekbar.getSelectedMinValue().doubleValue(), priceSeekbar.getSelectedMaxValue().doubleValue()); + onFilterListener.sendSort(storeSelection, sortMode, descending, priceSeekbar.getSelectedMinValue().doubleValue(), priceSeekbar.getSelectedMaxValue().doubleValue()); } }) .setNegativeButton("cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { - SortDialogFragment.this.getDialog().cancel(); + FilterDialogFragment.this.getDialog().cancel(); } }); @@ -175,9 +175,9 @@ public class SortDialogFragment extends DialogFragment { public void onAttach(@NonNull Context context) { super.onAttach(context); try { - onSortingListener = (OnSortingListener) getActivity(); + onFilterListener = (OnFilterListener) getActivity(); } catch (ClassCastException e) { - Log.e("SortDialogFragment", "onAttach: ClassCastException: " + e.getMessage()); + Log.e("FilterDialogFragment", "onAttach: ClassCastException: " + e.getMessage()); } } } diff --git a/Listify/app/src/main/java/com/example/listify/SearchResults.java b/Listify/app/src/main/java/com/example/listify/SearchResults.java index fcea894..102e3d2 100644 --- a/Listify/app/src/main/java/com/example/listify/SearchResults.java +++ b/Listify/app/src/main/java/com/example/listify/SearchResults.java @@ -3,6 +3,9 @@ import android.content.Intent; import android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; + +import android.view.Menu; +import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.EditText; @@ -22,7 +25,7 @@ import java.util.Properties; import static com.example.listify.MainActivity.am; -public class SearchResults extends AppCompatActivity implements SortDialogFragment.OnSortingListener { +public class SearchResults extends AppCompatActivity implements FilterDialogFragment.OnFilterListener { private ListView listView; private SearchResultsListAdapter searchResultsListAdapter; private List resultsProductList = new ArrayList<>(); @@ -108,14 +111,26 @@ public class SearchResults extends AppCompatActivity implements SortDialogFragme return false; } }); + } - // TODO: Change this to a menu in which sort and filter are two different options - // TODO: Sort should be disabled until a search is made - // Create a dialog for filtering and sorting search results - ImageButton sortButton = (ImageButton) findViewById(R.id.results_sort_button); - sortButton.setOnClickListener(new View.OnClickListener() { + @Override + public boolean onCreateOptionsMenu(Menu menu) { + //Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.search, menu); + MenuItem sortItem = menu.findItem(R.id.action_sort); + sortItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override - public void onClick(View v) { + public boolean onMenuItemClick(MenuItem item) { + // TODO: Create a sort dialog + return false; + } + }); + + // TODO: filter should be disabled until a search is made + MenuItem filterItem = menu.findItem(R.id.action_filter); + filterItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem item) { // Sort the store list stores.sort(new Comparator() { @Override @@ -147,11 +162,12 @@ public class SearchResults extends AppCompatActivity implements SortDialogFragme // Round up to nearest whole number for display on price seekbar maxProductPrice = Math.ceil(maxProductPrice); - SortDialogFragment sortDialog = new SortDialogFragment(storeSelection, stores, sortMode, descending, maxProductPrice, minPrice, maxPrice); + FilterDialogFragment sortDialog = new FilterDialogFragment(storeSelection, stores, sortMode, descending, maxProductPrice, minPrice, maxPrice); sortDialog.show(getSupportFragmentManager(), "Sort"); + return false; } }); - + return true; } diff --git a/Listify/app/src/main/res/layout/activity_search_results.xml b/Listify/app/src/main/res/layout/activity_search_results.xml index 2d8356e..2017735 100644 --- a/Listify/app/src/main/res/layout/activity_search_results.xml +++ b/Listify/app/src/main/res/layout/activity_search_results.xml @@ -36,13 +36,13 @@ > - + + + + + + + diff --git a/Listify/app/src/main/res/layout/dialog_sort.xml b/Listify/app/src/main/res/layout/dialog_filter.xml similarity index 100% rename from Listify/app/src/main/res/layout/dialog_sort.xml rename to Listify/app/src/main/res/layout/dialog_filter.xml diff --git a/Listify/app/src/main/res/menu/search.xml b/Listify/app/src/main/res/menu/search.xml new file mode 100644 index 0000000..1602687 --- /dev/null +++ b/Listify/app/src/main/res/menu/search.xml @@ -0,0 +1,14 @@ + + + + + From e7c1ab85ea479147aa3739dee7cb2368ceb1460d Mon Sep 17 00:00:00 2001 From: Clayton Wilson Date: Mon, 26 Oct 2020 00:59:18 -0400 Subject: [PATCH 02/12] Moving sort and filter code to the correct files --- .../example/listify/FilterDialogFragment.java | 87 ++----------- .../com/example/listify/MainActivity.java | 12 -- .../com/example/listify/SearchResults.java | 21 ++- .../example/listify/SortDialogFragment.java | 122 ++++++++++++++++++ .../app/src/main/res/layout/dialog_filter.xml | 31 ----- .../app/src/main/res/layout/dialog_sort.xml | 41 ++++++ 6 files changed, 191 insertions(+), 123 deletions(-) create mode 100644 Listify/app/src/main/java/com/example/listify/SortDialogFragment.java create mode 100644 Listify/app/src/main/res/layout/dialog_sort.xml diff --git a/Listify/app/src/main/java/com/example/listify/FilterDialogFragment.java b/Listify/app/src/main/java/com/example/listify/FilterDialogFragment.java index f61ea60..fa2e9a1 100644 --- a/Listify/app/src/main/java/com/example/listify/FilterDialogFragment.java +++ b/Listify/app/src/main/java/com/example/listify/FilterDialogFragment.java @@ -8,24 +8,20 @@ import android.view.LayoutInflater; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; -import android.widget.ImageButton; import android.widget.Spinner; import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.DialogFragment; - import com.crystal.crystalrangeseekbar.interfaces.OnRangeSeekbarChangeListener; import com.crystal.crystalrangeseekbar.widgets.CrystalRangeSeekbar; - import java.util.ArrayList; public class FilterDialogFragment extends DialogFragment { public interface OnFilterListener { - void sendSort(int storeSelection, int sortMode, boolean descending, double minPrice, double maxPrice); + void sendFilter(int storeSelection, double minPrice, double maxPrice); } public OnFilterListener onFilterListener; @@ -33,18 +29,14 @@ public class FilterDialogFragment extends DialogFragment { CrystalRangeSeekbar priceSeekbar; private int storeSelection; - private int sortMode; - private boolean descending; private ArrayList stores; private double maxProductPrice; // The highest price on the slider private double minPrice; // The selected min price private double maxPrice; // The selected max price - public FilterDialogFragment(int storeSelection, ArrayList stores, int sortMode, boolean descending, double maxProductPrice, double minPrice, double maxPrice) { + public FilterDialogFragment(int storeSelection, ArrayList stores, double maxProductPrice, double minPrice, double maxPrice) { this.storeSelection = storeSelection; this.stores = stores; - this.sortMode = sortMode; - this.descending = descending; this.maxProductPrice = maxProductPrice; this.minPrice = minPrice; this.maxPrice = maxPrice; @@ -61,18 +53,18 @@ public class FilterDialogFragment extends DialogFragment { // Pass null as the parent view because its going in the dialog layout View root = inflater.inflate(R.layout.dialog_filter, null); builder.setView(root) - // Add action buttons - .setPositiveButton("OK", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - onFilterListener.sendSort(storeSelection, sortMode, descending, priceSeekbar.getSelectedMinValue().doubleValue(), priceSeekbar.getSelectedMaxValue().doubleValue()); - } - }) - .setNegativeButton("cancel", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - FilterDialogFragment.this.getDialog().cancel(); - } - }); + // Add action buttons + .setPositiveButton("OK", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + onFilterListener.sendFilter(storeSelection, priceSeekbar.getSelectedMinValue().doubleValue(), priceSeekbar.getSelectedMaxValue().doubleValue()); + } + }) + .setNegativeButton("cancel", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + FilterDialogFragment.this.getDialog().cancel(); + } + }); Spinner storeDropdown = (Spinner) root.findViewById(R.id.sort_store_dropdown); String[] storeChoices = new String[stores.size() + 1]; @@ -97,57 +89,6 @@ public class FilterDialogFragment extends DialogFragment { } }); - // Change the sort arrow to be pointing up or down based on ascending or descending - final ImageButton sortDirectionButton = root.findViewById(R.id.sort_direction_button); - if (descending) { - sortDirectionButton.setImageResource(R.drawable.ic_baseline_arrow_downward_50); - } else { - sortDirectionButton.setImageResource(R.drawable.ic_baseline_arrow_upward_50); - } - - // Change arrow pointing direction whenever the user clicks the button - sortDirectionButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (descending) { - descending = false; - sortDirectionButton.setImageResource(R.drawable.ic_baseline_arrow_upward_50); - } else { - descending = true; - sortDirectionButton.setImageResource(R.drawable.ic_baseline_arrow_downward_50); - } - } - }); - - // Create the sort mode selection dropdown - Spinner sortDropdown = (Spinner) root.findViewById(R.id.sort_mode_dropdown); - String[] items = new String[] {"", "Name", "Price", "Store"}; - ArrayAdapter adapter = new ArrayAdapter<>(root.getContext(), android.R.layout.simple_spinner_dropdown_item, items); - sortDropdown.setAdapter(adapter); - sortDropdown.setSelection(this.sortMode); - sortDropdown.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - sortMode = position; - - // Update the sort direction button - if (position == 0) { - sortDirectionButton.setEnabled(false); - } else { - sortDirectionButton.setEnabled(true); - } - } - - @Override - public void onNothingSelected(AdapterView parent) {} - }); - - // Disable the direction button if they have the default sorting mode selected - // Ascending and Descending are mostly irrelevant in the default sort mode - if (sortDropdown.getSelectedItemPosition() == 0) { - sortDirectionButton.setEnabled(false); - } - // Set up the seekbar for price priceSeekbar = (CrystalRangeSeekbar) root.findViewById(R.id.price_range_seekbar); final TextView tvMin = (TextView) root.findViewById(R.id.tv_min_price); diff --git a/Listify/app/src/main/java/com/example/listify/MainActivity.java b/Listify/app/src/main/java/com/example/listify/MainActivity.java index dd6d2bc..fef669e 100644 --- a/Listify/app/src/main/java/com/example/listify/MainActivity.java +++ b/Listify/app/src/main/java/com/example/listify/MainActivity.java @@ -190,18 +190,6 @@ public class MainActivity extends AppCompatActivity implements CreateListDialogF return NavigationUI.navigateUp(navController, mAppBarConfiguration) || super.onSupportNavigateUp(); } - // This function only exists for the create new list option in hamburger menu - public void onClickCreateList(MenuItem m) { - m.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { - @Override - public boolean onMenuItemClick(MenuItem item) { - CreateListDialogFragment createListDialogFragment = new CreateListDialogFragment(); - createListDialogFragment.show(getSupportFragmentManager(), "Create New List"); - return false; - } - }); - } - public void onClickSignout(MenuItem m) { m.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override diff --git a/Listify/app/src/main/java/com/example/listify/SearchResults.java b/Listify/app/src/main/java/com/example/listify/SearchResults.java index 102e3d2..4f24bcf 100644 --- a/Listify/app/src/main/java/com/example/listify/SearchResults.java +++ b/Listify/app/src/main/java/com/example/listify/SearchResults.java @@ -25,7 +25,7 @@ import java.util.Properties; import static com.example.listify.MainActivity.am; -public class SearchResults extends AppCompatActivity implements FilterDialogFragment.OnFilterListener { +public class SearchResults extends AppCompatActivity implements FilterDialogFragment.OnFilterListener, SortDialogFragment.OnSortListener { private ListView listView; private SearchResultsListAdapter searchResultsListAdapter; private List resultsProductList = new ArrayList<>(); @@ -38,15 +38,20 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag private double maxPrice = -1; @Override - public void sendSort(int storeSelection, int sortMode, boolean descending, double minPrice, double maxPrice) { + public void sendFilter(int storeSelection, double minPrice, double maxPrice) { this.storeSelection = storeSelection; - this.sortMode = sortMode; - this.descending = descending; this.minPrice = minPrice; this.maxPrice = maxPrice; sortResults(); } + @Override + public void sendSort(int sortMode, boolean descending) { + this.sortMode = sortMode; + this.descending = descending; + sortResults(); + } + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -122,11 +127,13 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag @Override public boolean onMenuItemClick(MenuItem item) { // TODO: Create a sort dialog + SortDialogFragment sortDialog = new SortDialogFragment(sortMode, descending); + sortDialog.show(getSupportFragmentManager(), "Sort Dialog"); return false; } }); - // TODO: filter should be disabled until a search is made + // TODO: price filter should be disabled until a search is made MenuItem filterItem = menu.findItem(R.id.action_filter); filterItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override @@ -162,8 +169,8 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag // Round up to nearest whole number for display on price seekbar maxProductPrice = Math.ceil(maxProductPrice); - FilterDialogFragment sortDialog = new FilterDialogFragment(storeSelection, stores, sortMode, descending, maxProductPrice, minPrice, maxPrice); - sortDialog.show(getSupportFragmentManager(), "Sort"); + FilterDialogFragment sortDialog = new FilterDialogFragment(storeSelection, stores, maxProductPrice, minPrice, maxPrice); + sortDialog.show(getSupportFragmentManager(), "Filter Dialog"); return false; } }); diff --git a/Listify/app/src/main/java/com/example/listify/SortDialogFragment.java b/Listify/app/src/main/java/com/example/listify/SortDialogFragment.java new file mode 100644 index 0000000..ab46236 --- /dev/null +++ b/Listify/app/src/main/java/com/example/listify/SortDialogFragment.java @@ -0,0 +1,122 @@ +package com.example.listify; +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageButton; +import android.widget.Spinner; +import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; +import androidx.fragment.app.DialogFragment; + + +public class SortDialogFragment extends DialogFragment { + + public interface OnSortListener { + void sendSort(int sortMode, boolean descending); + } + + public OnSortListener onSortListener; + + private int sortMode; + private boolean descending; + + public SortDialogFragment(int sortMode, boolean descending) { + this.sortMode = sortMode; + this.descending = descending; + } + + + @Override + public Dialog onCreateDialog(final Bundle savedInstanceState) { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + // Get the layout inflater + LayoutInflater inflater = requireActivity().getLayoutInflater(); + + // Inflate and set the layout for the dialog + // Pass null as the parent view because its going in the dialog layout + View root = inflater.inflate(R.layout.dialog_sort, null); + builder.setView(root) + // Add action buttons + .setPositiveButton("OK", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + onSortListener.sendSort(sortMode, descending); + } + }) + .setNegativeButton("cancel", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + SortDialogFragment.this.getDialog().cancel(); + } + }); + + // Change the sort arrow to be pointing up or down based on ascending or descending + final ImageButton sortDirectionButton = root.findViewById(R.id.sort_direction_button); + if (descending) { + sortDirectionButton.setImageResource(R.drawable.ic_baseline_arrow_downward_50); + } else { + sortDirectionButton.setImageResource(R.drawable.ic_baseline_arrow_upward_50); + } + + // Change arrow pointing direction whenever the user clicks the button + sortDirectionButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (descending) { + descending = false; + sortDirectionButton.setImageResource(R.drawable.ic_baseline_arrow_upward_50); + } else { + descending = true; + sortDirectionButton.setImageResource(R.drawable.ic_baseline_arrow_downward_50); + } + } + }); + + // Create the sort mode selection dropdown + Spinner sortDropdown = (Spinner) root.findViewById(R.id.sort_mode_dropdown); + String[] items = new String[] {"", "Name", "Price", "Store"}; + ArrayAdapter adapter = new ArrayAdapter<>(root.getContext(), android.R.layout.simple_spinner_dropdown_item, items); + sortDropdown.setAdapter(adapter); + sortDropdown.setSelection(this.sortMode); + sortDropdown.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + sortMode = position; + + // Update the sort direction button + if (position == 0) { + sortDirectionButton.setEnabled(false); + } else { + sortDirectionButton.setEnabled(true); + } + } + + @Override + public void onNothingSelected(AdapterView parent) {} + }); + + // Disable the direction button if they have the default sorting mode selected + // Ascending and Descending are mostly irrelevant in the default sort mode + if (sortDropdown.getSelectedItemPosition() == 0) { + sortDirectionButton.setEnabled(false); + } + + return builder.create(); + } + + // Required to extend DialogFragment + @Override + public void onAttach(@NonNull Context context) { + super.onAttach(context); + try { + onSortListener = (OnSortListener) getActivity(); + } catch (ClassCastException e) { + Log.e("FilterDialogFragment", "onAttach: ClassCastException: " + e.getMessage()); + } + } +} diff --git a/Listify/app/src/main/res/layout/dialog_filter.xml b/Listify/app/src/main/res/layout/dialog_filter.xml index 6a6d5b1..4783b06 100644 --- a/Listify/app/src/main/res/layout/dialog_filter.xml +++ b/Listify/app/src/main/res/layout/dialog_filter.xml @@ -20,37 +20,6 @@ android:background="@android:drawable/spinner_dropdown_background" android:spinnerMode="dropdown"/> - - - - - - - - - - + + + + + + + + + + + + + + \ No newline at end of file From 20b86c573abe2721a2217663dcaff41ef8db7165 Mon Sep 17 00:00:00 2001 From: Clayton Wilson Date: Mon, 26 Oct 2020 03:49:43 -0400 Subject: [PATCH 03/12] New sort dialog layout --- .../example/listify/SortDialogFragment.java | 81 ++++--------- .../res/layout/activity_search_results.xml | 14 +-- .../app/src/main/res/layout/app_bar_home.xml | 6 +- .../app/src/main/res/layout/dialog_sort.xml | 114 +++++++++++++----- 4 files changed, 117 insertions(+), 98 deletions(-) diff --git a/Listify/app/src/main/java/com/example/listify/SortDialogFragment.java b/Listify/app/src/main/java/com/example/listify/SortDialogFragment.java index ab46236..a97cd1f 100644 --- a/Listify/app/src/main/java/com/example/listify/SortDialogFragment.java +++ b/Listify/app/src/main/java/com/example/listify/SortDialogFragment.java @@ -1,20 +1,15 @@ package com.example.listify; import android.app.Dialog; import android.content.Context; -import android.content.DialogInterface; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.ImageButton; -import android.widget.Spinner; +import android.widget.TextView; import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.DialogFragment; - public class SortDialogFragment extends DialogFragment { public interface OnSortListener { @@ -41,70 +36,40 @@ public class SortDialogFragment extends DialogFragment { // Inflate and set the layout for the dialog // Pass null as the parent view because its going in the dialog layout View root = inflater.inflate(R.layout.dialog_sort, null); - builder.setView(root) - // Add action buttons - .setPositiveButton("OK", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - onSortListener.sendSort(sortMode, descending); - } - }) - .setNegativeButton("cancel", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - SortDialogFragment.this.getDialog().cancel(); - } - }); + builder.setView(root); - // Change the sort arrow to be pointing up or down based on ascending or descending - final ImageButton sortDirectionButton = root.findViewById(R.id.sort_direction_button); - if (descending) { - sortDirectionButton.setImageResource(R.drawable.ic_baseline_arrow_downward_50); - } else { - sortDirectionButton.setImageResource(R.drawable.ic_baseline_arrow_upward_50); - } + TextView tvSortNone = root.findViewById(R.id.sort_none); + TextView tvSortName = root.findViewById(R.id.sort_name); + TextView tvSortPrice = root.findViewById(R.id.sort_price); + TextView tvSortStore = root.findViewById(R.id.sort_store); - // Change arrow pointing direction whenever the user clicks the button - sortDirectionButton.setOnClickListener(new View.OnClickListener() { + tvSortNone.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - if (descending) { - descending = false; - sortDirectionButton.setImageResource(R.drawable.ic_baseline_arrow_upward_50); - } else { - descending = true; - sortDirectionButton.setImageResource(R.drawable.ic_baseline_arrow_downward_50); - } + } }); - // Create the sort mode selection dropdown - Spinner sortDropdown = (Spinner) root.findViewById(R.id.sort_mode_dropdown); - String[] items = new String[] {"", "Name", "Price", "Store"}; - ArrayAdapter adapter = new ArrayAdapter<>(root.getContext(), android.R.layout.simple_spinner_dropdown_item, items); - sortDropdown.setAdapter(adapter); - sortDropdown.setSelection(this.sortMode); - sortDropdown.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + tvSortName.setOnClickListener(new View.OnClickListener() { @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - sortMode = position; + public void onClick(View v) { - // Update the sort direction button - if (position == 0) { - sortDirectionButton.setEnabled(false); - } else { - sortDirectionButton.setEnabled(true); - } } - - @Override - public void onNothingSelected(AdapterView parent) {} }); - // Disable the direction button if they have the default sorting mode selected - // Ascending and Descending are mostly irrelevant in the default sort mode - if (sortDropdown.getSelectedItemPosition() == 0) { - sortDirectionButton.setEnabled(false); - } + tvSortPrice.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + } + }); + + tvSortStore.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + } + }); return builder.create(); } diff --git a/Listify/app/src/main/res/layout/activity_search_results.xml b/Listify/app/src/main/res/layout/activity_search_results.xml index 2017735..3850f4d 100644 --- a/Listify/app/src/main/res/layout/activity_search_results.xml +++ b/Listify/app/src/main/res/layout/activity_search_results.xml @@ -23,10 +23,12 @@ android:id="@+id/backToHomeButton" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_weight="1" + android:translationX="-10dp" + android:padding="10dp" app:srcCompat="@drawable/abc_vector_test" android:background="@null" - android:contentDescription="@string/backButton"/> + android:contentDescription="@string/backButton" + android:foreground="?android:attr/selectableItemBackgroundBorderless"/> - - - - - - - - diff --git a/Listify/app/src/main/res/layout/app_bar_home.xml b/Listify/app/src/main/res/layout/app_bar_home.xml index 285fb12..d124049 100644 --- a/Listify/app/src/main/res/layout/app_bar_home.xml +++ b/Listify/app/src/main/res/layout/app_bar_home.xml @@ -19,13 +19,15 @@ app:popupTheme="@style/AppTheme.PopupOverlay" > + android:background="@null" + android:foreground="?android:attr/selectableItemBackgroundBorderless"/> diff --git a/Listify/app/src/main/res/layout/dialog_sort.xml b/Listify/app/src/main/res/layout/dialog_sort.xml index 01f3251..09f4f03 100644 --- a/Listify/app/src/main/res/layout/dialog_sort.xml +++ b/Listify/app/src/main/res/layout/dialog_sort.xml @@ -1,41 +1,99 @@ + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginHorizontal="30dp"> + android:id="@+id/sort_none" + android:layout_width="match_parent" + android:layout_height="50dp" + android:text="None" + android:textSize="16sp" + android:textColor="@android:color/black" + android:paddingStart="16dp" + android:gravity="center_vertical" + android:clickable="true" + android:focusable="true" + android:foreground="?attr/selectableItemBackgroundBorderless" + android:soundEffectsEnabled="true"/> + + + + + + + + + + + + + + + android:layout_width="match_parent" + android:layout_height="50dp" + android:gravity="center_vertical"> - - - + android:text="Descending" + android:textSize="16sp" + android:textColor="@android:color/black" + android:paddingStart="16dp"/> + - \ No newline at end of file From 32dd8c56ca4e78e23aafa168b2615d6e963dcbd5 Mon Sep 17 00:00:00 2001 From: Clayton Wilson Date: Mon, 26 Oct 2020 19:15:58 -0400 Subject: [PATCH 04/12] New sort dialog fully implemented --- .../com/example/listify/SearchResults.java | 18 ++-- .../example/listify/SortDialogFragment.java | 85 ++++++++++++++++--- .../java/com/example/listify/SortModes.java | 9 ++ .../app/src/main/res/layout/dialog_sort.xml | 12 ++- Listify/app/src/main/res/values/colors.xml | 1 + 5 files changed, 101 insertions(+), 24 deletions(-) create mode 100644 Listify/app/src/main/java/com/example/listify/SortModes.java diff --git a/Listify/app/src/main/java/com/example/listify/SearchResults.java b/Listify/app/src/main/java/com/example/listify/SearchResults.java index 4f24bcf..36542f2 100644 --- a/Listify/app/src/main/java/com/example/listify/SearchResults.java +++ b/Listify/app/src/main/java/com/example/listify/SearchResults.java @@ -32,7 +32,7 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag private List resultsProductListSorted = new ArrayList<>(); private ArrayList stores = new ArrayList<>(); private int storeSelection; - private int sortMode; + private SortModes sortMode = SortModes.NONE; private boolean descending; private double minPrice = 0; private double maxPrice = -1; @@ -46,7 +46,7 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag } @Override - public void sendSort(int sortMode, boolean descending) { + public void sendSort(SortModes sortMode, boolean descending) { this.sortMode = sortMode; this.descending = descending; sortResults(); @@ -243,10 +243,10 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag // Sort based on mode switch (this.sortMode) { - case 0: + case NONE: // Do nothing break; - case 1: + case NAME: resultsProductListSorted.sort(new Comparator() { @Override public int compare(Product a, Product b) { @@ -254,9 +254,7 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag } }); break; - - // TODO: May need to change this depending on if price is stored as a string or a double - case 2: + case PRICE: resultsProductListSorted.sort(new Comparator() { @Override public int compare(Product a, Product b) { @@ -271,7 +269,7 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag }); break; - case 3: + case STORE: resultsProductListSorted.sort(new Comparator() { @Override public int compare(Product a, Product b) { @@ -280,7 +278,7 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag }); break; - case 4: + case UPC: resultsProductListSorted.sort(new Comparator() { @Override public int compare(Product a, Product b) { @@ -291,7 +289,7 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag } // Flip the list if descending is selected - if (this.sortMode != 0 & this.descending) { + if (this.sortMode != SortModes.NONE & this.descending) { for (int i = 0; i < resultsProductListSorted.size() / 2; i++) { Product temp = resultsProductListSorted.get(i); resultsProductListSorted.set(i, resultsProductListSorted.get(resultsProductListSorted.size() - i - 1)); diff --git a/Listify/app/src/main/java/com/example/listify/SortDialogFragment.java b/Listify/app/src/main/java/com/example/listify/SortDialogFragment.java index a97cd1f..0fbf7f2 100644 --- a/Listify/app/src/main/java/com/example/listify/SortDialogFragment.java +++ b/Listify/app/src/main/java/com/example/listify/SortDialogFragment.java @@ -5,23 +5,31 @@ import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; +import android.widget.LinearLayout; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.widget.SwitchCompat; import androidx.fragment.app.DialogFragment; public class SortDialogFragment extends DialogFragment { public interface OnSortListener { - void sendSort(int sortMode, boolean descending); + void sendSort(SortModes sortMode, boolean descending); } public OnSortListener onSortListener; - private int sortMode; + private SortModes sortMode; private boolean descending; - public SortDialogFragment(int sortMode, boolean descending) { + TextView tvSortNone; + TextView tvSortName; + TextView tvSortPrice; + TextView tvSortStore; + SwitchCompat swDescending; + + public SortDialogFragment(SortModes sortMode, boolean descending) { this.sortMode = sortMode; this.descending = descending; } @@ -38,42 +46,97 @@ public class SortDialogFragment extends DialogFragment { View root = inflater.inflate(R.layout.dialog_sort, null); builder.setView(root); - TextView tvSortNone = root.findViewById(R.id.sort_none); - TextView tvSortName = root.findViewById(R.id.sort_name); - TextView tvSortPrice = root.findViewById(R.id.sort_price); - TextView tvSortStore = root.findViewById(R.id.sort_store); + tvSortNone = (TextView) root.findViewById(R.id.sort_none); + tvSortName = (TextView) root.findViewById(R.id.sort_name); + tvSortPrice = (TextView) root.findViewById(R.id.sort_price); + tvSortStore = (TextView) root.findViewById(R.id.sort_store); + LinearLayout llDescendingContainer = (LinearLayout) root.findViewById(R.id.descending_container); + swDescending = (SwitchCompat) root.findViewById(R.id.switch_descending); + + switch (this.sortMode) { + case NONE: + tvSortNone.setBackgroundColor(getResources().getColor(R.color.colorAccent)); + break; + case NAME: + tvSortName.setBackgroundColor(getResources().getColor(R.color.colorAccent)); + break; + case PRICE: + tvSortPrice.setBackgroundColor(getResources().getColor(R.color.colorAccent)); + break; + case STORE: + tvSortStore.setBackgroundColor(getResources().getColor(R.color.colorAccent)); + break; + } + + if (this.descending) { + swDescending.setChecked(true); + } tvSortNone.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - + handleClicked(tvSortNone, SortModes.NONE, swDescending.isChecked()); } }); tvSortName.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - + handleClicked(tvSortName, SortModes.NAME, swDescending.isChecked()); } }); tvSortPrice.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - + handleClicked(tvSortPrice, SortModes.PRICE, swDescending.isChecked()); } }); tvSortStore.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { + handleClicked(tvSortStore, SortModes.STORE, swDescending.isChecked()); + } + }); + // TODO: set onclick listener for descending switch + llDescendingContainer.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + System.out.println("linear"); + swDescending.performClick(); +// handleClicked(sortMode, swDescending.isChecked()); + } + }); + + swDescending.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + System.out.println("switch"); + descending = swDescending.isChecked(); + onSortListener.sendSort(sortMode, swDescending.isChecked()); } }); return builder.create(); } + void handleClicked(TextView tvSelected, SortModes sortMode, boolean descending) { + this.sortMode = sortMode; + this.descending = descending; + + tvSortNone.setBackgroundColor(getResources().getColor(R.color.white)); + tvSortName.setBackgroundColor(getResources().getColor(R.color.white)); + tvSortPrice.setBackgroundColor(getResources().getColor(R.color.white)); + tvSortStore.setBackgroundColor(getResources().getColor(R.color.white)); + + tvSelected.setBackgroundColor(getResources().getColor(R.color.colorAccent)); + onSortListener.sendSort(sortMode, descending); + +// SortDialogFragment.this.getDialog().cancel(); + } + // Required to extend DialogFragment @Override public void onAttach(@NonNull Context context) { @@ -81,7 +144,7 @@ public class SortDialogFragment extends DialogFragment { try { onSortListener = (OnSortListener) getActivity(); } catch (ClassCastException e) { - Log.e("FilterDialogFragment", "onAttach: ClassCastException: " + e.getMessage()); + Log.e("SortDialogFragment", "onAttach: ClassCastException: " + e.getMessage()); } } } diff --git a/Listify/app/src/main/java/com/example/listify/SortModes.java b/Listify/app/src/main/java/com/example/listify/SortModes.java new file mode 100644 index 0000000..6c490a3 --- /dev/null +++ b/Listify/app/src/main/java/com/example/listify/SortModes.java @@ -0,0 +1,9 @@ +package com.example.listify; + +public enum SortModes { + NONE, + NAME, + PRICE, + STORE, + UPC +} diff --git a/Listify/app/src/main/res/layout/dialog_sort.xml b/Listify/app/src/main/res/layout/dialog_sort.xml index 09f4f03..af88f7d 100644 --- a/Listify/app/src/main/res/layout/dialog_sort.xml +++ b/Listify/app/src/main/res/layout/dialog_sort.xml @@ -4,6 +4,7 @@ android:layout_height="wrap_content" android:layout_marginHorizontal="30dp"> + + android:foreground="?attr/selectableItemBackgroundBorderless" /> + android:gravity="center_vertical" + android:clickable="true" + android:focusable="true" + android:foreground="?attr/selectableItemBackgroundBorderless" + android:soundEffectsEnabled="false"> diff --git a/Listify/app/src/main/res/values/colors.xml b/Listify/app/src/main/res/values/colors.xml index a9055a6..84a11b5 100644 --- a/Listify/app/src/main/res/values/colors.xml +++ b/Listify/app/src/main/res/values/colors.xml @@ -11,4 +11,5 @@ #ebeef0 #1c9ef4 #e6e6e6 + #ffffffff \ No newline at end of file From e392820404e1ff0004ea24be53b26470e3553598 Mon Sep 17 00:00:00 2001 From: Clayton Wilson Date: Sat, 31 Oct 2020 19:36:45 -0400 Subject: [PATCH 05/12] Default can be sorted descending --- .../app/src/main/java/com/example/listify/SearchResults.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Listify/app/src/main/java/com/example/listify/SearchResults.java b/Listify/app/src/main/java/com/example/listify/SearchResults.java index 36542f2..f6d84b5 100644 --- a/Listify/app/src/main/java/com/example/listify/SearchResults.java +++ b/Listify/app/src/main/java/com/example/listify/SearchResults.java @@ -126,7 +126,6 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag sortItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { - // TODO: Create a sort dialog SortDialogFragment sortDialog = new SortDialogFragment(sortMode, descending); sortDialog.show(getSupportFragmentManager(), "Sort Dialog"); return false; @@ -289,7 +288,7 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag } // Flip the list if descending is selected - if (this.sortMode != SortModes.NONE & this.descending) { + if (this.descending) { for (int i = 0; i < resultsProductListSorted.size() / 2; i++) { Product temp = resultsProductListSorted.get(i); resultsProductListSorted.set(i, resultsProductListSorted.get(resultsProductListSorted.size() - i - 1)); From 33c3d8c56e504806e28d1975763e28fb874c4e53 Mon Sep 17 00:00:00 2001 From: Clayton Wilson Date: Sun, 1 Nov 2020 00:51:38 -0400 Subject: [PATCH 06/12] Filtering search results is disabled until there are results to filter --- .../java/com/example/listify/SearchResults.java | 16 +++++++++++++++- .../com/example/listify/SortDialogFragment.java | 1 + 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Listify/app/src/main/java/com/example/listify/SearchResults.java b/Listify/app/src/main/java/com/example/listify/SearchResults.java index f6d84b5..7111156 100644 --- a/Listify/app/src/main/java/com/example/listify/SearchResults.java +++ b/Listify/app/src/main/java/com/example/listify/SearchResults.java @@ -27,6 +27,7 @@ import static com.example.listify.MainActivity.am; public class SearchResults extends AppCompatActivity implements FilterDialogFragment.OnFilterListener, SortDialogFragment.OnSortListener { private ListView listView; + private MenuItem filterItem; private SearchResultsListAdapter searchResultsListAdapter; private List resultsProductList = new ArrayList<>(); private List resultsProductListSorted = new ArrayList<>(); @@ -133,7 +134,7 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag }); // TODO: price filter should be disabled until a search is made - MenuItem filterItem = menu.findItem(R.id.action_filter); + filterItem = menu.findItem(R.id.action_filter); filterItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { @@ -173,6 +174,12 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag return false; } }); + + // Disable filtering by default until a search is made + if (resultsProductList.isEmpty()) { + filterItem.setEnabled(false); + } + return true; } @@ -223,6 +230,13 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag // Add all results to the sorted list resultsProductListSorted.addAll(resultsProductList); + // Filtering should only be allowed if there are items in the results + if (resultsProductList.isEmpty()) { + filterItem.setEnabled(false); + } else { + filterItem.setEnabled(true); + } + // Apply selected sorting to the list sortResults(); } diff --git a/Listify/app/src/main/java/com/example/listify/SortDialogFragment.java b/Listify/app/src/main/java/com/example/listify/SortDialogFragment.java index 0fbf7f2..e76a43e 100644 --- a/Listify/app/src/main/java/com/example/listify/SortDialogFragment.java +++ b/Listify/app/src/main/java/com/example/listify/SortDialogFragment.java @@ -35,6 +35,7 @@ public class SortDialogFragment extends DialogFragment { } + // TODO: Sorting should scroll the user back to the top of the page @Override public Dialog onCreateDialog(final Bundle savedInstanceState) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); From 9616c7a57294e4857484657e24a1881f23924b5e Mon Sep 17 00:00:00 2001 From: Clayton Wilson Date: Sun, 1 Nov 2020 02:42:02 -0500 Subject: [PATCH 07/12] Display checkbox listview for filtering store selection --- .../example/listify/FilterDialogFragment.java | 43 ++++----- .../com/example/listify/SearchResults.java | 32 ++++--- .../adapter/CheckBoxListViewAdapter.java | 94 +++++++++++++++++++ .../app/src/main/res/layout/dialog_filter.xml | 11 +-- .../src/main/res/layout/filter_store_item.xml | 30 ++++++ 5 files changed, 162 insertions(+), 48 deletions(-) create mode 100644 Listify/app/src/main/java/com/example/listify/adapter/CheckBoxListViewAdapter.java create mode 100644 Listify/app/src/main/res/layout/filter_store_item.xml diff --git a/Listify/app/src/main/java/com/example/listify/FilterDialogFragment.java b/Listify/app/src/main/java/com/example/listify/FilterDialogFragment.java index fa2e9a1..e12eb39 100644 --- a/Listify/app/src/main/java/com/example/listify/FilterDialogFragment.java +++ b/Listify/app/src/main/java/com/example/listify/FilterDialogFragment.java @@ -6,36 +6,37 @@ import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.Spinner; +import android.widget.ListView; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.DialogFragment; import com.crystal.crystalrangeseekbar.interfaces.OnRangeSeekbarChangeListener; import com.crystal.crystalrangeseekbar.widgets.CrystalRangeSeekbar; +import com.example.listify.adapter.CheckBoxListViewAdapter; + import java.util.ArrayList; public class FilterDialogFragment extends DialogFragment { public interface OnFilterListener { - void sendFilter(int storeSelection, double minPrice, double maxPrice); + void sendFilter(ArrayList selectedStores, double minPrice, double maxPrice); } public OnFilterListener onFilterListener; CrystalRangeSeekbar priceSeekbar; + CheckBoxListViewAdapter checkBoxAdapter; - private int storeSelection; + private ArrayList selectedStores; private ArrayList stores; private double maxProductPrice; // The highest price on the slider private double minPrice; // The selected min price private double maxPrice; // The selected max price - public FilterDialogFragment(int storeSelection, ArrayList stores, double maxProductPrice, double minPrice, double maxPrice) { - this.storeSelection = storeSelection; + public FilterDialogFragment(ArrayList selectedStores, ArrayList stores, double maxProductPrice, double minPrice, double maxPrice) { + this.selectedStores = selectedStores; this.stores = stores; this.maxProductPrice = maxProductPrice; this.minPrice = minPrice; @@ -57,7 +58,8 @@ public class FilterDialogFragment extends DialogFragment { .setPositiveButton("OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { - onFilterListener.sendFilter(storeSelection, priceSeekbar.getSelectedMinValue().doubleValue(), priceSeekbar.getSelectedMaxValue().doubleValue()); + selectedStores = checkBoxAdapter.getChecked(); + onFilterListener.sendFilter(selectedStores, priceSeekbar.getSelectedMinValue().doubleValue(), priceSeekbar.getSelectedMaxValue().doubleValue()); } }) .setNegativeButton("cancel", new DialogInterface.OnClickListener() { @@ -66,28 +68,15 @@ public class FilterDialogFragment extends DialogFragment { } }); - Spinner storeDropdown = (Spinner) root.findViewById(R.id.sort_store_dropdown); - String[] storeChoices = new String[stores.size() + 1]; - storeChoices[0] = "All"; - for (int i = 1; i < stores.size() + 1; i++) { - storeChoices[i] = stores.get(i - 1); - } + ListView storesList = root.findViewById(R.id.store_name_list); - // Create the store selection dropdown - ArrayAdapter storeAdapter = new ArrayAdapter<>(root.getContext(), android.R.layout.simple_spinner_dropdown_item, storeChoices); - storeDropdown.setAdapter(storeAdapter); - storeDropdown.setSelection(this.storeSelection); - storeDropdown.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - storeSelection = position; - } + // Create arraylist of stores from search results + ArrayList storeChoices = new ArrayList<>(stores); - @Override - public void onNothingSelected(AdapterView parent) { + // Create adapter and send stores and selected stores + checkBoxAdapter = new CheckBoxListViewAdapter(getActivity(), storeChoices, this.selectedStores); - } - }); + storesList.setAdapter(checkBoxAdapter); // Set up the seekbar for price priceSeekbar = (CrystalRangeSeekbar) root.findViewById(R.id.price_range_seekbar); diff --git a/Listify/app/src/main/java/com/example/listify/SearchResults.java b/Listify/app/src/main/java/com/example/listify/SearchResults.java index 7111156..80ddc3e 100644 --- a/Listify/app/src/main/java/com/example/listify/SearchResults.java +++ b/Listify/app/src/main/java/com/example/listify/SearchResults.java @@ -32,15 +32,15 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag private List resultsProductList = new ArrayList<>(); private List resultsProductListSorted = new ArrayList<>(); private ArrayList stores = new ArrayList<>(); - private int storeSelection; + private ArrayList selectedStores = new ArrayList<>(); private SortModes sortMode = SortModes.NONE; private boolean descending; private double minPrice = 0; private double maxPrice = -1; @Override - public void sendFilter(int storeSelection, double minPrice, double maxPrice) { - this.storeSelection = storeSelection; + public void sendFilter(ArrayList selectedStores, double minPrice, double maxPrice) { + this.selectedStores = selectedStores; this.minPrice = minPrice; this.maxPrice = maxPrice; sortResults(); @@ -138,14 +138,6 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag filterItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { - // Sort the store list - stores.sort(new Comparator() { - @Override - public int compare(String o1, String o2) { - return o1.compareTo(o2); - } - }); - // Determine the max price for the price slider double maxProductPrice; if (resultsProductList.isEmpty()) { @@ -169,7 +161,7 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag // Round up to nearest whole number for display on price seekbar maxProductPrice = Math.ceil(maxProductPrice); - FilterDialogFragment sortDialog = new FilterDialogFragment(storeSelection, stores, maxProductPrice, minPrice, maxPrice); + FilterDialogFragment sortDialog = new FilterDialogFragment(selectedStores, stores, maxProductPrice, minPrice, maxPrice); sortDialog.show(getSupportFragmentManager(), "Filter Dialog"); return false; } @@ -227,6 +219,18 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag } } + // Sort the store list + stores.sort(new Comparator() { + @Override + public int compare(String o1, String o2) { + return o1.compareTo(o2); + } + }); + + // Reset selected stores on search so that every store is selected + this.selectedStores.clear(); + this.selectedStores.addAll(stores); + // Add all results to the sorted list resultsProductListSorted.addAll(resultsProductList); @@ -311,10 +315,10 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag } // Only keep results that match the current store selection - if (this.storeSelection != 0) { + if (!this.selectedStores.equals(this.stores)) { ArrayList temp = new ArrayList<>(); resultsProductListSorted.forEach(product -> { - if (product.getChainName().equals(this.stores.get(this.storeSelection - 1))) { + if (this.selectedStores.contains(product.getChainName())) { temp.add(product); } }); diff --git a/Listify/app/src/main/java/com/example/listify/adapter/CheckBoxListViewAdapter.java b/Listify/app/src/main/java/com/example/listify/adapter/CheckBoxListViewAdapter.java new file mode 100644 index 0000000..5951d79 --- /dev/null +++ b/Listify/app/src/main/java/com/example/listify/adapter/CheckBoxListViewAdapter.java @@ -0,0 +1,94 @@ +package com.example.listify.adapter; +import android.app.Activity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.TextView; +import com.example.listify.R; + +import java.util.ArrayList; + +public class CheckBoxListViewAdapter extends BaseAdapter { + private Activity activity; + ArrayList list = new ArrayList<>(); + ArrayList checkedList = new ArrayList<>(); + + public CheckBoxListViewAdapter(Activity activity, ArrayList list, ArrayList checkedList) { + super(); + this.activity = activity; + this.list = list; + this.checkedList = checkedList; + } + + @Override + public int getCount() { + return list.size(); + } + + @Override + public String getItem(int position) { + return list.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + public class ViewHolder { + public TextView label; + public CheckBox checkBox; + } + @Override + public View getView(final int position, View convertView, ViewGroup parent) { + ViewHolder holder; + LayoutInflater inflator = ((Activity) activity).getLayoutInflater(); + + if (convertView == null) { + convertView = inflator.inflate(R.layout.filter_store_item, null); + + convertView.setSoundEffectsEnabled(false); + + holder = new ViewHolder(); + holder.label = (TextView) convertView.findViewById(R.id.store_name); + holder.checkBox = (CheckBox)convertView.findViewById(R.id.store_check_box); + + holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + int getPosition = (Integer) buttonView.getTag(); + + if (isChecked) { + checkedList.add(list.get(getPosition)); + } else { + checkedList.remove(list.get(getPosition)); + } + } + }); + + convertView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + System.out.println("clicked"); + holder.checkBox.performClick(); + } + }); + + convertView.setTag(holder); + } else { + holder = (ViewHolder) convertView.getTag(); + } + + holder.checkBox.setTag(position); + holder.label.setText("" + list.get(position)); + holder.checkBox.setChecked(checkedList.contains(list.get(position))); + return convertView; + } + + public ArrayList getChecked() { + return this.checkedList; + } +} diff --git a/Listify/app/src/main/res/layout/dialog_filter.xml b/Listify/app/src/main/res/layout/dialog_filter.xml index 4783b06..03ec65c 100644 --- a/Listify/app/src/main/res/layout/dialog_filter.xml +++ b/Listify/app/src/main/res/layout/dialog_filter.xml @@ -12,13 +12,10 @@ android:layout_marginStart="15dp" android:text="@string/store_selection" /> - + + + + + + + + \ No newline at end of file From 6623aeef900d37931ddafa26519def11a00c4e84 Mon Sep 17 00:00:00 2001 From: Clayton Wilson Date: Sun, 1 Nov 2020 19:37:11 -0500 Subject: [PATCH 08/12] Filter dialog layout improvements --- .../java/com/example/listify/SearchResults.java | 2 +- .../app/src/main/res/layout/dialog_filter.xml | 16 +++++++++------- .../src/main/res/layout/filter_store_item.xml | 6 ++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Listify/app/src/main/java/com/example/listify/SearchResults.java b/Listify/app/src/main/java/com/example/listify/SearchResults.java index 80ddc3e..b321a07 100644 --- a/Listify/app/src/main/java/com/example/listify/SearchResults.java +++ b/Listify/app/src/main/java/com/example/listify/SearchResults.java @@ -133,7 +133,7 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag } }); - // TODO: price filter should be disabled until a search is made + // TODO: Reset upper and lower limits on price filter when a new search is made filterItem = menu.findItem(R.id.action_filter); filterItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override diff --git a/Listify/app/src/main/res/layout/dialog_filter.xml b/Listify/app/src/main/res/layout/dialog_filter.xml index 03ec65c..7e6afc5 100644 --- a/Listify/app/src/main/res/layout/dialog_filter.xml +++ b/Listify/app/src/main/res/layout/dialog_filter.xml @@ -6,25 +6,27 @@ + android:text="@string/store_selection" + android:textSize="20sp"/> + android:layout_height="wrap_content" + android:layout_marginTop="5dp" + android:layout_marginBottom="10dp"/> + android:text="Price" + android:textSize="20sp"/> + android:textSize="16sp" + android:layout_marginStart="25dp"/> Date: Sun, 1 Nov 2020 20:09:46 -0500 Subject: [PATCH 09/12] Fixing merge bugs --- .../com/example/listify/MainActivity.java | 18 ------------------ .../com/example/listify/SearchResults.java | 19 ++++++++++++++----- 2 files changed, 14 insertions(+), 23 deletions(-) diff --git a/Listify/app/src/main/java/com/example/listify/MainActivity.java b/Listify/app/src/main/java/com/example/listify/MainActivity.java index ab0e781..fef669e 100644 --- a/Listify/app/src/main/java/com/example/listify/MainActivity.java +++ b/Listify/app/src/main/java/com/example/listify/MainActivity.java @@ -208,24 +208,6 @@ public class MainActivity extends AppCompatActivity implements CreateListDialogF }); } - public void onClickSignout(MenuItem m) { - m.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { - @Override - public boolean onMenuItemClick(MenuItem item) { - try { - am.signOutUser(); - Intent intent = new Intent(MainActivity.this, com.example.listify.ui.LoginPage.class); - startActivity(intent); - finish(); - } - catch (Exception e) { - Log.i("Authentication", e.toString()); - } - return false; - } - }); - } - @Override public void sendNewListName(String name) { Properties configs = new Properties(); diff --git a/Listify/app/src/main/java/com/example/listify/SearchResults.java b/Listify/app/src/main/java/com/example/listify/SearchResults.java index 788f4f7..96e1fa1 100644 --- a/Listify/app/src/main/java/com/example/listify/SearchResults.java +++ b/Listify/app/src/main/java/com/example/listify/SearchResults.java @@ -340,15 +340,24 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag } } + // Reset selected stores on search so that every store is selected + this.selectedStores.clear(); + this.selectedStores.addAll(stores); + // Add all results to the sorted list resultsProductListSorted.addAll(resultsProductList); // Filtering should only be allowed if there are items in the results - if (resultsProductList.isEmpty()) { - filterItem.setEnabled(false); - } else { - filterItem.setEnabled(true); - } + runOnUiThread(new Runnable() { + @Override + public void run() { + if (resultsProductList.isEmpty()) { + filterItem.setEnabled(false); + } else { + filterItem.setEnabled(true); + } + } + }); // Apply selected sorting to the list sortResults(); From 48f96c414691919b172daf97709189ad727babe5 Mon Sep 17 00:00:00 2001 From: NMerz Date: Sun, 1 Nov 2020 21:08:07 -0500 Subject: [PATCH 10/12] Add chainID to Chain class Lambda --- Lambdas/Lists/Chain/src/Chain.java | 35 +++++++++++++++++++ Lambdas/Lists/Chain/src/ChainGET.java | 11 ++++++ Lambdas/Lists/Chain/src/ChainGetter.java | 29 +++++++++++++++ .../java/com/example/listify/data/Chain.java | 27 ++++++++++++++ 4 files changed, 102 insertions(+) create mode 100644 Lambdas/Lists/Chain/src/Chain.java create mode 100644 Lambdas/Lists/Chain/src/ChainGET.java create mode 100644 Lambdas/Lists/Chain/src/ChainGetter.java create mode 100644 Listify/app/src/main/java/com/example/listify/data/Chain.java diff --git a/Lambdas/Lists/Chain/src/Chain.java b/Lambdas/Lists/Chain/src/Chain.java new file mode 100644 index 0000000..925ebf7 --- /dev/null +++ b/Lambdas/Lists/Chain/src/Chain.java @@ -0,0 +1,35 @@ +import java.sql.ResultSet; +import java.sql.SQLException; + +public class Chain { + String name; + String website; + + public Chain (ResultSet chainRow) throws SQLException { + this.name = chainRow.getString("name"); + System.out.println(this.name); + this.website = chainRow.getString("website"); + System.out.println(this.website); + } + + public Chain(String name, String website) { + this.name = name; + this.website = website; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getWebsite() { + return website; + } + + public void setWebsite(String website) { + this.website = website; + } +} diff --git a/Lambdas/Lists/Chain/src/ChainGET.java b/Lambdas/Lists/Chain/src/ChainGET.java new file mode 100644 index 0000000..82842ac --- /dev/null +++ b/Lambdas/Lists/Chain/src/ChainGET.java @@ -0,0 +1,11 @@ +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +import java.util.Map; + +public class ChainGET implements RequestHandler, Object> { + + public Object handleRequest(Map inputMap, Context unfilled) { + return BasicHandler.handleRequest(inputMap, unfilled, ChainGetter.class); + } +} diff --git a/Lambdas/Lists/Chain/src/ChainGetter.java b/Lambdas/Lists/Chain/src/ChainGetter.java new file mode 100644 index 0000000..f1775a0 --- /dev/null +++ b/Lambdas/Lists/Chain/src/ChainGetter.java @@ -0,0 +1,29 @@ +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; + +public class ChainGetter implements CallHandler { + private final Connection connection; + + private final String GET_CHAIN = "SELECT * FROM Chain WHERE chainID = ?;"; + + public ChainGetter(Connection connection, String cognitoID) { + this.connection = connection; + } + + @Override + public Object conductAction(Map bodyMap, HashMap queryMap, String cognitoID) throws SQLException { + PreparedStatement statement = connection.prepareStatement(GET_CHAIN); + statement.setInt(1, Integer.parseInt(queryMap.get("id"))); + System.out.println(statement); + ResultSet queryResults = statement.executeQuery(); + queryResults.first(); + System.out.println(queryResults); + Chain retrievedChain = new Chain(queryResults); + System.out.println(retrievedChain); + return retrievedChain; + } +} \ No newline at end of file diff --git a/Listify/app/src/main/java/com/example/listify/data/Chain.java b/Listify/app/src/main/java/com/example/listify/data/Chain.java new file mode 100644 index 0000000..cfd42c4 --- /dev/null +++ b/Listify/app/src/main/java/com/example/listify/data/Chain.java @@ -0,0 +1,27 @@ +package com.example.listify.data; + +public class Chain { + String name; + String website; + + public Chain(String name, String website) { + this.name = name; + this.website = website; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getWebsite() { + return website; + } + + public void setWebsite(String website) { + this.website = website; + } +} From 7412915034eb8b2d291678500695a3c527ed42b1 Mon Sep 17 00:00:00 2001 From: NMerz Date: Sun, 1 Nov 2020 21:48:05 -0500 Subject: [PATCH 11/12] Allow non-owner semi-delete Non-owners should be able to remove only their own access to a list --- Lambdas/Lists/List/src/ListDeleter.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Lambdas/Lists/List/src/ListDeleter.java b/Lambdas/Lists/List/src/ListDeleter.java index 0b71411..820f65f 100644 --- a/Lambdas/Lists/List/src/ListDeleter.java +++ b/Lambdas/Lists/List/src/ListDeleter.java @@ -12,6 +12,7 @@ public class ListDeleter implements CallHandler { private final String GET_LISTS = "SELECT * FROM List WHERE (owner = ? AND listID = ?);"; private final String DELETE_LIST = "DELETE FROM List WHERE listID = ?;"; + private final String DELETE_REQUESTOR_ACCESS = "DELETE FROM ListSharee where listID = ? AND userID = ?;"; private final String DELETE_LIST_ACCESS = "DELETE FROM ListSharee where listID = ?;"; private final String DELETE_LIST_ENTRIES = "DELETE FROM ListProduct where listID = ?;"; @@ -23,12 +24,17 @@ public class ListDeleter implements CallHandler { @Override public Object conductAction(Map bodyMap, HashMap queryMap, String cognitoID) throws SQLException { Integer listID = Integer.parseInt(queryMap.get("id")); + PreparedStatement cleanRequestorAccess = connection.prepareStatement(DELETE_REQUESTOR_ACCESS); + cleanRequestorAccess.setInt(1, listID); + cleanRequestorAccess.setString(2, cognitoID); + System.out.println(cleanRequestorAccess); + cleanRequestorAccess.executeUpdate(); + PreparedStatement accessCheck = connection.prepareStatement(GET_LISTS); accessCheck.setString(1, cognitoID); accessCheck.setInt(2, listID); System.out.println(accessCheck); ResultSet userLists = accessCheck.executeQuery(); - if (!userLists.next()) { throw new AccessControlException("User does not have access to list"); } From e58d28ea6a0717966802c23b754b24c6d9be2214 Mon Sep 17 00:00:00 2001 From: Clayton Wilson Date: Mon, 2 Nov 2020 00:55:57 -0500 Subject: [PATCH 12/12] Change list swipe direction --- .../src/main/res/layout/shopping_lists_swipeable_name_item.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Listify/app/src/main/res/layout/shopping_lists_swipeable_name_item.xml b/Listify/app/src/main/res/layout/shopping_lists_swipeable_name_item.xml index 2bba1d9..98f9613 100644 --- a/Listify/app/src/main/res/layout/shopping_lists_swipeable_name_item.xml +++ b/Listify/app/src/main/res/layout/shopping_lists_swipeable_name_item.xml @@ -5,7 +5,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" - app:dragEdge="right" + app:dragEdge="left" app:mode="same_level">