mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 09:08:52 -06:00
Make models observable, refactor ShowHabitFragment
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<Listener> 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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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<Habit> 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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<Command> undoList;
|
||||
private LinkedList<Command> 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()
|
||||
@Override
|
||||
protected void onPause()
|
||||
{
|
||||
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()
|
||||
{
|
||||
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<Void, Void, Void>()
|
||||
{
|
||||
@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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Integer> 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<Integer> 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);
|
||||
showColorPicker(mode, selectedHabits, firstHabit);
|
||||
mode.finish();
|
||||
}
|
||||
});
|
||||
picker.show(activity.getSupportFragmentManager(), "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);
|
||||
deleteHabits(mode, selectedHabits);
|
||||
mode.finish();
|
||||
}
|
||||
}).setNegativeButton(android.R.string.no, null)
|
||||
.show();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -199,6 +162,64 @@ public class HabitListSelectionCallback implements ActionMode.Callback
|
||||
return false;
|
||||
}
|
||||
|
||||
private void deleteHabits(final ActionMode mode, final LinkedList<Habit> 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<Habit> 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<Habit> selectedHabits)
|
||||
{
|
||||
CommandRunner.getInstance().execute(new UnarchiveHabitsCommand(selectedHabits), null);
|
||||
}
|
||||
|
||||
private void archiveHabits(LinkedList<Habit> selectedHabits)
|
||||
{
|
||||
CommandRunner.getInstance().execute(new ArchiveHabitsCommand(selectedHabits), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyActionMode(ActionMode mode)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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<HabitDataView> 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;
|
||||
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));
|
||||
|
||||
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);
|
||||
|
||||
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,55 +131,6 @@ public class ShowHabitFragment extends Fragment
|
||||
refreshData();
|
||||
}
|
||||
|
||||
private void updateScore(View view)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
private void updateHeaders(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);
|
||||
}
|
||||
|
||||
private void updateColor(View view, int viewId)
|
||||
{
|
||||
if(habit == null || activity == null) return;
|
||||
|
||||
TextView textView = (TextView) view.findViewById(viewId);
|
||||
int androidColor = ColorUtils.getColor(activity, habit.color);
|
||||
textView.setTextColor(androidColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
|
||||
{
|
||||
@@ -266,48 +140,70 @@ public class ShowHabitFragment extends Fragment
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (item.getItemId() == R.id.action_edit_habit)
|
||||
return showEditHabitDialog();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaved(Command command, Object savedObject)
|
||||
private boolean showEditHabitDialog()
|
||||
{
|
||||
if(activity == null) return;
|
||||
Habit h = (Habit) savedObject;
|
||||
if(habit == null) return false;
|
||||
|
||||
if (h == null) activity.executeCommand(command, null);
|
||||
else activity.executeCommand(command, h.getId());
|
||||
|
||||
ReminderUtils.createReminderAlarms(activity);
|
||||
HabitBroadcastReceiver.sendRefreshBroadcast(getActivity());
|
||||
|
||||
activity.recreate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHistoryEditorClosed()
|
||||
{
|
||||
refreshData();
|
||||
HabitBroadcastReceiver.sendRefreshBroadcast(getActivity());
|
||||
EditHabitDialogFragment frag = EditHabitDialogFragment.editSingleHabitFragment(habit.getId());
|
||||
frag.show(getFragmentManager(), "editHabit");
|
||||
return true;
|
||||
}
|
||||
|
||||
public void refreshData()
|
||||
{
|
||||
new BaseTask()
|
||||
new RefreshTask().execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
|
||||
{
|
||||
if(parent.getId() == R.id.sStrengthInterval)
|
||||
setScoreBucketSize(position);
|
||||
}
|
||||
|
||||
private void setScoreBucketSize(int position)
|
||||
{
|
||||
if(getView() == null) return;
|
||||
|
||||
HabitScoreView scoreView = (HabitScoreView) getView().findViewById(R.id.scoreView);
|
||||
scoreView.setBucketSize(HabitScoreView.DEFAULT_BUCKET_SIZES[position]);
|
||||
|
||||
if(position != previousScoreInterval)
|
||||
refreshData();
|
||||
|
||||
InterfaceUtils.setDefaultScoreInterval(getContext(), position);
|
||||
previousScoreInterval = position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> parent)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onModelChange()
|
||||
{
|
||||
refreshData();
|
||||
activity.runOnUiThread(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
helper.updateColors();
|
||||
helper.updateMainHeader(getView());
|
||||
helper.updateCardHeaders(getView());
|
||||
if(activity != null) activity.setupHabitActionBar();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private class RefreshTask extends BaseTask
|
||||
{
|
||||
@Override
|
||||
protected void doInBackground()
|
||||
@@ -322,52 +218,27 @@ public class ShowHabitFragment extends Fragment
|
||||
todayScore = (float) habit.scores.getTodayValue();
|
||||
lastMonthScore = (float) habit.scores.getValue(lastMonth);
|
||||
lastYearScore = (float) habit.scores.getValue(lastYear);
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
for(HabitDataView view : dataViews)
|
||||
@Override
|
||||
protected void onPostExecute(Void aVoid)
|
||||
{
|
||||
view.refreshData();
|
||||
publishProgress(count++);
|
||||
helper.updateScore(getView());
|
||||
super.onPostExecute(aVoid);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onProgressUpdate(Integer... values)
|
||||
public void onStart()
|
||||
{
|
||||
updateScore(getView());
|
||||
if(dataViews == null) return;
|
||||
dataViews.get(values[0]).postInvalidate();
|
||||
}
|
||||
}.execute();
|
||||
|
||||
super.onStart();
|
||||
habit.observable.addListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
|
||||
public void onPause()
|
||||
{
|
||||
if(parent.getId() == R.id.sStrengthInterval)
|
||||
setScoreBucketSize(position);
|
||||
}
|
||||
|
||||
private void setScoreBucketSize(int position)
|
||||
{
|
||||
if(scoreView == null) return;
|
||||
|
||||
scoreView.setBucketSize(HabitScoreView.DEFAULT_BUCKET_SIZES[position]);
|
||||
|
||||
if(position != previousScoreInterval)
|
||||
{
|
||||
refreshData();
|
||||
HabitBroadcastReceiver.sendRefreshBroadcast(getActivity());
|
||||
}
|
||||
|
||||
InterfaceUtils.setDefaultScoreInterval(getContext(), position);
|
||||
previousScoreInterval = position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> parent)
|
||||
{
|
||||
|
||||
habit.observable.removeListener(this);
|
||||
super.onPause();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,12 +30,13 @@ import android.view.HapticFeedbackConstants;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import org.isoron.uhabits.R;
|
||||
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 org.isoron.uhabits.models.Habit;
|
||||
import org.isoron.uhabits.tasks.BaseTask;
|
||||
import org.isoron.uhabits.tasks.ToggleRepetitionTask;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user