diff --git a/app/src/main/java/org/isoron/uhabits/HabitBroadcastReceiver.java b/app/src/main/java/org/isoron/uhabits/HabitBroadcastReceiver.java index 455d41a15..c923b4e34 100644 --- a/app/src/main/java/org/isoron/uhabits/HabitBroadcastReceiver.java +++ b/app/src/main/java/org/isoron/uhabits/HabitBroadcastReceiver.java @@ -36,6 +36,8 @@ import android.support.v4.app.NotificationCompat; import android.support.v4.app.TaskStackBuilder; import android.support.v4.content.LocalBroadcastManager; +import org.isoron.uhabits.commands.CommandRunner; +import org.isoron.uhabits.commands.ToggleRepetitionCommand; import org.isoron.uhabits.utils.DateUtils; import org.isoron.uhabits.utils.ReminderUtils; import org.isoron.uhabits.models.Checkmark; @@ -115,9 +117,12 @@ public class HabitBroadcastReceiver extends BroadcastReceiver long habitId = ContentUris.parseId(data); Habit habit = Habit.get(habitId); if(habit != null) - habit.repetitions.toggle(timestamp); - dismissNotification(context, habitId); + { + ToggleRepetitionCommand command = new ToggleRepetitionCommand(habit, timestamp); + CommandRunner.getInstance().execute(command, habitId); + } + dismissNotification(context, habitId); sendRefreshBroadcast(context); } diff --git a/app/src/main/java/org/isoron/uhabits/MainActivity.java b/app/src/main/java/org/isoron/uhabits/MainActivity.java index 8d425572a..1655c4de2 100644 --- a/app/src/main/java/org/isoron/uhabits/MainActivity.java +++ b/app/src/main/java/org/isoron/uhabits/MainActivity.java @@ -19,7 +19,6 @@ package org.isoron.uhabits; -import android.content.Context; import android.content.Intent; import android.graphics.drawable.ColorDrawable; import android.net.Uri; @@ -31,21 +30,18 @@ import android.support.v7.app.ActionBar; import android.view.Menu; import android.view.MenuItem; -import org.isoron.uhabits.models.Checkmark; import org.isoron.uhabits.models.Habit; -import org.isoron.uhabits.tasks.BaseTask; import org.isoron.uhabits.tasks.ProgressBar; -import org.isoron.uhabits.ui.about.AboutActivity; import org.isoron.uhabits.ui.AndroidProgressBar; import org.isoron.uhabits.ui.BaseActivity; -import org.isoron.uhabits.ui.intro.IntroActivity; +import org.isoron.uhabits.ui.about.AboutActivity; import org.isoron.uhabits.ui.habits.list.ListHabitsFragment; +import org.isoron.uhabits.ui.habits.show.ShowHabitActivity; +import org.isoron.uhabits.ui.intro.IntroActivity; import org.isoron.uhabits.ui.settings.FilePickerDialog; import org.isoron.uhabits.ui.settings.SettingsActivity; -import org.isoron.uhabits.ui.habits.show.ShowHabitActivity; import org.isoron.uhabits.utils.FileUtils; import org.isoron.uhabits.utils.InterfaceUtils; -import org.isoron.uhabits.widgets.WidgetManager; import java.io.File; @@ -196,31 +192,6 @@ public class MainActivity extends BaseActivity showHabitScreen(habit); } - @Override - public void onPostExecuteCommand(Long refreshKey) - { - listHabitsFragment.onPostExecuteCommand(refreshKey); - - new BaseTask() - { - @Override - protected void doInBackground() - { - dismissNotifications(MainActivity.this); - WidgetManager.updateWidgets(MainActivity.this); - } - }.execute(); - } - - private void dismissNotifications(Context context) - { - for(Habit h : Habit.getHabitsWithReminder()) - { - if(h.checkmarks.getTodayValue() != Checkmark.UNCHECKED) - HabitBroadcastReceiver.dismissNotification(context, h); - } - } - private void showHabitScreen(Habit habit) { Intent intent = new Intent(this, ShowHabitActivity.class); diff --git a/app/src/main/java/org/isoron/uhabits/commands/CommandRunner.java b/app/src/main/java/org/isoron/uhabits/commands/CommandRunner.java new file mode 100644 index 000000000..05d541dbc --- /dev/null +++ b/app/src/main/java/org/isoron/uhabits/commands/CommandRunner.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2016 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker 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. + * + * Loop Habit Tracker 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.commands; + +import org.isoron.uhabits.tasks.BaseTask; + +import java.util.LinkedList; + +public class CommandRunner +{ + public interface Listener + { + void onCommandExecuted(Command command, Long refreshKey); + } + + private static CommandRunner singleton; + private LinkedList listeners; + + private CommandRunner() + { + listeners = new LinkedList<>(); + } + + public static CommandRunner getInstance() + { + if(singleton == null) singleton = new CommandRunner(); + return singleton; + } + + public void execute(final Command command, final Long refreshKey) + { + new BaseTask() + { + @Override + protected void doInBackground() + { + command.execute(); + } + + @Override + protected void onPostExecute(Void aVoid) + { + for(Listener l : listeners) + l.onCommandExecuted(command, refreshKey); + } + }.execute(); + } + + public void addListener(Listener l) + { + listeners.add(l); + } + + public void removeListener(Listener l) + { + listeners.remove(l); + } +} diff --git a/app/src/main/java/org/isoron/uhabits/models/CheckmarkList.java b/app/src/main/java/org/isoron/uhabits/models/CheckmarkList.java index 7c949491b..c0306cdb3 100644 --- a/app/src/main/java/org/isoron/uhabits/models/CheckmarkList.java +++ b/app/src/main/java/org/isoron/uhabits/models/CheckmarkList.java @@ -41,6 +41,7 @@ import java.util.List; public class CheckmarkList { private Habit habit; + public ModelObservable observable = new ModelObservable(); public CheckmarkList(Habit habit) { @@ -59,6 +60,8 @@ public class CheckmarkList .where("habit = ?", habit.getId()) .and("timestamp >= ?", timestamp) .execute(); + + observable.notifyListeners(); } /** diff --git a/app/src/main/java/org/isoron/uhabits/models/Habit.java b/app/src/main/java/org/isoron/uhabits/models/Habit.java index 3751996cd..8752fbb1f 100644 --- a/app/src/main/java/org/isoron/uhabits/models/Habit.java +++ b/app/src/main/java/org/isoron/uhabits/models/Habit.java @@ -147,6 +147,8 @@ public class Habit extends Model @NonNull public CheckmarkList checkmarks; + public ModelObservable observable = new ModelObservable(); + /** * Constructs a habit with the same attributes as the specified habit. * @@ -348,6 +350,8 @@ public class Habit extends Model this.reminderDays = model.reminderDays; this.highlight = model.highlight; this.archived = model.archived; + + observable.notifyListeners(); } /** @@ -424,6 +428,8 @@ public class Habit extends Model finally { ActiveAndroid.endTransaction(); + for(Habit h : habits) + h.observable.notifyListeners(); } } @@ -456,6 +462,8 @@ public class Habit extends Model public static void setColor(@NonNull List habits, int color) { updateAttributes(habits, color, null); + for(Habit h : habits) + h.observable.notifyListeners(); } /** @@ -476,6 +484,7 @@ public class Habit extends Model reminderHour = null; reminderMin = null; reminderDays = DateUtils.ALL_WEEK_DAYS; + observable.notifyListeners(); } /** diff --git a/app/src/main/java/org/isoron/uhabits/models/RepetitionList.java b/app/src/main/java/org/isoron/uhabits/models/RepetitionList.java index 1e4227e9f..f9766645d 100644 --- a/app/src/main/java/org/isoron/uhabits/models/RepetitionList.java +++ b/app/src/main/java/org/isoron/uhabits/models/RepetitionList.java @@ -41,6 +41,7 @@ public class RepetitionList { @NonNull private Habit habit; + public ModelObservable observable = new ModelObservable(); public RepetitionList(@NonNull Habit habit) { @@ -105,6 +106,7 @@ public class RepetitionList habit.scores.invalidateNewerThan(timestamp); habit.checkmarks.deleteNewerThan(timestamp); habit.streaks.deleteNewerThan(timestamp); + observable.notifyListeners(); } private void insert(long timestamp) diff --git a/app/src/main/java/org/isoron/uhabits/models/ScoreList.java b/app/src/main/java/org/isoron/uhabits/models/ScoreList.java index b207b130c..e49ec56ca 100644 --- a/app/src/main/java/org/isoron/uhabits/models/ScoreList.java +++ b/app/src/main/java/org/isoron/uhabits/models/ScoreList.java @@ -44,6 +44,7 @@ public class ScoreList { @NonNull private Habit habit; + public ModelObservable observable = new ModelObservable(); /** * Constructs a new ScoreList associated with the given habit. @@ -75,6 +76,8 @@ public class ScoreList .where("habit = ?", habit.getId()) .and("timestamp >= ?", timestamp) .execute(); + + observable.notifyListeners(); } /** diff --git a/app/src/main/java/org/isoron/uhabits/models/StreakList.java b/app/src/main/java/org/isoron/uhabits/models/StreakList.java index a47409ef1..523b9e339 100644 --- a/app/src/main/java/org/isoron/uhabits/models/StreakList.java +++ b/app/src/main/java/org/isoron/uhabits/models/StreakList.java @@ -37,6 +37,7 @@ import java.util.List; public class StreakList { private Habit habit; + public ModelObservable observable = new ModelObservable(); public StreakList(Habit habit) { @@ -156,5 +157,7 @@ public class StreakList .where("habit = ?", habit.getId()) .and("end >= ?", timestamp - DateUtils.millisecondsInOneDay) .execute(); + + observable.notifyListeners(); } } diff --git a/app/src/main/java/org/isoron/uhabits/tasks/ToggleRepetitionTask.java b/app/src/main/java/org/isoron/uhabits/tasks/ToggleRepetitionTask.java index 3b46ec95c..828656eb3 100644 --- a/app/src/main/java/org/isoron/uhabits/tasks/ToggleRepetitionTask.java +++ b/app/src/main/java/org/isoron/uhabits/tasks/ToggleRepetitionTask.java @@ -19,6 +19,8 @@ package org.isoron.uhabits.tasks; +import org.isoron.uhabits.commands.CommandRunner; +import org.isoron.uhabits.commands.ToggleRepetitionCommand; import org.isoron.uhabits.models.Habit; public class ToggleRepetitionTask extends BaseTask @@ -40,7 +42,8 @@ public class ToggleRepetitionTask extends BaseTask @Override protected void doInBackground() { - habit.repetitions.toggle(timestamp); + ToggleRepetitionCommand command = new ToggleRepetitionCommand(habit, timestamp); + CommandRunner.getInstance().execute(command, habit.getId()); } @Override diff --git a/app/src/main/java/org/isoron/uhabits/ui/BaseActivity.java b/app/src/main/java/org/isoron/uhabits/ui/BaseActivity.java index d8d6f26e9..e7ed2471b 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/BaseActivity.java +++ b/app/src/main/java/org/isoron/uhabits/ui/BaseActivity.java @@ -20,9 +20,9 @@ package org.isoron.uhabits.ui; import android.app.backup.BackupManager; +import android.content.Context; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; -import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.support.v7.app.ActionBar; @@ -31,20 +31,21 @@ import android.support.v7.widget.Toolbar; import android.view.View; import android.widget.Toast; +import org.isoron.uhabits.HabitBroadcastReceiver; import org.isoron.uhabits.HabitsApplication; import org.isoron.uhabits.R; import org.isoron.uhabits.commands.Command; +import org.isoron.uhabits.commands.CommandRunner; +import org.isoron.uhabits.models.Checkmark; +import org.isoron.uhabits.models.Habit; +import org.isoron.uhabits.tasks.BaseTask; import org.isoron.uhabits.utils.ColorUtils; import org.isoron.uhabits.utils.InterfaceUtils; +import org.isoron.uhabits.widgets.WidgetManager; -import java.util.LinkedList; - -abstract public class BaseActivity extends AppCompatActivity implements Thread.UncaughtExceptionHandler +abstract public class BaseActivity extends AppCompatActivity implements Thread.UncaughtExceptionHandler, + CommandRunner.Listener { - private static int MAX_UNDO_LEVEL = 15; - - private LinkedList undoList; - private LinkedList redoList; private Toast toast; Thread.UncaughtExceptionHandler androidExceptionHandler; @@ -58,39 +59,20 @@ abstract public class BaseActivity extends AppCompatActivity implements Thread.U androidExceptionHandler = Thread.getDefaultUncaughtExceptionHandler(); Thread.setDefaultUncaughtExceptionHandler(this); - - undoList = new LinkedList<>(); - redoList = new LinkedList<>(); } - public void executeCommand(Command command, Long refreshKey) + @Override + protected void onResume() { - executeCommand(command, false, refreshKey); + super.onResume(); + CommandRunner.getInstance().addListener(this); } - protected void undo() - { - if (undoList.isEmpty()) - { - showMessage(R.string.toast_nothing_to_undo); - return; - } - - Command last = undoList.pop(); - redoList.push(last); - last.undo(); - showMessage(last.getUndoStringId()); - } - - protected void redo() + @Override + protected void onPause() { - if (redoList.isEmpty()) - { - showMessage(R.string.toast_nothing_to_redo); - return; - } - Command last = redoList.pop(); - executeCommand(last, false, null); + CommandRunner.getInstance().removeListener(this); + super.onPause(); } public void showMessage(Integer stringId) @@ -101,34 +83,6 @@ abstract public class BaseActivity extends AppCompatActivity implements Thread.U toast.show(); } - public void executeCommand(final Command command, Boolean clearRedoStack, final Long refreshKey) - { - undoList.push(command); - - if (undoList.size() > MAX_UNDO_LEVEL) undoList.removeLast(); - if (clearRedoStack) redoList.clear(); - - new AsyncTask() - { - @Override - protected Void doInBackground(Void... params) - { - command.execute(); - return null; - } - - @Override - protected void onPostExecute(Void aVoid) - { - BaseActivity.this.onPostExecuteCommand(refreshKey); - BackupManager.dataChanged("org.isoron.uhabits"); - } - }.execute(); - - - showMessage(command.getExecuteStringId()); - } - protected void setupSupportActionBar(boolean homeButtonEnabled) { Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); @@ -146,10 +100,6 @@ abstract public class BaseActivity extends AppCompatActivity implements Thread.U actionBar.setDisplayHomeAsUpEnabled(true); } - public void onPostExecuteCommand(Long refreshKey) - { - } - @Override public void uncaughtException(Thread thread, Throwable ex) { @@ -203,4 +153,29 @@ abstract public class BaseActivity extends AppCompatActivity implements Thread.U view = findViewById(R.id.headerShadow); if(view != null) view.setVisibility(View.GONE); } + + private void dismissNotifications(Context context) + { + for(Habit h : Habit.getHabitsWithReminder()) + { + if(h.checkmarks.getTodayValue() != Checkmark.UNCHECKED) + HabitBroadcastReceiver.dismissNotification(context, h); + } + } + + @Override + public void onCommandExecuted(Command command, Long refreshKey) + { + showMessage(command.getExecuteStringId()); + new BaseTask() + { + @Override + protected void doInBackground() + { + dismissNotifications(BaseActivity.this); + BackupManager.dataChanged("org.isoron.uhabits"); + WidgetManager.updateWidgets(BaseActivity.this); + } + }.execute(); + } } diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/edit/EditHabitDialogFragment.java b/app/src/main/java/org/isoron/uhabits/ui/habits/edit/EditHabitDialogFragment.java index b70b2ce2b..9a84b84b3 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/habits/edit/EditHabitDialogFragment.java +++ b/app/src/main/java/org/isoron/uhabits/ui/habits/edit/EditHabitDialogFragment.java @@ -42,12 +42,12 @@ import com.android.datetimepicker.time.TimePickerDialog; import org.isoron.uhabits.R; import org.isoron.uhabits.commands.Command; +import org.isoron.uhabits.commands.CommandRunner; import org.isoron.uhabits.commands.CreateHabitCommand; import org.isoron.uhabits.commands.EditHabitCommand; -import org.isoron.uhabits.utils.DateUtils; import org.isoron.uhabits.models.Habit; import org.isoron.uhabits.utils.ColorUtils; -import org.isoron.uhabits.utils.InterfaceUtils; +import org.isoron.uhabits.utils.DateUtils; import java.util.Arrays; @@ -59,8 +59,6 @@ public class EditHabitDialogFragment extends AppCompatDialogFragment static final int EDIT_MODE = 0; static final int CREATE_MODE = 1; - private InterfaceUtils.OnSavedListener onSavedListener; - private Habit originalHabit; private Habit modifiedHabit; @@ -202,11 +200,6 @@ public class EditHabitDialogFragment extends AppCompatDialogFragment } } - public void setOnSavedListener(InterfaceUtils.OnSavedListener onSavedListener) - { - this.onSavedListener = onSavedListener; - } - @Override public void onClick(View v) { @@ -264,21 +257,17 @@ public class EditHabitDialogFragment extends AppCompatDialogFragment if (!validate()) return; - Command command = null; - Habit savedHabit = null; - if (mode == EDIT_MODE) { - command = new EditHabitCommand(originalHabit, modifiedHabit); - savedHabit = originalHabit; + Command command = new EditHabitCommand(originalHabit, modifiedHabit); + CommandRunner.getInstance().execute(command, originalHabit.getId()); } else if (mode == CREATE_MODE) { - command = new CreateHabitCommand(modifiedHabit); + Command command = new CreateHabitCommand(modifiedHabit); + CommandRunner.getInstance().execute(command, null); } - if (onSavedListener != null) onSavedListener.onSaved(command, savedHabit); - dismiss(); } diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/list/HabitListLoader.java b/app/src/main/java/org/isoron/uhabits/ui/habits/list/HabitListLoader.java index 496d336d4..d80b178fa 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/habits/list/HabitListLoader.java +++ b/app/src/main/java/org/isoron/uhabits/ui/habits/list/HabitListLoader.java @@ -21,6 +21,8 @@ package org.isoron.uhabits.ui.habits.list; import android.support.annotation.Nullable; +import org.isoron.uhabits.commands.Command; +import org.isoron.uhabits.commands.CommandRunner; import org.isoron.uhabits.utils.DateUtils; import org.isoron.uhabits.models.Habit; import org.isoron.uhabits.tasks.BaseTask; @@ -28,7 +30,7 @@ import org.isoron.uhabits.tasks.BaseTask; import java.util.HashMap; import java.util.List; -public class HabitListLoader +public class HabitListLoader implements CommandRunner.Listener { public interface Listener { @@ -201,4 +203,21 @@ public class HabitListLoader } }.execute(); } + + public void onResume() + { + CommandRunner.getInstance().addListener(this); + } + + public void onPause() + { + CommandRunner.getInstance().removeListener(this); + } + + @Override + public void onCommandExecuted(Command command, Long refreshKey) + { + if(refreshKey == null) updateAllHabits(true); + else updateHabit(refreshKey); + } } diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/list/HabitListSelectionCallback.java b/app/src/main/java/org/isoron/uhabits/ui/habits/list/HabitListSelectionCallback.java index 41378e8d0..1091841e6 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/habits/list/HabitListSelectionCallback.java +++ b/app/src/main/java/org/isoron/uhabits/ui/habits/list/HabitListSelectionCallback.java @@ -31,13 +31,13 @@ import com.android.colorpicker.ColorPickerSwatch; import org.isoron.uhabits.R; import org.isoron.uhabits.commands.ArchiveHabitsCommand; import org.isoron.uhabits.commands.ChangeHabitColorCommand; +import org.isoron.uhabits.commands.CommandRunner; import org.isoron.uhabits.commands.DeleteHabitsCommand; import org.isoron.uhabits.commands.UnarchiveHabitsCommand; import org.isoron.uhabits.models.Habit; import org.isoron.uhabits.ui.BaseActivity; import org.isoron.uhabits.ui.habits.edit.EditHabitDialogFragment; import org.isoron.uhabits.utils.ColorUtils; -import org.isoron.uhabits.utils.InterfaceUtils; import java.util.LinkedList; import java.util.List; @@ -48,7 +48,6 @@ public class HabitListSelectionCallback implements ActionMode.Callback private List selectedPositions; private BaseActivity activity; private Listener listener; - private InterfaceUtils.OnSavedListener onSavedListener; public interface Listener { @@ -67,11 +66,6 @@ public class HabitListSelectionCallback implements ActionMode.Callback this.listener = listener; } - public void setOnSavedListener(InterfaceUtils.OnSavedListener onSavedListener) - { - this.onSavedListener = onSavedListener; - } - public void setSelectedPositions(List selectedPositions) { this.selectedPositions = selectedPositions; @@ -134,64 +128,33 @@ public class HabitListSelectionCallback implements ActionMode.Callback switch (item.getItemId()) { case R.id.action_archive_habit: - activity.executeCommand(new ArchiveHabitsCommand(selectedHabits), null); + archiveHabits(selectedHabits); mode.finish(); return true; case R.id.action_unarchive_habit: - activity.executeCommand(new UnarchiveHabitsCommand(selectedHabits), null); + unarchiveHabits(selectedHabits); mode.finish(); return true; case R.id.action_edit_habit: { - EditHabitDialogFragment - frag = EditHabitDialogFragment.editSingleHabitFragment(firstHabit.getId()); - frag.setOnSavedListener(onSavedListener); - frag.show(activity.getSupportFragmentManager(), "editHabit"); + editHabit(firstHabit); + mode.finish(); return true; } case R.id.action_color: { - int originalAndroidColor = ColorUtils.getColor(activity, firstHabit.color); - - ColorPickerDialog picker = ColorPickerDialog.newInstance( - R.string.color_picker_default_title, ColorUtils.getPalette(activity), - originalAndroidColor, 4, ColorPickerDialog.SIZE_SMALL); - - picker.setOnColorSelectedListener(new ColorPickerSwatch.OnColorSelectedListener() - { - public void onColorSelected(int androidColor) - { - int paletteColor = ColorUtils.colorToPaletteIndex(activity, - androidColor); - activity.executeCommand(new ChangeHabitColorCommand(selectedHabits, - paletteColor), null); - mode.finish(); - } - }); - picker.show(activity.getSupportFragmentManager(), "picker"); + showColorPicker(mode, selectedHabits, firstHabit); + mode.finish(); 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(); - + deleteHabits(mode, selectedHabits); + mode.finish(); return true; } } @@ -199,6 +162,64 @@ public class HabitListSelectionCallback implements ActionMode.Callback return false; } + private void deleteHabits(final ActionMode mode, final LinkedList selectedHabits) + { + 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) + { + CommandRunner.getInstance() + .execute(new DeleteHabitsCommand(selectedHabits), null); + mode.finish(); + } + }) + .setNegativeButton(android.R.string.no, null) + .show(); + } + + private void showColorPicker(final ActionMode mode, final LinkedList selectedHabits, + Habit firstHabit) + { + int originalAndroidColor = ColorUtils.getColor(activity, firstHabit.color); + + ColorPickerDialog picker = + ColorPickerDialog.newInstance(R.string.color_picker_default_title, + ColorUtils.getPalette(activity), originalAndroidColor, 4, + ColorPickerDialog.SIZE_SMALL); + + picker.setOnColorSelectedListener(new ColorPickerSwatch.OnColorSelectedListener() + { + public void onColorSelected(int androidColor) + { + int paletteColor = ColorUtils.colorToPaletteIndex(activity, androidColor); + CommandRunner.getInstance() + .execute(new ChangeHabitColorCommand(selectedHabits, paletteColor), null); + mode.finish(); + } + }); + picker.show(activity.getSupportFragmentManager(), "picker"); + } + + private void editHabit(Habit habit) + { + EditHabitDialogFragment + frag = EditHabitDialogFragment.editSingleHabitFragment(habit.getId()); + frag.show(activity.getSupportFragmentManager(), "editHabit"); + } + + private void unarchiveHabits(LinkedList selectedHabits) + { + CommandRunner.getInstance().execute(new UnarchiveHabitsCommand(selectedHabits), null); + } + + private void archiveHabits(LinkedList selectedHabits) + { + CommandRunner.getInstance().execute(new ArchiveHabitsCommand(selectedHabits), null); + } + @Override public void onDestroyActionMode(ActionMode mode) { diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsFragment.java b/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsFragment.java index b42c9b7ce..cefecc0c9 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsFragment.java +++ b/app/src/main/java/org/isoron/uhabits/ui/habits/list/ListHabitsFragment.java @@ -35,17 +35,15 @@ import android.widget.ProgressBar; import android.widget.TextView; import org.isoron.uhabits.R; -import org.isoron.uhabits.commands.Command; +import org.isoron.uhabits.commands.CommandRunner; import org.isoron.uhabits.commands.ToggleRepetitionCommand; import org.isoron.uhabits.models.Habit; import org.isoron.uhabits.ui.BaseActivity; import org.isoron.uhabits.ui.HintManager; import org.isoron.uhabits.ui.habits.edit.EditHabitDialogFragment; import org.isoron.uhabits.utils.InterfaceUtils; -import org.isoron.uhabits.utils.InterfaceUtils.OnSavedListener; -import org.isoron.uhabits.utils.ReminderUtils; -public class ListHabitsFragment extends Fragment implements OnSavedListener, OnClickListener, +public class ListHabitsFragment extends Fragment implements OnClickListener, HabitListSelectionCallback.Listener, ListHabitsController.Screen { private ActionMode actionMode; @@ -84,7 +82,6 @@ public class ListHabitsFragment extends Fragment implements OnSavedListener, OnC { EditHabitDialogFragment frag = (EditHabitDialogFragment) getFragmentManager() .findFragmentByTag("editHabit"); - if(frag != null) frag.setOnSavedListener(this); } return view; @@ -104,12 +101,20 @@ public class ListHabitsFragment extends Fragment implements OnSavedListener, OnC { super.onResume(); + listView.getLoader().onResume(); listView.refreshData(null); helper.updateEmptyMessage(llEmpty); helper.updateHeader(llButtonsHeader); hintManager.showHintIfAppropriate(); } + @Override + public void onPause() + { + listView.getLoader().onPause(); + super.onPause(); + } + @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { @@ -146,7 +151,6 @@ public class ListHabitsFragment extends Fragment implements OnSavedListener, OnC private void showCreateHabitScreen() { EditHabitDialogFragment frag = EditHabitDialogFragment.createHabitFragment(); - frag.setOnSavedListener(this); frag.show(getFragmentManager(), "editHabit"); } @@ -155,7 +159,6 @@ public class ListHabitsFragment extends Fragment implements OnSavedListener, OnC HabitListSelectionCallback callback = new HabitListSelectionCallback(activity, listView.getLoader()); callback.setSelectedPositions(listView.getSelectedPositions()); - callback.setOnSavedListener(this); callback.setListener(this); actionMode = activity.startSupportActionMode(callback); } @@ -172,26 +175,6 @@ public class ListHabitsFragment extends Fragment implements OnSavedListener, OnC listView.cancelSelection(); } - @Override - public void onSaved(Command command, Object savedObject) - { - Habit h = (Habit) savedObject; - - if (h == null) activity.executeCommand(command, null); - else activity.executeCommand(command, h.getId()); - - listView.refreshData(null); - - ReminderUtils.createReminderAlarms(activity); - - finishActionMode(); - } - - private void executeCommand(Command c, Long refreshKey) - { - activity.executeCommand(c, refreshKey); - } - @Override public void onClick(View v) { @@ -199,11 +182,6 @@ public class ListHabitsFragment extends Fragment implements OnSavedListener, OnC hintManager.dismissHint(); } - public void onPostExecuteCommand(Long refreshKey) - { - listView.refreshData(refreshKey); - } - public ProgressBar getProgressBar() { return progressBar; @@ -224,7 +202,8 @@ public class ListHabitsFragment extends Fragment implements OnSavedListener, OnC @Override public void onToggleCheckmark(Habit habit, long timestamp) { - executeCommand(new ToggleRepetitionCommand(habit, timestamp), habit.getId()); + CommandRunner.getInstance().execute(new ToggleRepetitionCommand(habit, timestamp), + habit.getId()); } @Override diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/show/ShowHabitActivity.java b/app/src/main/java/org/isoron/uhabits/ui/habits/show/ShowHabitActivity.java index a34a61fe4..1d15e642e 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/habits/show/ShowHabitActivity.java +++ b/app/src/main/java/org/isoron/uhabits/ui/habits/show/ShowHabitActivity.java @@ -42,12 +42,11 @@ public class ShowHabitActivity extends BaseActivity habit = Habit.get(ContentUris.parseId(data)); setContentView(R.layout.show_habit_activity); - setupSupportActionBar(true); setupHabitActionBar(); } - private void setupHabitActionBar() + public void setupHabitActionBar() { if(habit == null) return; @@ -55,7 +54,6 @@ public class ShowHabitActivity extends BaseActivity if(actionBar == null) return; actionBar.setTitle(habit.name); - setupActionBarColor(ColorUtils.getColor(this, habit.color)); } diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/show/ShowHabitFragment.java b/app/src/main/java/org/isoron/uhabits/ui/habits/show/ShowHabitFragment.java index 43d3261b3..3ce2bf349 100644 --- a/app/src/main/java/org/isoron/uhabits/ui/habits/show/ShowHabitFragment.java +++ b/app/src/main/java/org/isoron/uhabits/ui/habits/show/ShowHabitFragment.java @@ -31,60 +31,42 @@ import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.Button; import android.widget.Spinner; -import android.widget.TextView; -import org.isoron.uhabits.HabitBroadcastReceiver; import org.isoron.uhabits.R; -import org.isoron.uhabits.commands.Command; +import org.isoron.uhabits.models.Habit; +import org.isoron.uhabits.models.ModelObservable; +import org.isoron.uhabits.tasks.BaseTask; import org.isoron.uhabits.ui.habits.edit.EditHabitDialogFragment; import org.isoron.uhabits.ui.habits.edit.HistoryEditorDialog; -import org.isoron.uhabits.utils.ColorUtils; import org.isoron.uhabits.utils.DateUtils; -import org.isoron.uhabits.utils.ReminderUtils; import org.isoron.uhabits.utils.InterfaceUtils; -import org.isoron.uhabits.models.Habit; -import org.isoron.uhabits.models.Score; -import org.isoron.uhabits.tasks.BaseTask; import org.isoron.uhabits.views.HabitDataView; import org.isoron.uhabits.views.HabitFrequencyView; import org.isoron.uhabits.views.HabitHistoryView; import org.isoron.uhabits.views.HabitScoreView; import org.isoron.uhabits.views.HabitStreakView; -import org.isoron.uhabits.views.RingView; import java.util.LinkedList; import java.util.List; public class ShowHabitFragment extends Fragment - implements InterfaceUtils.OnSavedListener, HistoryEditorDialog.Listener, - Spinner.OnItemSelectedListener + implements Spinner.OnItemSelectedListener, ModelObservable.Listener { - @Nullable protected ShowHabitActivity activity; - - @Nullable - private Habit habit; - @Nullable private List dataViews; - @Nullable - private HabitScoreView scoreView; - private int previousScoreInterval; - private float todayScore; - private float lastMonthScore; - private float lastYearScore; + Habit habit; - private int activeColor; - private int inactiveColor; + float todayScore; + float lastMonthScore; + float lastYearScore; + int activeColor; + int inactiveColor; - @Override - public void onStart() - { - super.onStart(); - } + private ShowHabitHelper helper; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, @@ -92,37 +74,32 @@ public class ShowHabitFragment extends Fragment { View view = inflater.inflate(R.layout.show_habit, container, false); activity = (ShowHabitActivity) getActivity(); + helper = new ShowHabitHelper(this); habit = activity.getHabit(); - activeColor = ColorUtils.getColor(getContext(), habit.color); - inactiveColor = InterfaceUtils.getStyledColor(getContext(), R.attr.mediumContrastTextColor); - - updateHeader(view); - - dataViews = new LinkedList<>(); - - Button btEditHistory = (Button) view.findViewById(R.id.btEditHistory); - Spinner sStrengthInterval = (Spinner) view.findViewById(R.id.sStrengthInterval); - - scoreView = (HabitScoreView) view.findViewById(R.id.scoreView); + helper.updateColors(); + helper.updateMainHeader(view); int defaultScoreInterval = InterfaceUtils.getDefaultScoreInterval(getContext()); previousScoreInterval = defaultScoreInterval; setScoreBucketSize(defaultScoreInterval); + Spinner sStrengthInterval = (Spinner) view.findViewById(R.id.sStrengthInterval); sStrengthInterval.setSelection(defaultScoreInterval); sStrengthInterval.setOnItemSelectedListener(this); - dataViews.add((HabitScoreView) view.findViewById(R.id.scoreView)); - dataViews.add((HabitHistoryView) view.findViewById(R.id.historyView)); - dataViews.add((HabitFrequencyView) view.findViewById(R.id.punchcardView)); - dataViews.add((HabitStreakView) view.findViewById(R.id.streakView)); + createDataViews(view); + helper.updateCardHeaders(view); - updateHeaders(view); + bindButtontEditHistory(view); + setHasOptionsMenu(true); - for(HabitDataView dataView : dataViews) - dataView.setHabit(habit); + return view; + } + private void bindButtontEditHistory(View view) + { + Button btEditHistory = (Button) view.findViewById(R.id.btEditHistory); btEditHistory.setOnClickListener(new View.OnClickListener() { @Override @@ -130,75 +107,21 @@ public class ShowHabitFragment extends Fragment { HistoryEditorDialog frag = new HistoryEditorDialog(); frag.setHabit(habit); - frag.setListener(ShowHabitFragment.this); frag.show(getFragmentManager(), "historyEditor"); } }); - - if(savedInstanceState != null) - { - EditHabitDialogFragment fragEdit = (EditHabitDialogFragment) getFragmentManager() - .findFragmentByTag("editHabit"); - HistoryEditorDialog fragEditor = (HistoryEditorDialog) getFragmentManager() - .findFragmentByTag("historyEditor"); - - if(fragEdit != null) fragEdit.setOnSavedListener(this); - if(fragEditor != null) fragEditor.setListener(this); - } - - setHasOptionsMenu(true); - - return view; } - private void updateHeader(View view) + private void createDataViews(View view) { - if(habit == null) return; - - TextView questionLabel = (TextView) view.findViewById(R.id.questionLabel); - questionLabel.setTextColor(activeColor); - questionLabel.setText(habit.description); - - TextView reminderLabel = (TextView) view.findViewById(R.id.reminderLabel); - if(habit.hasReminder()) - reminderLabel.setText(DateUtils.formatTime(getActivity(), habit.reminderHour, - habit.reminderMin)); - else - reminderLabel.setText(getResources().getString(R.string.reminder_off)); - - TextView frequencyLabel = (TextView) view.findViewById(R.id.frequencyLabel); - frequencyLabel.setText(getFreqText()); - - if(habit.description.isEmpty()) - questionLabel.setVisibility(View.GONE); - } - - private String getFreqText() - { - if(habit == null) - return ""; - - if(habit.freqNum.equals(habit.freqDen)) - return getResources().getString(R.string.every_day); - - if(habit.freqNum == 1) - { - if (habit.freqDen == 7) - return getResources().getString(R.string.every_week); - - if (habit.freqDen % 7 == 0) - return getResources().getString(R.string.every_x_weeks, habit.freqDen / 7); - - return getResources().getString(R.string.every_x_days, habit.freqDen); - } - - String times_every = getResources().getString(R.string.times_every); - - if(habit.freqNum == 1) - times_every = getResources().getString(R.string.time_every); + dataViews = new LinkedList<>(); + dataViews.add((HabitScoreView) view.findViewById(R.id.scoreView)); + dataViews.add((HabitHistoryView) view.findViewById(R.id.historyView)); + dataViews.add((HabitFrequencyView) view.findViewById(R.id.punchcardView)); + dataViews.add((HabitStreakView) view.findViewById(R.id.streakView)); - return String.format("%d %s %d %s", habit.freqNum, times_every, habit.freqDen, - getResources().getString(R.string.days)); + for(HabitDataView dataView : dataViews) + dataView.setHabit(habit); } @Override @@ -208,166 +131,114 @@ public class ShowHabitFragment extends Fragment refreshData(); } - private void updateScore(View view) + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - if(habit == null) return; - if(view == null) return; - - float todayPercentage = todayScore / Score.MAX_VALUE; - float monthDiff = todayPercentage - (lastMonthScore / Score.MAX_VALUE); - float yearDiff = todayPercentage - (lastYearScore / Score.MAX_VALUE); - - RingView scoreRing = (RingView) view.findViewById(R.id.scoreRing); - int androidColor = ColorUtils.getColor(getActivity(), habit.color); - scoreRing.setColor(androidColor); - scoreRing.setPercentage(todayPercentage); - - TextView scoreLabel = (TextView) view.findViewById(R.id.scoreLabel); - TextView monthDiffLabel = (TextView) view.findViewById(R.id.monthDiffLabel); - TextView yearDiffLabel = (TextView) view.findViewById(R.id.yearDiffLabel); - - scoreLabel.setText(String.format("%.0f%%", todayPercentage * 100)); - - String minus = "\u2212"; - monthDiffLabel.setText(String.format("%s%.0f%%", (monthDiff >= 0 ? "+" : minus), - Math.abs(monthDiff) * 100)); - yearDiffLabel.setText( - String.format("%s%.0f%%", (yearDiff >= 0 ? "+" : minus), Math.abs(yearDiff) * 100)); - - monthDiffLabel.setTextColor(monthDiff >= 0 ? activeColor : inactiveColor); - yearDiffLabel.setTextColor(yearDiff >= 0 ? activeColor : inactiveColor); + inflater.inflate(R.menu.show_habit_fragment, menu); } - private void updateHeaders(View view) + @Override + public boolean onOptionsItemSelected(MenuItem item) { - updateColor(view, R.id.tvHistory); - updateColor(view, R.id.tvOverview); - updateColor(view, R.id.tvStrength); - updateColor(view, R.id.tvStreaks); - updateColor(view, R.id.tvWeekdayFreq); - updateColor(view, R.id.scoreLabel); + if (item.getItemId() == R.id.action_edit_habit) + return showEditHabitDialog(); + + return false; } - private void updateColor(View view, int viewId) + private boolean showEditHabitDialog() { - if(habit == null || activity == null) return; + if(habit == null) return false; - TextView textView = (TextView) view.findViewById(viewId); - int androidColor = ColorUtils.getColor(activity, habit.color); - textView.setTextColor(androidColor); + EditHabitDialogFragment frag = EditHabitDialogFragment.editSingleHabitFragment(habit.getId()); + frag.show(getFragmentManager(), "editHabit"); + return true; } - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) + public void refreshData() { - inflater.inflate(R.menu.show_habit_fragment, menu); + new RefreshTask().execute(); } @Override - public boolean onOptionsItemSelected(MenuItem item) + public void onItemSelected(AdapterView parent, View view, int position, long id) { - if(habit == null) return false; - - switch (item.getItemId()) - { - case R.id.action_edit_habit: - { - EditHabitDialogFragment - frag = EditHabitDialogFragment.editSingleHabitFragment(habit.getId()); - frag.setOnSavedListener(this); - frag.show(getFragmentManager(), "editHabit"); - return true; - } - } - - return false; + if(parent.getId() == R.id.sStrengthInterval) + setScoreBucketSize(position); } - @Override - public void onSaved(Command command, Object savedObject) + private void setScoreBucketSize(int position) { - if(activity == null) return; - Habit h = (Habit) savedObject; + if(getView() == null) return; - if (h == null) activity.executeCommand(command, null); - else activity.executeCommand(command, h.getId()); + HabitScoreView scoreView = (HabitScoreView) getView().findViewById(R.id.scoreView); + scoreView.setBucketSize(HabitScoreView.DEFAULT_BUCKET_SIZES[position]); - ReminderUtils.createReminderAlarms(activity); - HabitBroadcastReceiver.sendRefreshBroadcast(getActivity()); + if(position != previousScoreInterval) + refreshData(); - activity.recreate(); + InterfaceUtils.setDefaultScoreInterval(getContext(), position); + previousScoreInterval = position; } @Override - public void onHistoryEditorClosed() + public void onNothingSelected(AdapterView parent) { - refreshData(); - HabitBroadcastReceiver.sendRefreshBroadcast(getActivity()); } - public void refreshData() + @Override + public void onModelChange() { - new BaseTask() + refreshData(); + activity.runOnUiThread(new Runnable() { @Override - protected void doInBackground() + public void run() { - if(habit == null) return; - if(dataViews == null) return; - - long today = DateUtils.getStartOfToday(); - long lastMonth = today - 30 * DateUtils.millisecondsInOneDay; - long lastYear = today - 365 * DateUtils.millisecondsInOneDay; - - todayScore = (float) habit.scores.getTodayValue(); - lastMonthScore = (float) habit.scores.getValue(lastMonth); - lastYearScore = (float) habit.scores.getValue(lastYear); - - int count = 0; - for(HabitDataView view : dataViews) - { - view.refreshData(); - publishProgress(count++); - } + helper.updateColors(); + helper.updateMainHeader(getView()); + helper.updateCardHeaders(getView()); + if(activity != null) activity.setupHabitActionBar(); } - - @Override - protected void onProgressUpdate(Integer... values) - { - updateScore(getView()); - if(dataViews == null) return; - dataViews.get(values[0]).postInvalidate(); - } - }.execute(); - + }); } - @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) + private class RefreshTask extends BaseTask { - if(parent.getId() == R.id.sStrengthInterval) - setScoreBucketSize(position); - } + @Override + protected void doInBackground() + { + if(habit == null) return; + if(dataViews == null) return; - private void setScoreBucketSize(int position) - { - if(scoreView == null) return; + long today = DateUtils.getStartOfToday(); + long lastMonth = today - 30 * DateUtils.millisecondsInOneDay; + long lastYear = today - 365 * DateUtils.millisecondsInOneDay; - scoreView.setBucketSize(HabitScoreView.DEFAULT_BUCKET_SIZES[position]); + todayScore = (float) habit.scores.getTodayValue(); + lastMonthScore = (float) habit.scores.getValue(lastMonth); + lastYearScore = (float) habit.scores.getValue(lastYear); + } - if(position != previousScoreInterval) + @Override + protected void onPostExecute(Void aVoid) { - refreshData(); - HabitBroadcastReceiver.sendRefreshBroadcast(getActivity()); + helper.updateScore(getView()); + super.onPostExecute(aVoid); } - - InterfaceUtils.setDefaultScoreInterval(getContext(), position); - previousScoreInterval = position; } @Override - public void onNothingSelected(AdapterView parent) + public void onStart() { + super.onStart(); + habit.observable.addListener(this); + } + @Override + public void onPause() + { + habit.observable.removeListener(this); + super.onPause(); } } diff --git a/app/src/main/java/org/isoron/uhabits/ui/habits/show/ShowHabitHelper.java b/app/src/main/java/org/isoron/uhabits/ui/habits/show/ShowHabitHelper.java new file mode 100644 index 000000000..026327d22 --- /dev/null +++ b/app/src/main/java/org/isoron/uhabits/ui/habits/show/ShowHabitHelper.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2016 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker 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. + * + * Loop Habit Tracker 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.ui.habits.show; + +import android.content.res.Resources; +import android.view.View; +import android.widget.TextView; + +import org.isoron.uhabits.R; +import org.isoron.uhabits.models.Score; +import org.isoron.uhabits.utils.ColorUtils; +import org.isoron.uhabits.utils.DateUtils; +import org.isoron.uhabits.utils.InterfaceUtils; +import org.isoron.uhabits.views.RingView; + +public class ShowHabitHelper +{ + private ShowHabitFragment fragment; + + public ShowHabitHelper(ShowHabitFragment fragment) + { + this.fragment = fragment; + } + + String getFreqText() + { + if(fragment.habit == null) return ""; + + Resources resources = fragment.getResources(); + Integer freqNum = fragment.habit.freqNum; + Integer freqDen = fragment.habit.freqDen; + + if (freqNum.equals(freqDen)) return resources.getString(R.string.every_day); + + if (freqNum == 1) + { + if (freqDen == 7) return resources.getString(R.string.every_week); + if (freqDen % 7 == 0) return resources.getString(R.string.every_x_weeks, freqDen / 7); + return resources.getString(R.string.every_x_days, freqDen); + } + + String times_every = resources.getString(R.string.time_every); + return String.format("%d %s %d %s", freqNum, times_every, freqDen, + resources.getString(R.string.days)); + } + + void updateScore(View view) + { + if (fragment.habit == null) return; + if (view == null) return; + + float todayPercentage = fragment.todayScore / Score.MAX_VALUE; + float monthDiff = todayPercentage - (fragment.lastMonthScore / Score.MAX_VALUE); + float yearDiff = todayPercentage - (fragment.lastYearScore / Score.MAX_VALUE); + + RingView scoreRing = (RingView) view.findViewById(R.id.scoreRing); + int androidColor = ColorUtils.getColor(fragment.getActivity(), fragment.habit.color); + scoreRing.setColor(androidColor); + scoreRing.setPercentage(todayPercentage); + + TextView scoreLabel = (TextView) view.findViewById(R.id.scoreLabel); + TextView monthDiffLabel = (TextView) view.findViewById(R.id.monthDiffLabel); + TextView yearDiffLabel = (TextView) view.findViewById(R.id.yearDiffLabel); + + scoreLabel.setText(String.format("%.0f%%", todayPercentage * 100)); + + String minus = "\u2212"; + monthDiffLabel.setText(String.format("%s%.0f%%", (monthDiff >= 0 ? "+" : minus), + Math.abs(monthDiff) * 100)); + yearDiffLabel.setText( + String.format("%s%.0f%%", (yearDiff >= 0 ? "+" : minus), Math.abs(yearDiff) * 100)); + + monthDiffLabel.setTextColor(monthDiff >= 0 ? fragment.activeColor : fragment.inactiveColor); + yearDiffLabel.setTextColor(yearDiff >= 0 ? fragment.activeColor : fragment.inactiveColor); + } + + void updateMainHeader(View view) + { + if (fragment.habit == null) return; + + TextView questionLabel = (TextView) view.findViewById(R.id.questionLabel); + questionLabel.setTextColor(fragment.activeColor); + questionLabel.setText(fragment.habit.description); + + TextView reminderLabel = (TextView) view.findViewById(R.id.reminderLabel); + if (fragment.habit.hasReminder()) reminderLabel.setText( + DateUtils.formatTime(fragment.getActivity(), fragment.habit.reminderHour, + fragment.habit.reminderMin)); + else reminderLabel.setText(fragment.getResources().getString(R.string.reminder_off)); + + TextView frequencyLabel = (TextView) view.findViewById(R.id.frequencyLabel); + frequencyLabel.setText(getFreqText()); + + if (fragment.habit.description.isEmpty()) questionLabel.setVisibility(View.GONE); + } + + void updateCardHeaders(View view) + { + updateColor(view, R.id.tvHistory); + updateColor(view, R.id.tvOverview); + updateColor(view, R.id.tvStrength); + updateColor(view, R.id.tvStreaks); + updateColor(view, R.id.tvWeekdayFreq); + updateColor(view, R.id.scoreLabel); + } + + void updateColor(View view, int viewId) + { + if(fragment.habit == null || fragment.activity == null) return; + + TextView textView = (TextView) view.findViewById(viewId); + int androidColor = ColorUtils.getColor(fragment.activity, fragment.habit.color); + textView.setTextColor(androidColor); + } + + void updateColors() + { + fragment.activeColor = ColorUtils.getColor(fragment.getContext(), fragment.habit.color); + fragment.inactiveColor = InterfaceUtils.getStyledColor(fragment.getContext(), + R.attr.mediumContrastTextColor); + } +} diff --git a/app/src/main/java/org/isoron/uhabits/utils/InterfaceUtils.java b/app/src/main/java/org/isoron/uhabits/utils/InterfaceUtils.java index f6492725a..b19b62bf5 100644 --- a/app/src/main/java/org/isoron/uhabits/utils/InterfaceUtils.java +++ b/app/src/main/java/org/isoron/uhabits/utils/InterfaceUtils.java @@ -36,7 +36,6 @@ import android.util.TypedValue; import org.isoron.uhabits.HabitsApplication; import org.isoron.uhabits.R; -import org.isoron.uhabits.commands.Command; import java.util.Locale; @@ -55,11 +54,6 @@ public abstract class InterfaceUtils InterfaceUtils.fixedTheme = fixedTheme; } - public interface OnSavedListener - { - void onSaved(Command command, Object savedObject); - } - public static Typeface getFontAwesome(Context context) { if(fontAwesome == null) diff --git a/app/src/main/java/org/isoron/uhabits/views/HabitFrequencyView.java b/app/src/main/java/org/isoron/uhabits/views/HabitFrequencyView.java index 7cf504508..212aaa570 100644 --- a/app/src/main/java/org/isoron/uhabits/views/HabitFrequencyView.java +++ b/app/src/main/java/org/isoron/uhabits/views/HabitFrequencyView.java @@ -26,6 +26,8 @@ import android.graphics.RectF; import android.util.AttributeSet; import org.isoron.uhabits.R; +import org.isoron.uhabits.models.ModelObservable; +import org.isoron.uhabits.tasks.BaseTask; import org.isoron.uhabits.utils.ColorUtils; import org.isoron.uhabits.utils.DateUtils; import org.isoron.uhabits.utils.InterfaceUtils; @@ -38,9 +40,8 @@ import java.util.GregorianCalendar; import java.util.HashMap; import java.util.Random; -public class HabitFrequencyView extends ScrollableDataView implements HabitDataView +public class HabitFrequencyView extends ScrollableDataView implements HabitDataView, ModelObservable.Listener { - private Paint pGrid; private float em; private Habit habit; @@ -173,10 +174,12 @@ public class HabitFrequencyView extends ScrollableDataView implements HabitDataV public void refreshData() { - if(isInEditMode()) - generateRandomData(); + if(isInEditMode()) generateRandomData(); else if(habit != null) + { frequency = habit.repetitions.getWeekdayFrequency(); + createColors(); + } postInvalidate(); } @@ -297,4 +300,35 @@ public class HabitFrequencyView extends ScrollableDataView implements HabitDataV this.isBackgroundTransparent = isBackgroundTransparent; createColors(); } + + + @Override + protected void onAttachedToWindow() + { + super.onAttachedToWindow(); + new BaseTask() + { + @Override + protected void doInBackground() + { + refreshData(); + } + }.execute(); + habit.observable.addListener(this); + habit.checkmarks.observable.addListener(this); + } + + @Override + protected void onDetachedFromWindow() + { + habit.checkmarks.observable.removeListener(this); + habit.observable.removeListener(this); + super.onDetachedFromWindow(); + } + + @Override + public void onModelChange() + { + refreshData(); + } } diff --git a/app/src/main/java/org/isoron/uhabits/views/HabitHistoryView.java b/app/src/main/java/org/isoron/uhabits/views/HabitHistoryView.java index 4c529194e..d390fdb42 100644 --- a/app/src/main/java/org/isoron/uhabits/views/HabitHistoryView.java +++ b/app/src/main/java/org/isoron/uhabits/views/HabitHistoryView.java @@ -30,12 +30,13 @@ import android.view.HapticFeedbackConstants; import android.view.MotionEvent; import org.isoron.uhabits.R; -import org.isoron.uhabits.utils.ColorUtils; -import org.isoron.uhabits.utils.DateUtils; -import org.isoron.uhabits.utils.InterfaceUtils; import org.isoron.uhabits.models.Habit; +import org.isoron.uhabits.models.ModelObservable; import org.isoron.uhabits.tasks.BaseTask; import org.isoron.uhabits.tasks.ToggleRepetitionTask; +import org.isoron.uhabits.utils.ColorUtils; +import org.isoron.uhabits.utils.DateUtils; +import org.isoron.uhabits.utils.InterfaceUtils; import java.text.SimpleDateFormat; import java.util.Calendar; @@ -43,7 +44,7 @@ import java.util.GregorianCalendar; import java.util.Random; public class HabitHistoryView extends ScrollableDataView implements HabitDataView, - ToggleRepetitionTask.Listener + ToggleRepetitionTask.Listener, ModelObservable.Listener { private Habit habit; private int[] checkmarks; @@ -216,6 +217,7 @@ public class HabitHistoryView extends ScrollableDataView implements HabitDataVie { if(habit == null) return; checkmarks = habit.checkmarks.getAllValues(); + createColors(); } updateDate(); @@ -409,4 +411,34 @@ public class HabitHistoryView extends ScrollableDataView implements HabitDataVie } }.execute(); } + + @Override + protected void onAttachedToWindow() + { + super.onAttachedToWindow(); + new BaseTask() + { + @Override + protected void doInBackground() + { + refreshData(); + } + }.execute(); + habit.observable.addListener(this); + habit.checkmarks.observable.addListener(this); + } + + @Override + protected void onDetachedFromWindow() + { + habit.checkmarks.observable.removeListener(this); + habit.observable.removeListener(this); + super.onDetachedFromWindow(); + } + + @Override + public void onModelChange() + { + refreshData(); + } } diff --git a/app/src/main/java/org/isoron/uhabits/views/HabitScoreView.java b/app/src/main/java/org/isoron/uhabits/views/HabitScoreView.java index 29c00e24b..5a336d101 100644 --- a/app/src/main/java/org/isoron/uhabits/views/HabitScoreView.java +++ b/app/src/main/java/org/isoron/uhabits/views/HabitScoreView.java @@ -31,18 +31,21 @@ import android.support.annotation.Nullable; import android.util.AttributeSet; import org.isoron.uhabits.R; +import org.isoron.uhabits.models.Habit; +import org.isoron.uhabits.models.ModelObservable; +import org.isoron.uhabits.models.Score; +import org.isoron.uhabits.tasks.BaseTask; import org.isoron.uhabits.utils.ColorUtils; import org.isoron.uhabits.utils.DateUtils; import org.isoron.uhabits.utils.InterfaceUtils; -import org.isoron.uhabits.models.Habit; -import org.isoron.uhabits.models.Score; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.Random; -public class HabitScoreView extends ScrollableDataView implements HabitDataView +public class HabitScoreView extends ScrollableDataView + implements HabitDataView, ModelObservable.Listener { public static final PorterDuffXfermode XFERMODE_CLEAR = new PorterDuffXfermode(PorterDuff.Mode.CLEAR); @@ -195,6 +198,7 @@ public class HabitScoreView extends ScrollableDataView implements HabitDataView { if (habit == null) return; scores = habit.scores.getAllValues(bucketSize); + createColors(); } postInvalidate(); @@ -434,4 +438,34 @@ public class HabitScoreView extends ScrollableDataView implements HabitDataView return maxDayWidth; } + + @Override + protected void onAttachedToWindow() + { + super.onAttachedToWindow(); + new BaseTask() + { + @Override + protected void doInBackground() + { + refreshData(); + } + }.execute(); + habit.observable.addListener(this); + habit.scores.observable.addListener(this); + } + + @Override + protected void onDetachedFromWindow() + { + habit.scores.observable.removeListener(this); + habit.observable.removeListener(this); + super.onDetachedFromWindow(); + } + + @Override + public void onModelChange() + { + refreshData(); + } } diff --git a/app/src/main/java/org/isoron/uhabits/views/HabitStreakView.java b/app/src/main/java/org/isoron/uhabits/views/HabitStreakView.java index 27959fddf..6019ef4a1 100644 --- a/app/src/main/java/org/isoron/uhabits/views/HabitStreakView.java +++ b/app/src/main/java/org/isoron/uhabits/views/HabitStreakView.java @@ -28,6 +28,8 @@ import android.util.AttributeSet; import android.view.View; import org.isoron.uhabits.R; +import org.isoron.uhabits.models.ModelObservable; +import org.isoron.uhabits.tasks.BaseTask; import org.isoron.uhabits.utils.ColorUtils; import org.isoron.uhabits.utils.InterfaceUtils; import org.isoron.uhabits.models.Habit; @@ -39,7 +41,7 @@ import java.util.Date; import java.util.List; import java.util.TimeZone; -public class HabitStreakView extends View implements HabitDataView +public class HabitStreakView extends View implements HabitDataView, ModelObservable.Listener { private Habit habit; private Paint paint; @@ -151,6 +153,7 @@ public class HabitStreakView extends View implements HabitDataView { if(habit == null) return; streaks = habit.streaks.getAll(maxStreakCount); + createColors(); updateMaxMin(); postInvalidate(); } @@ -246,4 +249,35 @@ public class HabitStreakView extends View implements HabitDataView this.isBackgroundTransparent = isBackgroundTransparent; createColors(); } + + + @Override + protected void onAttachedToWindow() + { + super.onAttachedToWindow(); + new BaseTask() + { + @Override + protected void doInBackground() + { + refreshData(); + } + }.execute(); + habit.observable.addListener(this); + habit.streaks.observable.addListener(this); + } + + @Override + protected void onDetachedFromWindow() + { + habit.streaks.observable.removeListener(this); + habit.observable.removeListener(this); + super.onDetachedFromWindow(); + } + + @Override + public void onModelChange() + { + refreshData(); + } }