Make models observable, refactor ShowHabitFragment

pull/145/head
Alinson S. Xavier 9 years ago
parent 16dc9c25d2
commit 071cad73d4

@ -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()
{
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<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);
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<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;
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();
}
}

@ -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.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();
}
}

@ -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();
}
}

Loading…
Cancel
Save