Refactor habit creation dialogs

pull/157/merge
Alinson S. Xavier 9 years ago
parent 19f4a19dba
commit fe7e8ef039

@ -182,7 +182,7 @@ public class MainActivityActions
try
{
onView(allOf(withId(R.id.sFrequency),
onView(allOf(withId(R.id.spinner),
withEffectiveVisibility(VISIBLE))).perform(click());
onData(allOf(instanceOf(String.class), startsWith("Custom")))
.inRoot(isPlatformPopup())
@ -193,7 +193,7 @@ public class MainActivityActions
// ignored
}
onView(withId(R.id.tvFreqNum)).perform(replaceText(num));
onView(withId(R.id.tvFreqDen)).perform(replaceText(den));
onView(withId(R.id.numerator)).perform(replaceText(num));
onView(withId(R.id.denominator)).perform(replaceText(den));
}
}

@ -26,6 +26,7 @@ import android.support.v7.app.AlertDialog;
import android.support.v7.app.*;
import org.isoron.uhabits.*;
import org.isoron.uhabits.models.*;
import org.isoron.uhabits.utils.*;
/**
@ -35,7 +36,6 @@ public class WeekdayPickerDialog extends AppCompatDialogFragment implements
DialogInterface.OnMultiChoiceClickListener,
DialogInterface.OnClickListener
{
private boolean[] selectedDays;
private OnWeekdaysPickedListener listener;
@ -49,7 +49,8 @@ public class WeekdayPickerDialog extends AppCompatDialogFragment implements
@Override
public void onClick(DialogInterface dialog, int which)
{
if (listener != null) listener.onWeekdaysPicked(selectedDays);
if (listener != null)
listener.onWeekdaysSet(new WeekdayList(selectedDays));
}
@Override
@ -73,13 +74,13 @@ public class WeekdayPickerDialog extends AppCompatDialogFragment implements
this.listener = listener;
}
public void setSelectedDays(boolean[] selectedDays)
public void setSelectedDays(WeekdayList days)
{
this.selectedDays = selectedDays;
this.selectedDays = days.toArray();
}
public interface OnWeekdaysPickedListener
{
void onWeekdaysPicked(boolean[] selectedDays);
void onWeekdaysSet(WeekdayList days);
}
}

@ -1,212 +0,0 @@
/*
* 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.activities.habits.edit;
import android.annotation.*;
import android.support.annotation.*;
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 BaseDialogHelper
{
private DialogFragment frag;
@BindView(R.id.tvName)
TextView tvName;
@BindView(R.id.tvDescription)
TextView tvDescription;
@Nullable
@BindView(R.id.tvFreqNum)
TextView tvFreqNum;
@Nullable
@BindView(R.id.tvFreqDen)
TextView tvFreqDen;
@BindView(R.id.tvReminderTime)
TextView tvReminderTime;
@BindView(R.id.tvReminderDays)
TextView tvReminderDays;
@Nullable
@BindView(R.id.sFrequency)
Spinner sFrequency;
@Nullable
@BindView(R.id.llCustomFrequency)
ViewGroup llCustomFrequency;
@BindView(R.id.llReminderDays)
ViewGroup llReminderDays;
public BaseDialogHelper(DialogFragment frag, View view)
{
this.frag = frag;
ButterKnife.bind(this, view);
}
protected void populateForm(final Habit habit)
{
tvName.setText(habit.getName());
tvDescription.setText(habit.getDescription());
populateColor(habit.getColor());
populateFrequencyFields(habit);
populateReminderFields(habit);
}
void parseFormIntoHabit(Habit habit)
{
habit.setName(tvName.getText().toString().trim());
habit.setDescription(tvDescription.getText().toString().trim());
if (tvFreqDen != null && tvFreqNum != null)
{
String freqNum = tvFreqNum.getText().toString();
String freqDen = tvFreqDen.getText().toString();
if (!freqNum.isEmpty() && !freqDen.isEmpty())
{
int numerator = Integer.parseInt(freqNum);
int denominator = Integer.parseInt(freqDen);
habit.setFrequency(new Frequency(numerator, denominator));
}
}
}
void populateColor(int paletteColor)
{
tvName.setTextColor(
ColorUtils.getColor(frag.getContext(), paletteColor));
}
@SuppressLint("SetTextI18n")
void populateFrequencyFields(Habit habit)
{
if (tvFreqNum == null) return;
if (tvFreqDen == null) return;
int quickSelectPosition = -1;
Frequency freq = habit.getFrequency();
if (freq.equals(Frequency.DAILY)) quickSelectPosition = 0;
else if (freq.equals(Frequency.WEEKLY)) quickSelectPosition = 1;
else if (freq.equals(Frequency.TWO_TIMES_PER_WEEK))
quickSelectPosition = 2;
else if (freq.equals(Frequency.FIVE_TIMES_PER_WEEK))
quickSelectPosition = 3;
if (quickSelectPosition >= 0)
showSimplifiedFrequency(quickSelectPosition);
else showCustomFrequency();
tvFreqNum.setText(Integer.toString(freq.getNumerator()));
tvFreqDen.setText(Integer.toString(freq.getDenominator()));
}
@SuppressWarnings("ConstantConditions")
void populateReminderFields(Habit habit)
{
if (!habit.hasReminder())
{
tvReminderTime.setText(R.string.reminder_off);
llReminderDays.setVisibility(View.GONE);
return;
}
Reminder reminder = habit.getReminder();
String time =
DateUtils.formatTime(frag.getContext(), reminder.getHour(),
reminder.getMinute());
tvReminderTime.setText(time);
llReminderDays.setVisibility(View.VISIBLE);
boolean weekdays[] = reminder.getDays().toArray();
tvReminderDays.setText(
DateUtils.formatWeekdayList(frag.getContext(), weekdays));
}
private void showCustomFrequency()
{
if(sFrequency == null) return;
if(llCustomFrequency == null) return;
sFrequency.setVisibility(View.GONE);
llCustomFrequency.setVisibility(View.VISIBLE);
}
@SuppressLint("SetTextI18n")
private void showSimplifiedFrequency(int quickSelectPosition)
{
if(sFrequency == null) return;
if(llCustomFrequency == null) return;
sFrequency.setVisibility(View.VISIBLE);
sFrequency.setSelection(quickSelectPosition);
llCustomFrequency.setVisibility(View.GONE);
}
boolean validate(Habit habit)
{
Boolean valid = true;
if (habit.getName().length() == 0)
{
tvName.setError(
frag.getString(R.string.validation_name_should_not_be_blank));
valid = false;
}
Frequency freq = habit.getFrequency();
if (tvFreqNum != null && tvFreqDen != null)
{
if (freq.getNumerator() <= 0)
{
tvFreqNum.setError(frag.getString(
R.string.validation_number_should_be_positive));
valid = false;
}
if (freq.getNumerator() > freq.getDenominator())
{
tvFreqNum.setError(frag.getString(
R.string.validation_at_most_one_rep_per_day));
valid = false;
}
}
return valid;
}
}

@ -31,24 +31,20 @@ import org.isoron.uhabits.*;
import org.isoron.uhabits.R;
import org.isoron.uhabits.activities.*;
import org.isoron.uhabits.activities.common.dialogs.*;
import org.isoron.uhabits.activities.habits.edit.views.*;
import org.isoron.uhabits.commands.*;
import org.isoron.uhabits.models.*;
import org.isoron.uhabits.preferences.*;
import java.util.*;
import butterknife.*;
public abstract class BooleanHabitDialog extends AppCompatDialogFragment
{
@Nullable
protected Habit originalHabit;
@Nullable
protected Habit modifiedHabit;
@Nullable
protected BaseDialogHelper helper;
protected BooleanHabitDialogHelper helper;
protected Preferences prefs;
@ -83,7 +79,8 @@ public abstract class BooleanHabitDialog extends AppCompatDialogFragment
ViewGroup container,
Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.edit_boolean_habit, container, false);
View view =
inflater.inflate(R.layout.edit_boolean_habit, container, false);
HabitsApplication app =
(HabitsApplication) getContext().getApplicationContext();
@ -96,23 +93,40 @@ public abstract class BooleanHabitDialog extends AppCompatDialogFragment
ButterKnife.bind(this, view);
helper = new BaseDialogHelper(this, view);
helper = new BooleanHabitDialogHelper(this, view);
getDialog().setTitle(getTitle());
initializeHabits();
restoreSavedInstance(savedInstanceState);
helper.populateForm(modifiedHabit);
return view;
}
@OnItemSelected(R.id.sFrequency)
public void onFrequencySelected(int position)
{
if (position < 0 || position > 4) throw new IllegalArgumentException();
int freqNums[] = { 1, 1, 2, 5, 3 };
int freqDens[] = { 1, 7, 7, 7, 7 };
modifiedHabit.setFrequency(
new Frequency(freqNums[position], freqDens[position]));
helper.populateFrequencyFields(modifiedHabit);
helper.frequencyPanel.setFrequency(modifiedHabit.getFrequency());
if (modifiedHabit.hasReminder())
helper.reminderPanel.setReminder(modifiedHabit.getReminder());
helper.reminderPanel.setController(new ReminderPanel.Controller()
{
@Override
public void onTimeClicked(int currentHour, int currentMin)
{
TimePickerDialog timePicker;
boolean is24HourMode = DateFormat.is24HourFormat(getContext());
timePicker = TimePickerDialog.newInstance(helper.reminderPanel,
currentHour, currentMin, is24HourMode);
timePicker.show(getFragmentManager(), "timePicker");
}
@Override
public void onWeekdayClicked(WeekdayList currentDays)
{
WeekdayPickerDialog dialog = new WeekdayPickerDialog();
dialog.setListener(helper.reminderPanel);
dialog.setSelectedDays(currentDays);
dialog.show(getFragmentManager(), "weekdayPicker");
}
});
return view;
}
@Override
@ -121,13 +135,6 @@ public abstract class BooleanHabitDialog extends AppCompatDialogFragment
{
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();
@ -139,19 +146,6 @@ public abstract class BooleanHabitDialog extends AppCompatDialogFragment
if (bundle == null) return;
modifiedHabit.setColor(
bundle.getInt("color", modifiedHabit.getColor()));
modifiedHabit.setReminder(null);
int hour = (bundle.getInt("reminderHour", -1));
int minute = (bundle.getInt("reminderMin", -1));
int days = (bundle.getInt("reminderDays", -1));
if (hour >= 0 && minute >= 0)
{
Reminder reminder =
new Reminder(hour, minute, new WeekdayList(days));
modifiedHabit.setReminder(reminder);
}
}
protected abstract void saveHabit();
@ -162,45 +156,20 @@ public abstract class BooleanHabitDialog extends AppCompatDialogFragment
dismiss();
}
@OnClick(R.id.tvReminderTime)
@SuppressWarnings("ConstantConditions")
void onDateSpinnerClick()
{
int defaultHour = 8;
int defaultMin = 0;
if (modifiedHabit.hasReminder())
{
Reminder reminder = modifiedHabit.getReminder();
defaultHour = reminder.getHour();
defaultMin = reminder.getMinute();
}
showTimePicker(defaultHour, defaultMin);
}
@OnClick(R.id.buttonSave)
void onSaveButtonClick()
{
helper.parseFormIntoHabit(modifiedHabit);
modifiedHabit.setReminder(helper.reminderPanel.getReminder());
modifiedHabit.setFrequency(helper.frequencyPanel.getFrequency());
if (!helper.frequencyPanel.validate()) return;
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()
{
@ -216,55 +185,4 @@ public abstract class BooleanHabitDialog 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;
}
}
}

@ -0,0 +1,86 @@
/*
* 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.activities.habits.edit;
import android.support.v4.app.*;
import android.view.*;
import android.widget.*;
import org.isoron.uhabits.R;
import org.isoron.uhabits.activities.habits.edit.views.*;
import org.isoron.uhabits.models.*;
import org.isoron.uhabits.utils.*;
import butterknife.*;
public class BooleanHabitDialogHelper
{
private DialogFragment frag;
@BindView(R.id.tvName)
TextView tvName;
@BindView(R.id.tvDescription)
TextView tvDescription;
@BindView(R.id.reminderPanel)
ReminderPanel reminderPanel;
@BindView(R.id.frequencyPanel)
FrequencyPanel frequencyPanel;
public BooleanHabitDialogHelper(DialogFragment frag, View view)
{
this.frag = frag;
ButterKnife.bind(this, view);
}
protected void populateForm(final Habit habit)
{
tvName.setText(habit.getName());
tvDescription.setText(habit.getDescription());
populateColor(habit.getColor());
}
void parseFormIntoHabit(Habit habit)
{
habit.setName(tvName.getText().toString().trim());
habit.setDescription(tvDescription.getText().toString().trim());
}
void populateColor(int paletteColor)
{
tvName.setTextColor(
ColorUtils.getColor(frag.getContext(), paletteColor));
}
boolean validate(Habit habit)
{
Boolean valid = true;
if (habit.getName().isEmpty())
{
tvName.setError(frag.getString(R.string.validation_name_should_not_be_blank));
valid = false;
}
return valid;
}
}

@ -25,6 +25,7 @@ import android.view.*;
import android.widget.*;
import org.isoron.uhabits.R;
import org.isoron.uhabits.activities.habits.edit.views.*;
import org.isoron.uhabits.models.*;
import org.isoron.uhabits.utils.*;

@ -17,7 +17,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.activities.habits.edit;
package org.isoron.uhabits.activities.habits.edit.views;
import android.content.*;
import android.support.annotation.*;
@ -31,6 +31,10 @@ import org.isoron.uhabits.utils.*;
import static org.isoron.uhabits.utils.AttributeSetUtils.*;
/**
* An EditText that shows an example usage when there is no text
* currently set. The example disappears when the widget gains focus.
*/
public class ExampleEditText extends EditText
implements View.OnFocusChangeListener
{

@ -0,0 +1,164 @@
/*
* 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.activities.habits.edit.views;
import android.annotation.*;
import android.content.*;
import android.content.res.*;
import android.support.annotation.*;
import android.util.*;
import android.view.*;
import android.widget.*;
import org.isoron.uhabits.R;
import org.isoron.uhabits.models.*;
import butterknife.*;
import static org.isoron.uhabits.R.id.*;
public class FrequencyPanel extends FrameLayout
{
@BindView(numerator)
TextView tvNumerator;
@BindView(R.id.denominator)
TextView tvDenominator;
@BindView(R.id.spinner)
Spinner spinner;
@BindView(R.id.customFreqPanel)
ViewGroup customFreqPanel;
public FrequencyPanel(@NonNull Context context,
@Nullable AttributeSet attrs)
{
super(context, attrs);
View view = inflate(context, R.layout.edit_habit_frequency, null);
ButterKnife.bind(this, view);
addView(view);
}
@NonNull
public Frequency getFrequency()
{
String freqNum = tvNumerator.getText().toString();
String freqDen = tvDenominator.getText().toString();
if (!freqNum.isEmpty() && !freqDen.isEmpty())
{
int numerator = Integer.parseInt(freqNum);
int denominator = Integer.parseInt(freqDen);
return new Frequency(numerator, denominator);
}
return Frequency.DAILY;
}
@SuppressLint("SetTextI18n")
public void setFrequency(@NonNull Frequency freq)
{
int position = getQuickSelectPosition(freq);
if (position >= 0) showSimplifiedFrequency(position);
else showCustomFrequency();
tvNumerator.setText(Integer.toString(freq.getNumerator()));
tvDenominator.setText(Integer.toString(freq.getDenominator()));
}
@OnItemSelected(R.id.spinner)
public void onFrequencySelected(int position)
{
if (position < 0 || position > 4) throw new IllegalArgumentException();
int freqNums[] = { 1, 1, 2, 5, 3 };
int freqDens[] = { 1, 7, 7, 7, 7 };
setFrequency(new Frequency(freqNums[position], freqDens[position]));
}
public boolean validate()
{
boolean valid = true;
Resources res = getResources();
String freqNum = tvNumerator.getText().toString();
String freqDen = tvDenominator.getText().toString();
if (freqDen.isEmpty())
{
tvDenominator.setError(
res.getString(R.string.validation_show_not_be_blank));
valid = false;
}
if (freqNum.isEmpty())
{
tvNumerator.setError(
res.getString(R.string.validation_show_not_be_blank));
valid = false;
}
if (!valid) return false;
int numerator = Integer.parseInt(freqNum);
int denominator = Integer.parseInt(freqDen);
if (numerator <= 0)
{
tvNumerator.setError(
res.getString(R.string.validation_number_should_be_positive));
valid = false;
}
if (numerator > denominator)
{
tvNumerator.setError(
res.getString(R.string.validation_at_most_one_rep_per_day));
valid = false;
}
return valid;
}
private int getQuickSelectPosition(@NonNull Frequency freq)
{
if (freq.equals(Frequency.DAILY)) return 0;
if (freq.equals(Frequency.WEEKLY)) return 1;
if (freq.equals(Frequency.TWO_TIMES_PER_WEEK)) return 2;
if (freq.equals(Frequency.FIVE_TIMES_PER_WEEK)) return 3;
return -1;
}
private void showCustomFrequency()
{
spinner.setVisibility(View.GONE);
customFreqPanel.setVisibility(View.VISIBLE);
}
private void showSimplifiedFrequency(int quickSelectPosition)
{
spinner.setVisibility(View.VISIBLE);
spinner.setSelection(quickSelectPosition);
customFreqPanel.setVisibility(View.GONE);
}
}

@ -0,0 +1,194 @@
/*
* 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.activities.habits.edit.views;
import android.content.*;
import android.os.*;
import android.support.annotation.*;
import android.util.*;
import android.view.*;
import android.widget.*;
import com.android.datetimepicker.time.*;
import org.isoron.uhabits.R;
import org.isoron.uhabits.activities.common.dialogs.*;
import org.isoron.uhabits.activities.common.views.*;
import org.isoron.uhabits.models.*;
import butterknife.*;
import static org.isoron.uhabits.utils.DateUtils.*;
public class ReminderPanel extends FrameLayout
implements TimePickerDialog.OnTimeSetListener,
WeekdayPickerDialog.OnWeekdaysPickedListener
{
@BindView(R.id.tvReminderTime)
TextView tvReminderTime;
@BindView(R.id.llReminderDays)
ViewGroup llReminderDays;
@BindView(R.id.tvReminderDays)
TextView tvReminderDays;
@Nullable
private Reminder reminder;
@NonNull
private Controller controller;
public ReminderPanel(@NonNull Context context, @Nullable AttributeSet attrs)
{
super(context, attrs);
View view = inflate(context, R.layout.edit_habit_reminder, null);
ButterKnife.bind(this, view);
addView(view);
controller = new Controller() {};
setReminder(null);
}
@Nullable
public Reminder getReminder()
{
return reminder;
}
public void setReminder(@Nullable Reminder reminder)
{
this.reminder = reminder;
if (reminder == null)
{
tvReminderTime.setText(R.string.reminder_off);
llReminderDays.setVisibility(View.GONE);
return;
}
Context ctx = getContext();
String time = formatTime(ctx, reminder.getHour(), reminder.getMinute());
tvReminderTime.setText(time);
llReminderDays.setVisibility(View.VISIBLE);
boolean weekdays[] = reminder.getDays().toArray();
tvReminderDays.setText(formatWeekdayList(ctx, weekdays));
}
@Override
public void onTimeCleared(RadialPickerLayout view)
{
setReminder(null);
}
@Override
public void onTimeSet(RadialPickerLayout view, int hour, int minute)
{
setReminder(new Reminder(hour, minute, WeekdayList.EVERY_DAY));
}
@Override
public void onWeekdaysSet(WeekdayList selectedDays)
{
if (reminder == null) return;
if (selectedDays.isEmpty()) selectedDays = WeekdayList.EVERY_DAY;
setReminder(new Reminder(reminder.getHour(), reminder.getMinute(),
selectedDays));
}
public void setController(@NonNull Controller controller)
{
this.controller = controller;
}
@Override
protected void onRestoreInstanceState(Parcelable state)
{
BundleSavedState bss = (BundleSavedState) state;
if (!bss.bundle.isEmpty())
{
int days = bss.bundle.getInt("days");
int hour = bss.bundle.getInt("hour");
int minute = bss.bundle.getInt("minute");
reminder = new Reminder(hour, minute, new WeekdayList(days));
setReminder(reminder);
}
super.onRestoreInstanceState(bss.getSuperState());
}
@Override
protected Parcelable onSaveInstanceState()
{
Parcelable superState = super.onSaveInstanceState();
Bundle bundle = new Bundle();
if (reminder != null)
{
bundle.putInt("days", reminder.getDays().toInteger());
bundle.putInt("hour", reminder.getHour());
bundle.putInt("minute", reminder.getMinute());
}
return new BundleSavedState(superState, bundle);
}
@OnClick(R.id.tvReminderTime)
void onDateSpinnerClick()
{
int hour = 8;
int min = 0;
if (reminder != null)
{
hour = reminder.getHour();
min = reminder.getMinute();
}
controller.onTimeClicked(hour, min);
}
@OnClick(R.id.tvReminderDays)
void onWeekdayClicked()
{
if (reminder == null) return;
controller.onWeekdayClicked(reminder.getDays());
}
public interface Controller
{
/**
* Called when the user has clicked the widget to change the time of
* the reminder.
*
* @param currentHour hour previously picked by the user
* @param currentMin minute previously picked by the user
*/
default void onTimeClicked(int currentHour, int currentMin) {}
/**
* Called when the used has clicked the widget to change the days
* of the reminder.
*
* @param currentDays days previously selected by the user.
*/
default void onWeekdayClicked(WeekdayList currentDays) {}
}
}

