From c8c4df6ef753c33e4df5ec47b61a476eb455367a Mon Sep 17 00:00:00 2001 From: Alinson Xavier Date: Sat, 5 Mar 2016 07:30:04 -0500 Subject: [PATCH] Split ListHabitsFragment into smaller classes --- .../dialogs/HabitSelectionCallback.java | 268 +++++++++++++++++ .../isoron/uhabits/dialogs/HintManager.java | 78 +++++ .../uhabits/fragments/EditHabitFragment.java | 4 +- .../uhabits/fragments/ListHabitsFragment.java | 278 ++---------------- 4 files changed, 378 insertions(+), 250 deletions(-) create mode 100644 app/src/main/java/org/isoron/uhabits/dialogs/HabitSelectionCallback.java create mode 100644 app/src/main/java/org/isoron/uhabits/dialogs/HintManager.java diff --git a/app/src/main/java/org/isoron/uhabits/dialogs/HabitSelectionCallback.java b/app/src/main/java/org/isoron/uhabits/dialogs/HabitSelectionCallback.java new file mode 100644 index 000000000..2283ffb9d --- /dev/null +++ b/app/src/main/java/org/isoron/uhabits/dialogs/HabitSelectionCallback.java @@ -0,0 +1,268 @@ +/* Copyright (C) 2016 Alinson Santos Xavier + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.isoron.uhabits.dialogs; + +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.net.Uri; +import android.os.AsyncTask; +import android.view.ActionMode; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.ProgressBar; + +import com.android.colorpicker.ColorPickerDialog; +import com.android.colorpicker.ColorPickerSwatch; + +import org.isoron.helpers.ColorHelper; +import org.isoron.helpers.DialogHelper; +import org.isoron.helpers.ReplayableActivity; +import org.isoron.uhabits.R; +import org.isoron.uhabits.commands.ArchiveHabitsCommand; +import org.isoron.uhabits.commands.ChangeHabitColorCommand; +import org.isoron.uhabits.commands.DeleteHabitsCommand; +import org.isoron.uhabits.commands.UnarchiveHabitsCommand; +import org.isoron.uhabits.fragments.EditHabitFragment; +import org.isoron.uhabits.io.CSVExporter; +import org.isoron.uhabits.loaders.HabitListLoader; +import org.isoron.uhabits.models.Habit; + +import java.io.File; +import java.util.LinkedList; +import java.util.List; + +public class HabitSelectionCallback implements ActionMode.Callback +{ + private HabitListLoader loader; + private List selectedPositions; + private ReplayableActivity activity; + private Listener listener; + private DialogHelper.OnSavedListener onSavedListener; + private ProgressBar progressBar; + + public interface Listener + { + void onActionModeDestroyed(ActionMode mode); + } + + public HabitSelectionCallback(ReplayableActivity activity, HabitListLoader loader) + { + this.activity = activity; + this.loader = loader; + selectedPositions = new LinkedList<>(); + } + + public void setListener(Listener listener) + { + this.listener = listener; + } + + public void setProgressBar(ProgressBar progressBar) + { + this.progressBar = progressBar; + } + + public void setOnSavedListener(DialogHelper.OnSavedListener onSavedListener) + { + this.onSavedListener = onSavedListener; + } + + public void setSelectedPositions(List selectedPositions) + { + this.selectedPositions = selectedPositions; + } + + @Override + public boolean onCreateActionMode(ActionMode mode, Menu menu) + { + activity.getMenuInflater().inflate(R.menu.list_habits_context, menu); + updateTitle(mode); + updateActions(menu); + return true; + } + + @Override + public boolean onPrepareActionMode(ActionMode mode, Menu menu) + { + updateTitle(mode); + updateActions(menu); + return true; + } + + private void updateActions(Menu menu) + { + boolean showEdit = (selectedPositions.size() == 1); + boolean showColor = true; + boolean showArchive = true; + boolean showUnarchive = true; + + if (showEdit) showColor = false; + for (int i : selectedPositions) + { + Habit h = loader.habitsList.get(i); + if (h.isArchived()) + { + showColor = false; + showArchive = false; + } + else showUnarchive = false; + } + + MenuItem itemEdit = menu.findItem(R.id.action_edit_habit); + MenuItem itemColor = menu.findItem(R.id.action_color); + MenuItem itemArchive = menu.findItem(R.id.action_archive_habit); + MenuItem itemUnarchive = menu.findItem(R.id.action_unarchive_habit); + + itemEdit.setVisible(showEdit); + itemColor.setVisible(showColor); + itemArchive.setVisible(showArchive); + itemUnarchive.setVisible(showUnarchive); + } + + private void updateTitle(ActionMode mode) + { + mode.setTitle("" + selectedPositions.size()); + } + + @Override + public boolean onActionItemClicked(final ActionMode mode, MenuItem item) + { + final LinkedList selectedHabits = new LinkedList<>(); + for (int i : selectedPositions) + selectedHabits.add(loader.habitsList.get(i)); + + Habit firstHabit = selectedHabits.getFirst(); + + switch (item.getItemId()) + { + case R.id.action_archive_habit: + activity.executeCommand(new ArchiveHabitsCommand(selectedHabits), null); + mode.finish(); + return true; + + case R.id.action_unarchive_habit: + activity.executeCommand(new UnarchiveHabitsCommand(selectedHabits), null); + mode.finish(); + return true; + + case R.id.action_edit_habit: + { + EditHabitFragment frag = EditHabitFragment.editSingleHabitFragment(firstHabit.getId()); + frag.setOnSavedListener(onSavedListener); + frag.show(activity.getFragmentManager(), "dialog"); + return true; + } + + case R.id.action_color: + { + ColorPickerDialog picker = ColorPickerDialog.newInstance(R.string.color_picker_default_title, + ColorHelper.palette, firstHabit.color, 4, ColorPickerDialog.SIZE_SMALL); + + picker.setOnColorSelectedListener(new ColorPickerSwatch.OnColorSelectedListener() + { + public void onColorSelected(int color) + { + activity.executeCommand( + new ChangeHabitColorCommand(selectedHabits, color), null); + mode.finish(); + } + }); + picker.show(activity.getFragmentManager(), "picker"); + return true; + } + + case R.id.action_delete: + { + new AlertDialog.Builder(activity).setTitle(R.string.delete_habits) + .setMessage(R.string.delete_habits_message) + .setPositiveButton(android.R.string.yes, + new DialogInterface.OnClickListener() + { + @Override + public void onClick(DialogInterface dialog, int which) + { + activity.executeCommand( + new DeleteHabitsCommand(selectedHabits), null); + mode.finish(); + } + }).setNegativeButton(android.R.string.no, null) + .show(); + + return true; + } + + case R.id.action_export_csv: + { + onExportHabitsClick(selectedHabits); + return true; + } + } + + return false; + } + + @Override + public void onDestroyActionMode(ActionMode mode) + { + if(listener != null) listener.onActionModeDestroyed(mode); + } + + private void onExportHabitsClick(final LinkedList selectedHabits) + { + new AsyncTask() + { + String filename; + + @Override + protected void onPreExecute() + { + if(progressBar != null) + { + progressBar.setIndeterminate(true); + progressBar.setVisibility(View.VISIBLE); + } + } + + @Override + protected void onPostExecute(Void aVoid) + { + if(filename != null) + { + Intent intent = new Intent(); + intent.setAction(Intent.ACTION_SEND); + intent.setType("application/zip"); + intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(filename))); + + activity.startActivity(intent); + } + + if(progressBar != null) + progressBar.setVisibility(View.GONE); + } + + @Override + protected Void doInBackground(Void... params) + { + CSVExporter exporter = new CSVExporter(activity, selectedHabits); + filename = exporter.writeArchive(); + return null; + } + }.execute(); + } +} diff --git a/app/src/main/java/org/isoron/uhabits/dialogs/HintManager.java b/app/src/main/java/org/isoron/uhabits/dialogs/HintManager.java new file mode 100644 index 000000000..eee95a27d --- /dev/null +++ b/app/src/main/java/org/isoron/uhabits/dialogs/HintManager.java @@ -0,0 +1,78 @@ +/* Copyright (C) 2016 Alinson Santos Xavier + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.isoron.uhabits.dialogs; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.content.Context; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import android.view.View; +import android.widget.TextView; + +import org.isoron.helpers.DateHelper; +import org.isoron.uhabits.R; + +public class HintManager +{ + private Context context; + private SharedPreferences prefs; + private View hintView; + + public HintManager(Context context, View hintView) + { + this.context = context; + this.hintView = hintView; + prefs = PreferenceManager.getDefaultSharedPreferences(context); + } + + public void dismissHint() + { + hintView.animate().alpha(0f).setDuration(500).setListener(new AnimatorListenerAdapter() + { + @Override + public void onAnimationEnd(Animator animation) + { + hintView.setVisibility(View.GONE); + } + }); + } + + public void showHintIfAppropriate() + { + Integer lastHintNumber = prefs.getInt("last_hint_number", -1); + Long lastHintTimestamp = prefs.getLong("last_hint_timestamp", -1); + + if (DateHelper.getStartOfToday() > lastHintTimestamp) showHint(lastHintNumber + 1); + } + + private void showHint(int hintNumber) + { + String[] hints = context.getResources().getStringArray(R.array.hints); + if (hintNumber >= hints.length) return; + + prefs.edit().putInt("last_hint_number", hintNumber).apply(); + prefs.edit().putLong("last_hint_timestamp", DateHelper.getStartOfToday()).apply(); + + TextView tvContent = (TextView) hintView.findViewById(R.id.hintContent); + tvContent.setText(hints[hintNumber]); + + hintView.setAlpha(0.0f); + hintView.setVisibility(View.VISIBLE); + hintView.animate().alpha(1f).setDuration(500); + } +} diff --git a/app/src/main/java/org/isoron/uhabits/fragments/EditHabitFragment.java b/app/src/main/java/org/isoron/uhabits/fragments/EditHabitFragment.java index 84bbf4822..cef7fa916 100644 --- a/app/src/main/java/org/isoron/uhabits/fragments/EditHabitFragment.java +++ b/app/src/main/java/org/isoron/uhabits/fragments/EditHabitFragment.java @@ -70,7 +70,7 @@ public class EditHabitFragment extends DialogFragment private SharedPreferences prefs; private boolean is24HourMode; - static EditHabitFragment editSingleHabitFragment(long id) + public static EditHabitFragment editSingleHabitFragment(long id) { EditHabitFragment frag = new EditHabitFragment(); Bundle args = new Bundle(); @@ -80,7 +80,7 @@ public class EditHabitFragment extends DialogFragment return frag; } - static EditHabitFragment createHabitFragment() + public static EditHabitFragment createHabitFragment() { EditHabitFragment frag = new EditHabitFragment(); Bundle args = new Bundle(); diff --git a/app/src/main/java/org/isoron/uhabits/fragments/ListHabitsFragment.java b/app/src/main/java/org/isoron/uhabits/fragments/ListHabitsFragment.java index 278e54345..e94a2d3e4 100644 --- a/app/src/main/java/org/isoron/uhabits/fragments/ListHabitsFragment.java +++ b/app/src/main/java/org/isoron/uhabits/fragments/ListHabitsFragment.java @@ -16,19 +16,12 @@ package org.isoron.uhabits.fragments; -import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; import android.app.Activity; -import android.app.AlertDialog; import android.app.Fragment; import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Color; import android.graphics.Typeface; -import android.net.Uri; -import android.os.AsyncTask; import android.os.Bundle; import android.preference.PreferenceManager; import android.util.DisplayMetrics; @@ -53,31 +46,24 @@ import android.widget.LinearLayout.LayoutParams; import android.widget.ProgressBar; import android.widget.TextView; -import com.android.colorpicker.ColorPickerDialog; -import com.android.colorpicker.ColorPickerSwatch; import com.mobeta.android.dslv.DragSortController; import com.mobeta.android.dslv.DragSortListView; import com.mobeta.android.dslv.DragSortListView.DropListener; -import org.isoron.helpers.ColorHelper; import org.isoron.helpers.Command; import org.isoron.helpers.DateHelper; import org.isoron.helpers.DialogHelper; import org.isoron.helpers.DialogHelper.OnSavedListener; import org.isoron.helpers.ReplayableActivity; import org.isoron.uhabits.R; -import org.isoron.uhabits.commands.ArchiveHabitsCommand; -import org.isoron.uhabits.commands.ChangeHabitColorCommand; -import org.isoron.uhabits.commands.DeleteHabitsCommand; import org.isoron.uhabits.commands.ToggleRepetitionCommand; -import org.isoron.uhabits.commands.UnarchiveHabitsCommand; +import org.isoron.uhabits.dialogs.HabitSelectionCallback; +import org.isoron.uhabits.dialogs.HintManager; import org.isoron.uhabits.helpers.ReminderHelper; -import org.isoron.uhabits.io.CSVExporter; import org.isoron.uhabits.loaders.HabitListLoader; import org.isoron.uhabits.models.Habit; import org.isoron.uhabits.models.Score; -import java.io.File; import java.util.Date; import java.util.GregorianCalendar; import java.util.LinkedList; @@ -85,156 +71,13 @@ import java.util.List; public class ListHabitsFragment extends Fragment implements OnSavedListener, OnItemClickListener, OnLongClickListener, DropListener, - OnClickListener, HabitListLoader.Listener, AdapterView.OnItemLongClickListener + OnClickListener, HabitListLoader.Listener, AdapterView.OnItemLongClickListener, + HabitSelectionCallback.Listener { - private class ListHabitsActionBarCallback implements ActionMode.Callback - { - @Override - public boolean onCreateActionMode(ActionMode mode, Menu menu) - { - getActivity().getMenuInflater().inflate(R.menu.list_habits_context, menu); - updateTitle(mode); - updateActions(menu); - return true; - } - - @Override - public boolean onPrepareActionMode(ActionMode mode, Menu menu) - { - updateTitle(mode); - updateActions(menu); - return true; - } - - private void updateActions(Menu menu) - { - boolean showEdit = (selectedPositions.size() == 1); - boolean showColor = true; - boolean showArchive = true; - boolean showUnarchive = true; - - if(showEdit) showColor = false; - for(int i : selectedPositions) - { - Habit h = loader.habitsList.get(i); - if(h.isArchived()) - { - showColor = false; - showArchive = false; - } - else showUnarchive = false; - } - - MenuItem itemEdit = menu.findItem(R.id.action_edit_habit); - MenuItem itemColor = menu.findItem(R.id.action_color); - MenuItem itemArchive = menu.findItem(R.id.action_archive_habit); - MenuItem itemUnarchive = menu.findItem(R.id.action_unarchive_habit); - - itemEdit.setVisible(showEdit); - itemColor.setVisible(showColor); - itemArchive.setVisible(showArchive); - itemUnarchive.setVisible(showUnarchive); - } - - private void updateTitle(ActionMode mode) - { - mode.setTitle("" + selectedPositions.size()); - } - - @Override - public boolean onActionItemClicked(final ActionMode mode, MenuItem item) - { - final LinkedList selectedHabits = new LinkedList<>(); - for(int i : selectedPositions) - selectedHabits.add(loader.habitsList.get(i)); - - Habit firstHabit = selectedHabits.getFirst(); - - switch(item.getItemId()) - { - case R.id.action_archive_habit: - executeCommand(new ArchiveHabitsCommand(selectedHabits), null); - mode.finish(); - return true; - - case R.id.action_unarchive_habit: - executeCommand(new UnarchiveHabitsCommand(selectedHabits), null); - mode.finish(); - return true; - - case R.id.action_edit_habit: - { - EditHabitFragment frag = EditHabitFragment.editSingleHabitFragment(firstHabit.getId()); - frag.setOnSavedListener(ListHabitsFragment.this); - frag.show(getFragmentManager(), "dialog"); - return true; - } - - case R.id.action_color: - { - ColorPickerDialog picker = ColorPickerDialog.newInstance( - R.string.color_picker_default_title, ColorHelper.palette, - firstHabit.color, 4, ColorPickerDialog.SIZE_SMALL); - - picker.setOnColorSelectedListener(new ColorPickerSwatch.OnColorSelectedListener() - { - public void onColorSelected(int color) - { - executeCommand(new ChangeHabitColorCommand(selectedHabits, color), null); - mode.finish(); - } - }); - picker.show(getFragmentManager(), "picker"); - return true; - } - - case R.id.action_delete: - { - new AlertDialog.Builder(activity) - .setTitle(R.string.delete_habits) - .setMessage(R.string.delete_habits_message) - .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() - { - @Override - public void onClick(DialogInterface dialog, int which) - { - executeCommand(new DeleteHabitsCommand(selectedHabits), null); - mode.finish(); - } - }).setNegativeButton(android.R.string.no, null) - .show(); - - return true; - } - - case R.id.action_export_csv: - { - onExportHabitsClick(selectedHabits); - return true; - } - } - - return false; - } - - @Override - public void onDestroyActionMode(ActionMode mode) - { - actionMode = null; - - selectedPositions.clear(); - adapter.notifyDataSetChanged(); - - listView.setDragEnabled(true); - } - } public static final int INACTIVE_COLOR = Color.rgb(200, 200, 200); public static final int INACTIVE_CHECKMARK_COLOR = Color.rgb(230, 230, 230); - public static final int HINT_INTERVAL = 5; - public static final int HINT_INTERVAL_OFFSET = 2; - public interface OnHabitClickListener { void onHabitClicked(Habit habit); @@ -249,7 +92,6 @@ public class ListHabitsFragment extends Fragment private int tvNameWidth; private int buttonCount; private View llEmpty; - private View llHint; private OnHabitClickListener habitClickListener; private boolean isShortToggleEnabled; @@ -260,9 +102,10 @@ public class ListHabitsFragment extends Fragment private ActionMode actionMode; private List selectedPositions; - private DragSortController dragSortController; private ProgressBar progressBar; + private HintManager hintManager; + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) @@ -302,26 +145,29 @@ public class ListHabitsFragment extends Fragment } }); - dragSortController = new DragSortController(listView) { - @Override - public View onCreateFloatView(int position) - { - return adapter.getView(position, null, null); - } + DragSortController dragSortController = new DragSortController(listView) + { + @Override + public View onCreateFloatView(int position) + { + return adapter.getView(position, null, null); + } @Override public void onDestroyFloatView(View floatView) { } }; + dragSortController.setRemoveEnabled(false); listView.setFloatViewManager(dragSortController); listView.setDragEnabled(true); listView.setLongClickable(true); - llHint = view.findViewById(R.id.llHint); + View llHint = view.findViewById(R.id.llHint); llHint.setOnClickListener(this); + hintManager = new HintManager(activity, llHint); Typeface fontawesome = Typeface.createFromAsset(getActivity().getAssets(), "fontawesome-webfont.ttf"); @@ -332,7 +178,6 @@ public class ListHabitsFragment extends Fragment setHasOptionsMenu(true); selectedPositions = new LinkedList<>(); - return view; } @@ -358,7 +203,7 @@ public class ListHabitsFragment extends Fragment updateEmptyMessage(); updateHeader(); - showNextHint(); + hintManager.showHintIfAppropriate(); adapter.notifyDataSetChanged(); isShortToggleEnabled = prefs.getBoolean("pref_short_toggle", false); @@ -485,8 +330,13 @@ public class ListHabitsFragment extends Fragment if(actionMode == null) { - actionMode = getActivity().startActionMode(new ListHabitsActionBarCallback()); -// listView.setDragEnabled(false); + HabitSelectionCallback callback = new HabitSelectionCallback(activity, loader); + callback.setSelectedPositions(selectedPositions); + callback.setProgressBar(progressBar); + callback.setOnSavedListener(this); + callback.setListener(this); + + actionMode = getActivity().startActionMode(callback); } if(actionMode != null) actionMode.invalidate(); @@ -555,43 +405,6 @@ public class ListHabitsFragment extends Fragment activity.executeCommand(c, refreshKey); } - private void hideHint() - { - llHint.animate().alpha(0f).setDuration(500).setListener(new AnimatorListenerAdapter() - { - @Override - public void onAnimationEnd(Animator animation) - { - llHint.setVisibility(View.GONE); - } - }); - } - - private void showNextHint() - { - Integer lastHintNumber = prefs.getInt("last_hint_number", -1); - Long lastHintTimestamp = prefs.getLong("last_hint_timestamp", -1); - - if(DateHelper.getStartOfToday() > lastHintTimestamp) - showHint(lastHintNumber + 1); - } - - private void showHint(int hintNumber) - { - String[] hints = activity.getResources().getStringArray(R.array.hints); - if(hintNumber >= hints.length) return; - - prefs.edit().putInt("last_hint_number", hintNumber).apply(); - prefs.edit().putLong("last_hint_timestamp", DateHelper.getStartOfToday()).apply(); - - TextView tvContent = (TextView) llHint.findViewById(R.id.hintContent); - tvContent.setText(hints[hintNumber]); - - llHint.setAlpha(0.0f); - llHint.setVisibility(View.VISIBLE); - llHint.animate().alpha(1f).setDuration(500); - } - @Override public void drop(int from, int to) { @@ -614,7 +427,7 @@ public class ListHabitsFragment extends Fragment break; case R.id.llHint: - hideHint(); + hintManager.dismissHint(); break; } } @@ -798,42 +611,11 @@ public class ListHabitsFragment extends Fragment else loader.updateHabit(refreshKey); } - private void onExportHabitsClick(final LinkedList selectedHabits) + public void onActionModeDestroyed(ActionMode mode) { - new AsyncTask() - { - String filename; - - @Override - protected void onPreExecute() - { - progressBar.setIndeterminate(true); - progressBar.setVisibility(View.VISIBLE); - } - - @Override - protected void onPostExecute(Void aVoid) - { - if(filename != null) - { - Intent intent = new Intent(); - intent.setAction(Intent.ACTION_SEND); - intent.setType("application/zip"); - intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(filename))); - - startActivity(intent); - } - - progressBar.setVisibility(View.GONE); - } - - @Override - protected Void doInBackground(Void... params) - { - CSVExporter exporter = new CSVExporter(activity, selectedHabits); - filename = exporter.writeArchive(); - return null; - } - }.execute(); + actionMode = null; + selectedPositions.clear(); + adapter.notifyDataSetChanged(); + listView.setDragEnabled(true); } }