From 7d2e8573f80b7d9aea1a6dffa84029beb3a08244 Mon Sep 17 00:00:00 2001 From: Alinson Xavier Date: Sat, 25 Mar 2017 19:57:38 -0400 Subject: [PATCH] Persist unit and target value of a habit --- app/build.gradle | 2 +- app/src/main/assets/migrations/18.sql | 3 + .../habits/edit/CreateBooleanHabitDialog.java | 3 +- .../edit/CreateNumericalHabitDialog.java | 1 + .../habits/edit/EditNumericalHabitDialog.java | 55 +++++++ .../edit/EditNumericalHabitDialogFactory.java | 47 ++++++ .../habits/edit/NumericalHabitDialog.java | 155 +++++------------- .../edit/NumericalHabitDialogHelper.java | 117 +++++++++++++ .../habits/list/ListHabitsController.java | 3 +- .../habits/list/ListHabitsScreen.java | 21 ++- .../habits/list/views/HabitCardListView.java | 2 + .../habits/list/views/HabitCardView.java | 20 ++- .../habits/list/views/NumberButtonView.java | 12 +- .../habits/list/views/NumberPanelView.java | 6 +- .../java/org/isoron/uhabits/models/Habit.java | 64 +++++++- .../models/sqlite/records/HabitRecord.java | 21 ++- .../main/res/layout/edit_numerical_habit.xml | 118 ++++++++----- app/src/main/res/values/constants.xml | 11 ++ app/src/main/res/values/styles_dialog.xml | 4 +- .../habits/list/ListHabitsScreenTest.java | 54 +++--- 20 files changed, 509 insertions(+), 210 deletions(-) create mode 100644 app/src/main/assets/migrations/18.sql create mode 100644 app/src/main/java/org/isoron/uhabits/activities/habits/edit/EditNumericalHabitDialog.java create mode 100644 app/src/main/java/org/isoron/uhabits/activities/habits/edit/EditNumericalHabitDialogFactory.java create mode 100644 app/src/main/java/org/isoron/uhabits/activities/habits/edit/NumericalHabitDialogHelper.java diff --git a/app/build.gradle b/app/build.gradle index 6c85a2323..5c9ef9d71 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -12,7 +12,7 @@ android { minSdkVersion 15 targetSdkVersion 25 - buildConfigField "Integer", "databaseVersion", "17" + buildConfigField "Integer", "databaseVersion", "18" buildConfigField "String", "databaseFilename", "\"uhabits.db\"" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" diff --git a/app/src/main/assets/migrations/18.sql b/app/src/main/assets/migrations/18.sql new file mode 100644 index 000000000..fa6318bcc --- /dev/null +++ b/app/src/main/assets/migrations/18.sql @@ -0,0 +1,3 @@ +alter table Habits add column target_type integer not null default 0; +alter table Habits add column target_value real not null default 0; +alter table Habits add column unit text not null default ""; \ No newline at end of file diff --git a/app/src/main/java/org/isoron/uhabits/activities/habits/edit/CreateBooleanHabitDialog.java b/app/src/main/java/org/isoron/uhabits/activities/habits/edit/CreateBooleanHabitDialog.java index 7d94f57c5..4ed21fea7 100644 --- a/app/src/main/java/org/isoron/uhabits/activities/habits/edit/CreateBooleanHabitDialog.java +++ b/app/src/main/java/org/isoron/uhabits/activities/habits/edit/CreateBooleanHabitDialog.java @@ -39,8 +39,7 @@ public class CreateBooleanHabitDialog extends BooleanHabitDialog { modifiedHabit = modelFactory.buildHabit(); modifiedHabit.setFrequency(Frequency.DAILY); - modifiedHabit.setColor( - prefs.getDefaultHabitColor(modifiedHabit.getColor())); + modifiedHabit.setColor(prefs.getDefaultHabitColor(modifiedHabit.getColor())); } @Override diff --git a/app/src/main/java/org/isoron/uhabits/activities/habits/edit/CreateNumericalHabitDialog.java b/app/src/main/java/org/isoron/uhabits/activities/habits/edit/CreateNumericalHabitDialog.java index 459a94aa1..c8754f72c 100644 --- a/app/src/main/java/org/isoron/uhabits/activities/habits/edit/CreateNumericalHabitDialog.java +++ b/app/src/main/java/org/isoron/uhabits/activities/habits/edit/CreateNumericalHabitDialog.java @@ -42,6 +42,7 @@ public class CreateNumericalHabitDialog extends NumericalHabitDialog modifiedHabit.setColor( prefs.getDefaultHabitColor(modifiedHabit.getColor())); modifiedHabit.setType(Habit.NUMBER_HABIT); + modifiedHabit.setTargetValue(100); } @Override diff --git a/app/src/main/java/org/isoron/uhabits/activities/habits/edit/EditNumericalHabitDialog.java b/app/src/main/java/org/isoron/uhabits/activities/habits/edit/EditNumericalHabitDialog.java new file mode 100644 index 000000000..87ba58a44 --- /dev/null +++ b/app/src/main/java/org/isoron/uhabits/activities/habits/edit/EditNumericalHabitDialog.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2016 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Loop Habit Tracker is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +package org.isoron.uhabits.activities.habits.edit; + +import org.isoron.uhabits.*; +import org.isoron.uhabits.commands.*; + +public class EditNumericalHabitDialog extends NumericalHabitDialog +{ + @Override + protected int getTitle() + { + return R.string.edit_habit; + } + + @Override + protected void initializeHabits() + { + Long habitId = (Long) getArguments().get("habitId"); + if (habitId == null) + throw new IllegalArgumentException("habitId must be specified"); + + originalHabit = habitList.getById(habitId); + if (originalHabit == null) + throw new IllegalStateException("habit is null"); + + modifiedHabit = modelFactory.buildHabit(); + modifiedHabit.copyFrom(originalHabit); + } + + @Override + protected void saveHabit() + { + Command command = appComponent.getEditHabitCommandFactory(). + create(habitList, originalHabit, modifiedHabit); + commandRunner.execute(command, originalHabit.getId()); + } +} diff --git a/app/src/main/java/org/isoron/uhabits/activities/habits/edit/EditNumericalHabitDialogFactory.java b/app/src/main/java/org/isoron/uhabits/activities/habits/edit/EditNumericalHabitDialogFactory.java new file mode 100644 index 000000000..084b61434 --- /dev/null +++ b/app/src/main/java/org/isoron/uhabits/activities/habits/edit/EditNumericalHabitDialogFactory.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2016 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Loop Habit Tracker is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +package org.isoron.uhabits.activities.habits.edit; + +import android.os.*; +import android.support.annotation.*; + +import org.isoron.uhabits.models.*; + +import javax.inject.*; + +public class EditNumericalHabitDialogFactory +{ + @Inject + public EditNumericalHabitDialogFactory() + { + } + + public EditNumericalHabitDialog create(@NonNull Habit habit) + { + if (habit.getId() == null) + throw new IllegalArgumentException("habit not saved"); + + EditNumericalHabitDialog dialog = new EditNumericalHabitDialog(); + Bundle args = new Bundle(); + args.putLong("habitId", habit.getId()); + dialog.setArguments(args); + return dialog; + } +} diff --git a/app/src/main/java/org/isoron/uhabits/activities/habits/edit/NumericalHabitDialog.java b/app/src/main/java/org/isoron/uhabits/activities/habits/edit/NumericalHabitDialog.java index 3425f6663..87e90c7f5 100644 --- a/app/src/main/java/org/isoron/uhabits/activities/habits/edit/NumericalHabitDialog.java +++ b/app/src/main/java/org/isoron/uhabits/activities/habits/edit/NumericalHabitDialog.java @@ -22,10 +22,8 @@ package org.isoron.uhabits.activities.habits.edit; import android.os.*; import android.support.annotation.*; import android.support.v7.app.*; -import android.text.format.*; import android.view.*; - -import com.android.datetimepicker.time.*; +import android.widget.*; import org.isoron.uhabits.*; import org.isoron.uhabits.R; @@ -34,11 +32,12 @@ import org.isoron.uhabits.activities.common.dialogs.*; import org.isoron.uhabits.commands.*; import org.isoron.uhabits.models.*; import org.isoron.uhabits.preferences.*; - -import java.util.*; +import org.isoron.uhabits.utils.*; import butterknife.*; +import static org.isoron.uhabits.R.id.*; + public abstract class NumericalHabitDialog extends AppCompatDialogFragment { @Nullable @@ -47,9 +46,6 @@ public abstract class NumericalHabitDialog extends AppCompatDialogFragment @Nullable protected Habit modifiedHabit; - @Nullable - protected BaseDialogHelper helper; - protected Preferences prefs; protected CommandRunner commandRunner; @@ -62,6 +58,12 @@ public abstract class NumericalHabitDialog extends AppCompatDialogFragment private ColorPickerDialogFactory colorPickerDialogFactory; + private NumericalHabitDialogHelper helper; + + private boolean tvDescriptionInitialized = false; + + private boolean tvUnitInitialized = false; + @Override public int getTheme() { @@ -72,10 +74,9 @@ public abstract class NumericalHabitDialog extends AppCompatDialogFragment public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - BaseActivity activity = (BaseActivity) getActivity(); - colorPickerDialogFactory = - activity.getComponent().getColorPickerDialogFactory(); + ActivityComponent component = activity.getComponent(); + colorPickerDialogFactory = component.getColorPickerDialogFactory(); } @Override @@ -97,7 +98,7 @@ public abstract class NumericalHabitDialog extends AppCompatDialogFragment ButterKnife.bind(this, view); - helper = new BaseDialogHelper(this, view); + helper = new NumericalHabitDialogHelper(this, view); getDialog().setTitle(getTitle()); initializeHabits(); restoreSavedInstance(savedInstanceState); @@ -106,18 +107,10 @@ public abstract class NumericalHabitDialog extends AppCompatDialogFragment } @Override - @SuppressWarnings("ConstantConditions") public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putInt("color", modifiedHabit.getColor()); - if (modifiedHabit.hasReminder()) - { - Reminder reminder = modifiedHabit.getReminder(); - outState.putInt("reminderMin", reminder.getMinute()); - outState.putInt("reminderHour", reminder.getHour()); - outState.putInt("reminderDays", reminder.getDays().toInteger()); - } } protected abstract int getTitle(); @@ -127,73 +120,60 @@ public abstract class NumericalHabitDialog extends AppCompatDialogFragment protected void restoreSavedInstance(@Nullable Bundle bundle) { if (bundle == null) return; - modifiedHabit.setColor( - bundle.getInt("color", modifiedHabit.getColor())); - - modifiedHabit.setReminder(null); + if (modifiedHabit == null) return; - int hour = (bundle.getInt("reminderHour", -1)); - int minute = (bundle.getInt("reminderMin", -1)); - int days = (bundle.getInt("reminderDays", -1)); + int color = bundle.getInt("color", modifiedHabit.getColor()); - if (hour >= 0 && minute >= 0) - { - Reminder reminder = - new Reminder(hour, minute, new WeekdayList(days)); - modifiedHabit.setReminder(reminder); - } + modifiedHabit.setColor(color); + modifiedHabit.setReminder(null); } protected abstract void saveHabit(); - @OnClick(R.id.buttonDiscard) - void onButtonDiscardClick() + @OnFocusChange(tvDescription) + void clearDefaultDescription(boolean focused) { - dismiss(); + if (!focused || tvDescriptionInitialized) return; + tvDescriptionInitialized = true; + clearDefaultText(helper.tvDescription); } - @OnClick(R.id.tvReminderTime) - @SuppressWarnings("ConstantConditions") - void onDateSpinnerClick() + private void clearDefaultText(TextView textView) { - int defaultHour = 8; - int defaultMin = 0; + StyledResources sr = new StyledResources(getContext()); + int color = sr.getColor(R.attr.highContrastTextColor); + textView.setText(""); + textView.setTextColor(color); + } - if (modifiedHabit.hasReminder()) - { - Reminder reminder = modifiedHabit.getReminder(); - defaultHour = reminder.getHour(); - defaultMin = reminder.getMinute(); - } + @OnFocusChange(tvUnit) + void clearDefaultUnit(boolean focused) + { + if (!focused || tvUnitInitialized) return; + tvUnitInitialized = true; + clearDefaultText(helper.tvUnit); + } - showTimePicker(defaultHour, defaultMin); + @OnClick(R.id.buttonDiscard) + void onButtonDiscardClick() + { + dismiss(); } @OnClick(R.id.buttonSave) void onSaveButtonClick() { - helper.parseFormIntoHabit(modifiedHabit); + helper.parseForm(modifiedHabit); if (!helper.validate(modifiedHabit)) return; saveHabit(); dismiss(); } - @OnClick(R.id.tvReminderDays) - @SuppressWarnings("ConstantConditions") - void onWeekdayClick() - { - if (!modifiedHabit.hasReminder()) return; - Reminder reminder = modifiedHabit.getReminder(); - - WeekdayPickerDialog dialog = new WeekdayPickerDialog(); - dialog.setListener(new OnWeekdaysPickedListener()); - dialog.setSelectedDays(reminder.getDays().toArray()); - dialog.show(getFragmentManager(), "weekdayPicker"); - } - @OnClick(R.id.buttonPickColor) void showColorPicker() { + if (modifiedHabit == null) return; + int color = modifiedHabit.getColor(); ColorPickerDialog picker = colorPickerDialogFactory.create(color); @@ -206,55 +186,4 @@ public abstract class NumericalHabitDialog extends AppCompatDialogFragment picker.show(getFragmentManager(), "picker"); } - - private void showTimePicker(int defaultHour, int defaultMin) - { - boolean is24HourMode = DateFormat.is24HourFormat(getContext()); - TimePickerDialog timePicker = - TimePickerDialog.newInstance(new OnTimeSetListener(), defaultHour, - defaultMin, is24HourMode); - timePicker.show(getFragmentManager(), "timePicker"); - } - - private class OnTimeSetListener - implements TimePickerDialog.OnTimeSetListener - { - @Override - public void onTimeCleared(RadialPickerLayout view) - { - modifiedHabit.clearReminder(); - helper.populateReminderFields(modifiedHabit); - } - - @Override - public void onTimeSet(RadialPickerLayout view, int hour, int minute) - { - Reminder reminder = - new Reminder(hour, minute, WeekdayList.EVERY_DAY); - modifiedHabit.setReminder(reminder); - helper.populateReminderFields(modifiedHabit); - } - } - - private class OnWeekdaysPickedListener - implements WeekdayPickerDialog.OnWeekdaysPickedListener - { - @Override - public void onWeekdaysPicked(boolean[] selectedDays) - { - if (isSelectionEmpty(selectedDays)) Arrays.fill(selectedDays, true); - - Reminder oldReminder = modifiedHabit.getReminder(); - modifiedHabit.setReminder( - new Reminder(oldReminder.getHour(), oldReminder.getMinute(), - new WeekdayList(selectedDays))); - helper.populateReminderFields(modifiedHabit); - } - - private boolean isSelectionEmpty(boolean[] selectedDays) - { - for (boolean d : selectedDays) if (d) return false; - return true; - } - } } diff --git a/app/src/main/java/org/isoron/uhabits/activities/habits/edit/NumericalHabitDialogHelper.java b/app/src/main/java/org/isoron/uhabits/activities/habits/edit/NumericalHabitDialogHelper.java new file mode 100644 index 000000000..47bda0c08 --- /dev/null +++ b/app/src/main/java/org/isoron/uhabits/activities/habits/edit/NumericalHabitDialogHelper.java @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2016 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Loop Habit Tracker is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +package org.isoron.uhabits.activities.habits.edit; + +import android.support.v4.app.*; +import android.view.*; +import android.widget.*; + +import org.isoron.uhabits.R; +import org.isoron.uhabits.models.*; +import org.isoron.uhabits.utils.*; + +import butterknife.*; + +public class NumericalHabitDialogHelper +{ + private DialogFragment frag; + + @BindView(R.id.tvName) + TextView tvName; + + @BindView(R.id.tvDescription) + TextView tvDescription; + + @BindView(R.id.tvUnit) + TextView tvUnit; + + @BindView(R.id.tvTargetCount) + TextView tvTargetValue; + + @BindView(R.id.tvTargetType) + Spinner tvTargetType; + + public NumericalHabitDialogHelper(DialogFragment frag, View view) + { + this.frag = frag; + ButterKnife.bind(this, view); + } + + public void parseForm(Habit habit) + { + habit.setName(tvName.getText().toString().trim()); + habit.setDescription(tvDescription.getText().toString().trim()); + habit.setTargetType(tvTargetType.getSelectedItemPosition()); + habit.setTargetValue( + Double.parseDouble(tvTargetValue.getText().toString())); + habit.setUnit(tvUnit.getText().toString().trim()); + } + + public void populateColor(int paletteColor) + { + tvName.setTextColor( + ColorUtils.getColor(frag.getContext(), paletteColor)); + } + + public void populateForm(final Habit habit) + { + tvName.setText(habit.getName()); + + if(!habit.getDescription().isEmpty()) + tvDescription.setText(habit.getDescription()); + + if(!habit.getUnit().isEmpty()) + tvUnit.setText(habit.getUnit()); + + tvTargetType.setSelection(habit.getTargetType()); + tvTargetValue.setText(String.format("%.0f", habit.getTargetValue())); + populateColor(habit.getColor()); + } + + public boolean validate(Habit habit) + { + Boolean valid = true; + if (!validateName(habit)) valid = false; + if (!validateTargetValue()) valid = false; + return valid; + } + + private boolean validateTargetValue() + { + double value = Double.parseDouble(tvTargetValue.getText().toString()); + if(value <= 0) + { + tvTargetValue.setError(frag.getString(R.string.validation_number_should_be_positive)); + return false; + } + return true; + } + + private Boolean validateName(Habit habit) + { + if (habit.getName().isEmpty()) + { + tvName.setError(frag.getString(R.string.validation_name_should_not_be_blank)); + return false; + } + + return true; + } +} diff --git a/app/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsController.java b/app/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsController.java index db0b8cbf5..3c78c3ad1 100644 --- a/app/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsController.java +++ b/app/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsController.java @@ -83,8 +83,7 @@ public class ListHabitsController @NonNull ReminderScheduler reminderScheduler, @NonNull TaskRunner taskRunner, @NonNull WidgetUpdater widgetUpdater, - @NonNull - ImportDataTaskFactory importTaskFactory, + @NonNull ImportDataTaskFactory importTaskFactory, @NonNull ExportCSVTaskFactory exportCSVFactory, @NonNull ExportDBTaskFactory exportDBFactory) { diff --git a/app/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.java b/app/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.java index afc3cc94b..c0fcae8fa 100644 --- a/app/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.java +++ b/app/src/main/java/org/isoron/uhabits/activities/habits/list/ListHabitsScreen.java @@ -97,8 +97,12 @@ public class ListHabitsScreen extends BaseScreen @NonNull private final ThemeSwitcher themeSwitcher; + @NonNull private CreateNumericalHabitDialogFactory createNumericalHabitDialogFactory; + @NonNull + private EditNumericalHabitDialogFactory editNumericalHabitDialogFactory; + @Inject public ListHabitsScreen(@NonNull BaseActivity activity, @NonNull CommandRunner commandRunner, @@ -111,6 +115,7 @@ public class ListHabitsScreen extends BaseScreen @NonNull FilePickerDialogFactory filePickerDialogFactory, @NonNull ColorPickerDialogFactory colorPickerFactory, @NonNull EditBooleanHabitDialogFactory editBooleanHabitDialogFactory, + @NonNull EditNumericalHabitDialogFactory editNumericalHabitDialogFactory, @NonNull CreateNumericalHabitDialogFactory createNumericalHabitDialogFactory) { super(activity); @@ -121,6 +126,7 @@ public class ListHabitsScreen extends BaseScreen this.createNumericalHabitDialogFactory = createNumericalHabitDialogFactory; this.createBooleanHabitDialogFactory = createBooleanHabitDialogFactory; this.editBooleanHabitDialogFactory = editBooleanHabitDialogFactory; + this.editNumericalHabitDialogFactory = editNumericalHabitDialogFactory; this.dirFinder = dirFinder; this.filePickerDialogFactory = filePickerDialogFactory; this.intentFactory = intentFactory; @@ -214,9 +220,18 @@ public class ListHabitsScreen extends BaseScreen public void showEditHabitScreen(Habit habit) { - EditBooleanHabitDialog dialog; - dialog = editBooleanHabitDialogFactory.create(habit); - activity.showDialog(dialog, "editHabit"); + if(habit.isNumerical()) + { + EditNumericalHabitDialog dialog; + dialog = editNumericalHabitDialogFactory.create(habit); + activity.showDialog(dialog, "editNumericalHabit"); + } + else + { + EditBooleanHabitDialog dialog; + dialog = editBooleanHabitDialogFactory.create(habit); + activity.showDialog(dialog, "editHabit"); + } } public void showFAQScreen() diff --git a/app/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.java b/app/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.java index f6cf68259..f0a2852d4 100644 --- a/app/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.java +++ b/app/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardListView.java @@ -95,6 +95,8 @@ public class HabitCardListView extends RecyclerView cardView.setButtonCount(checkmarkCount); cardView.setDataOffset(dataOffset); cardView.setScore(score); + cardView.setUnit(habit.getUnit()); + cardView.setThreshold(habit.getTargetValue()); if (controller != null) setupCardViewController(holder); return cardView; } diff --git a/app/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.java b/app/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.java index 5c6bebdfa..8b86f3f78 100644 --- a/app/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.java +++ b/app/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.java @@ -101,12 +101,9 @@ public class HabitCardView extends FrameLayout numberPanel.setButtonCount(buttonCount); } - public void setValues(int values[]) + public void setThreshold(double threshold) { - checkmarkPanel.setValues(values); - numberPanel.setValues(values); - numberPanel.setThreshold(10); - postInvalidate(); + numberPanel.setThreshold(threshold); } public void setController(Controller controller) @@ -153,6 +150,19 @@ public class HabitCardView extends FrameLayout updateBackground(isSelected); } + public void setUnit(String unit) + { + numberPanel.setUnit(unit); + } + + public void setValues(int values[]) + { + checkmarkPanel.setValues(values); + numberPanel.setValues(values); + numberPanel.setThreshold(10); + postInvalidate(); + } + public void triggerRipple(long timestamp) { long today = DateUtils.getStartOfToday(); diff --git a/app/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.java b/app/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.java index 07594cb6e..ccb2026e9 100644 --- a/app/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.java +++ b/app/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberButtonView.java @@ -46,7 +46,7 @@ public class NumberButtonView extends View private int value; - private int threshold; + private double threshold; private String unit; @@ -86,6 +86,11 @@ public class NumberButtonView extends View } } + /** + * + * @param v + * @return + */ private static String formatValue(int v) { double fv = (double) v; @@ -111,7 +116,7 @@ public class NumberButtonView extends View setOnLongClickListener(v -> controller.onLongClick()); } - public void setThreshold(int threshold) + public void setThreshold(double threshold) { this.threshold = threshold; postInvalidate(); @@ -146,10 +151,9 @@ public class NumberButtonView extends View String fv = formatValue(value); rect.set(0, 0, getWidth(), getHeight()); - rect.offset(0, - 0.1f * em); canvas.drawText(fv, rect.centerX(), rect.centerY(), pBold); - rect.offset(0, 1.25f * em); + rect.offset(0, 1.2f * em); canvas.drawText(unit, rect.centerX(), rect.centerY(), pRegular); } diff --git a/app/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.java b/app/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.java index e21bfa263..5723b9e1e 100644 --- a/app/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.java +++ b/app/src/main/java/org/isoron/uhabits/activities/habits/list/views/NumberPanelView.java @@ -49,7 +49,7 @@ public class NumberPanelView extends LinearLayout private int values[]; - private int threshold; + private double threshold; private int nButtons; @@ -98,7 +98,7 @@ public class NumberPanelView extends LinearLayout int values[] = new int[nButtons]; for(int i = 0; i < nButtons; i++) - values[i] = new Random().nextInt(threshold * 3); + values[i] = new Random().nextInt((int)(threshold * 3)); setValues(values); } @@ -153,7 +153,7 @@ public class NumberPanelView extends LinearLayout setupButtons(); } - public void setThreshold(int threshold) + public void setThreshold(double threshold) { this.threshold = threshold; setupButtons(); diff --git a/app/src/main/java/org/isoron/uhabits/models/Habit.java b/app/src/main/java/org/isoron/uhabits/models/Habit.java index 256e05add..d9b8c9d21 100644 --- a/app/src/main/java/org/isoron/uhabits/models/Habit.java +++ b/app/src/main/java/org/isoron/uhabits/models/Habit.java @@ -33,6 +33,10 @@ import javax.inject.*; */ public class Habit { + public static final int AT_LEAST = 0; + + public static final int AT_MOST = 1; + public static final String HABIT_URI_FORMAT = "content://org.isoron.uhabits/habit/%d"; @@ -52,10 +56,8 @@ public class Habit @NonNull private Frequency frequency; - @NonNull - private Integer color; + private int color; - @NonNull private boolean archived; @NonNull @@ -64,17 +66,24 @@ public class Habit @NonNull private ScoreList scores; + private int targetType; + + private double targetValue; + + private int type; + @NonNull private RepetitionList repetitions; @NonNull private CheckmarkList checkmarks; + @NonNull + private String unit; + @Nullable private Reminder reminder; - private int type; - private ModelObservable observable = new ModelObservable(); /** @@ -90,6 +99,11 @@ public class Habit this.archived = false; this.frequency = new Frequency(3, 7); this.type = YES_NO_HABIT; + this.name = ""; + this.description = ""; + this.targetType = AT_LEAST; + this.targetValue = 0; + this.unit = ""; checkmarks = factory.buildCheckmarkList(this); streaks = factory.buildStreakList(this); @@ -120,6 +134,9 @@ public class Habit this.frequency = model.frequency; this.reminder = model.reminder; this.type = model.type; + this.targetValue = model.targetValue; + this.targetType = model.targetType; + this.unit = model.unit; observable.notifyListeners(); } @@ -240,6 +257,29 @@ public class Habit return streaks; } + public int getTargetType() + { + return targetType; + } + + public void setTargetType(int targetType) + { + if (targetType != AT_LEAST && targetType != AT_MOST) + throw new IllegalArgumentException(); + this.targetType = targetType; + } + + public double getTargetValue() + { + return targetValue; + } + + public void setTargetValue(double targetValue) + { + if(targetValue < 0) throw new IllegalArgumentException(); + this.targetValue = targetValue; + } + public int getType() { return type; @@ -253,6 +293,17 @@ public class Habit this.type = type; } + @NonNull + public String getUnit() + { + return unit; + } + + public void setUnit(@NonNull String unit) + { + this.unit = unit; + } + /** * Returns the public URI that identifies this habit * @@ -306,6 +357,9 @@ public class Habit .append("color", color) .append("archived", archived) .append("type", type) + .append("targetType", targetType) + .append("targetValue", targetValue) + .append("unit", unit) .toString(); } } diff --git a/app/src/main/java/org/isoron/uhabits/models/sqlite/records/HabitRecord.java b/app/src/main/java/org/isoron/uhabits/models/sqlite/records/HabitRecord.java index 7b2c672b7..f60e3fe7e 100644 --- a/app/src/main/java/org/isoron/uhabits/models/sqlite/records/HabitRecord.java +++ b/app/src/main/java/org/isoron/uhabits/models/sqlite/records/HabitRecord.java @@ -42,7 +42,8 @@ public class HabitRecord extends Model implements SQLiteRecord public static String SELECT = "select id, color, description, freq_den, freq_num, " + "name, position, reminder_hour, reminder_min, " + - "highlight, archived, reminder_days, type from habits "; + "highlight, archived, reminder_days, type, target_type, " + + "target_value, unit from habits "; @Column(name = "name") public String name; @@ -83,6 +84,15 @@ public class HabitRecord extends Model implements SQLiteRecord @Column(name = "type") public Integer type; + @Column(name = "target_value") + public Double targetValue; + + @Column(name = "target_type") + public Integer targetType; + + @Column(name = "unit") + public String unit; + public HabitRecord() { } @@ -148,6 +158,9 @@ public class HabitRecord extends Model implements SQLiteRecord this.color = model.getColor(); this.archived = model.isArchived() ? 1 : 0; this.type = model.getType(); + this.targetType = model.getTargetType(); + this.targetValue = model.getTargetValue(); + this.unit = model.getUnit(); Frequency freq = model.getFrequency(); this.freqNum = freq.getNumerator(); @@ -181,6 +194,9 @@ public class HabitRecord extends Model implements SQLiteRecord archived = c.getInt(10); reminderDays = c.getInt(11); type = c.getInt(12); + targetType = c.getInt(13); + targetValue = c.getDouble(14); + unit = c.getString(15); } public void copyTo(Habit habit) @@ -192,6 +208,9 @@ public class HabitRecord extends Model implements SQLiteRecord habit.setArchived(this.archived != 0); habit.setId(this.getId()); habit.setType(this.type); + habit.setTargetType(this.targetType); + habit.setTargetValue(this.targetValue); + habit.setUnit(this.unit); if (reminderHour != null && reminderMin != null) { diff --git a/app/src/main/res/layout/edit_numerical_habit.xml b/app/src/main/res/layout/edit_numerical_habit.xml index e9d3f59f9..7137d07bb 100644 --- a/app/src/main/res/layout/edit_numerical_habit.xml +++ b/app/src/main/res/layout/edit_numerical_habit.xml @@ -16,7 +16,6 @@ ~ You should have received a copy of the GNU General Public License along ~ with this program. If not, see . --> - - - - - + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + @@ -87,17 +117,14 @@ style="?android:attr/buttonBarStyle" android:layout_width="match_parent" android:layout_height="wrap_content" - android:gravity="end" - android:paddingEnd="16dp" - android:paddingLeft="0dp" - android:paddingRight="16dp" - android:paddingStart="0dp"> + android:gravity="end">