@ -23,13 +23,12 @@ import java.util.*;
public class WeekdayList
{
public static WeekdayList EVERY_DAY = new WeekdayList(127);
public static final WeekdayList EVERY_DAY = new WeekdayList(127);
private final boolean[] weekdays;
public WeekdayList(int packedList)
{
if(packedList == 0) packedList = 127;
weekdays = new boolean[7];
int current = 1;
@ -42,16 +41,18 @@ public class WeekdayList
public WeekdayList(boolean weekdays[])
{
boolean isEmpty = true;
for(boolean b : weekdays) if(b) isEmpty = false;
if(isEmpty) throw new IllegalArgumentException("empty list");
this.weekdays = Arrays.copyOf(weekdays, 7);
}
public boolean isEmpty()
{
for (boolean d : weekdays) if (d) return false;
return true;
}
public boolean[] toArray()
{
return weekdays;
return Arrays.copyOf(weekdays, 7);
}
public int toInteger()

@ -53,82 +53,16 @@
style="@style/dialogFormInputMultiline"
android:hint="@string/description_hint"/>
<LinearLayout
style="@style/dialogFormRow">
<TextView
android:id="@+id/textView1"
style="@style/dialogFormLabel"
android:text="@string/repeat"/>
<android.support.v7.widget.AppCompatSpinner
android:id="@+id/sFrequency"
android:theme="@style/dialogFormText"
android:layout_width="wrap_content"
android:layout_height="25dp"
android:minWidth="400dp"
android:entries="@array/frequencyQuickSelect"
android:visibility="gone"/>
<org.apmem.tools.layouts.FlowLayout
android:id="@+id/llCustomFrequency"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="visible"
android:gravity="fill">
<EditText
android:id="@+id/tvFreqNum"
style="@style/dialogFormInputLargeNumber"/>
<TextView
android:id="@+id/textView3"
style="@style/dialogFormText"
android:text="@string/times_every"
android:gravity="center"/>
<EditText
android:id="@+id/tvFreqDen"
style="@style/dialogFormInputLargeNumber"/>
<TextView
android:id="@+id/textView5"
style="@style/dialogFormText"
android:text="@string/days"
android:gravity="center_vertical"
android:paddingLeft="12dp"/>
</org.apmem.tools.layouts.FlowLayout>
</LinearLayout>
<org.isoron.uhabits.activities.habits.edit.views.FrequencyPanel
android:id="@+id/frequencyPanel"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<LinearLayout
<org.isoron.uhabits.activities.habits.edit.views.ReminderPanel
android:id="@+id/reminderPanel"
style="@style/dialogFormRow">
<TextView
android:id="@+id/TextView2"
style="@style/dialogFormLabel"
android:text="@string/reminder"/>
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/tvReminderTime"
style="@style/dialogFormSpinner"/>
</LinearLayout>
<LinearLayout
android:id="@+id/llReminderDays"
style="@style/dialogFormRow">
<TextView
android:id="@+id/TextView3"
style="@style/dialogFormLabel"
android:text=""/>
<TextView
android:id="@+id/tvReminderDays"
style="@style/dialogFormSpinner"/>
</LinearLayout>
</LinearLayout>
<LinearLayout

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ 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/>.
-->
<LinearLayout style="@style/dialogFormRow"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
style="@style/dialogFormLabel"
android:text="@string/repeat"/>
<android.support.v7.widget.AppCompatSpinner
android:id="@+id/spinner"
android:layout_width="wrap_content"
android:layout_height="25dp"
android:entries="@array/frequencyQuickSelect"
android:minWidth="400dp"
android:theme="@style/dialogFormText"
android:visibility="gone"/>
<org.apmem.tools.layouts.FlowLayout
android:id="@+id/customFreqPanel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="fill"
android:visibility="visible">
<EditText
android:id="@+id/numerator"
style="@style/dialogFormInputLargeNumber"/>
<TextView
style="@style/dialogFormText"
android:gravity="center"
android:text="@string/times_every"/>
<EditText
android:id="@+id/denominator"
style="@style/dialogFormInputLargeNumber"/>
<TextView
style="@style/dialogFormText"
android:gravity="center_vertical"
android:paddingLeft="12dp"
android:text="@string/days"/>
</org.apmem.tools.layouts.FlowLayout>
</LinearLayout>

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ 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/>.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
style="@style/dialogFormRow">
<TextView
style="@style/dialogFormLabel"
android:text="@string/reminder"/>
<TextView
android:id="@+id/tvReminderTime"
style="@style/dialogFormSpinner"/>
</LinearLayout>
<LinearLayout
android:id="@+id/llReminderDays"
style="@style/dialogFormRow">
<TextView
style="@style/dialogFormLabel"
android:text=""/>
<TextView
android:id="@+id/tvReminderDays"
style="@style/dialogFormSpinner"/>
</LinearLayout>
</LinearLayout>

@ -61,7 +61,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content">
<org.isoron.uhabits.activities.habits.edit.ExampleEditText
<org.isoron.uhabits.activities.habits.edit.views.ExampleEditText
android:id="@+id/tvDescription"
style="@style/dialogFormInputMultiline"
android:layout_width="match_parent"
@ -100,7 +100,7 @@
android:layout_height="wrap_content"
android:layout_weight="2">
<org.isoron.uhabits.activities.habits.edit.ExampleEditText
<org.isoron.uhabits.activities.habits.edit.views.ExampleEditText
android:id="@+id/tvUnit"
style="@style/dialogFormInput"
android:layout_width="match_parent"

@ -210,4 +210,5 @@
<string name="calendar">Calendar</string>
<string name="unit">Unit</string>
<string name="count">Count</string>
<string name="validation_show_not_be_blank">This field should not be blank</string>
</resources>

@ -22,6 +22,7 @@ package org.isoron.uhabits.models;
import org.isoron.uhabits.*;
import org.junit.*;
import static junit.framework.Assert.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.core.IsEqual.*;
@ -48,6 +49,8 @@ public class WeekdayListTest extends BaseUnitTest
public void testEmpty()
{
WeekdayList list = new WeekdayList(0);
assertThat(list.toArray(), equalTo(WeekdayList.EVERY_DAY.toArray()));
assertTrue(list.isEmpty());
assertFalse(WeekdayList.EVERY_DAY.isEmpty());
}
}

Loading…
Cancel
Save