mirror of https://github.com/iSoron/uhabits.git
commit
fc57a9db6c
@ -1,229 +1,215 @@
|
||||
<?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/>.
|
||||
-->
|
||||
<manifest
|
||||
package="org.isoron.uhabits"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.isoron.uhabits">
|
||||
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
|
||||
<application
|
||||
android:name=".HabitsApplication"
|
||||
android:allowBackup="true"
|
||||
android:backupAgent=".HabitsBackupAgent"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/main_activity_title"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppBaseTheme">
|
||||
android:name=".HabitsApplication"
|
||||
android:allowBackup="true"
|
||||
android:backupAgent=".HabitsBackupAgent"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/main_activity_title"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppBaseTheme">
|
||||
|
||||
<activity
|
||||
android:exported="true"
|
||||
android:name=".activities.habits.edit.EditHabitActivity">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".activities.habits.list.ListHabitsActivity" />
|
||||
</activity>
|
||||
|
||||
<meta-data
|
||||
android:name="com.google.android.backup.api_key"
|
||||
android:value="AEdPqrEAAAAI6aeWncbnMNo8E5GWeZ44dlc5cQ7tCROwFhOtiw"/>
|
||||
android:name="com.google.android.backup.api_key"
|
||||
android:value="AEdPqrEAAAAI6aeWncbnMNo8E5GWeZ44dlc5cQ7tCROwFhOtiw" />
|
||||
|
||||
<activity
|
||||
android:name=".activities.habits.list.ListHabitsActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/main_activity_title"
|
||||
android:launchMode="singleTop"/>
|
||||
android:name=".activities.habits.list.ListHabitsActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/main_activity_title"
|
||||
android:launchMode="singleTop" />
|
||||
|
||||
<activity-alias
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/main_activity_title"
|
||||
android:launchMode="singleTop"
|
||||
android:targetActivity=".activities.habits.list.ListHabitsActivity">
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/main_activity_title"
|
||||
android:launchMode="singleTop"
|
||||
android:targetActivity=".activities.habits.list.ListHabitsActivity">
|
||||
<intent-filter android:label="@string/main_activity_title">
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity
|
||||
android:name=".activities.habits.show.ShowHabitActivity"
|
||||
android:label="@string/title_activity_show_habit">
|
||||
android:name=".activities.habits.show.ShowHabitActivity"
|
||||
android:label="@string/title_activity_show_habit">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".activities.habits.list.ListHabitsActivity"/>
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".activities.habits.list.ListHabitsActivity" />
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activities.settings.SettingsActivity"
|
||||
android:label="@string/settings">
|
||||
android:name=".activities.settings.SettingsActivity"
|
||||
android:label="@string/settings">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".activities.habits.list.ListHabitsActivity"/>
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".activities.habits.list.ListHabitsActivity" />
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activities.intro.IntroActivity"
|
||||
android:label=""
|
||||
android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
|
||||
android:name=".activities.intro.IntroActivity"
|
||||
android:label=""
|
||||
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
|
||||
<activity
|
||||
android:name=".widgets.HabitPickerDialog"
|
||||
android:theme="@style/Theme.AppCompat.Light.Dialog">
|
||||
android:name=".widgets.HabitPickerDialog"
|
||||
android:theme="@style/Theme.AppCompat.Light.Dialog">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activities.about.AboutActivity"
|
||||
android:label="@string/about">
|
||||
android:name=".activities.about.AboutActivity"
|
||||
android:label="@string/about">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".activities.habits.list.ListHabitsActivity"/>
|
||||
</activity>
|
||||
<activity android:name=".notifications.SnoozeDelayPickerActivity"
|
||||
android:excludeFromRecents="true"
|
||||
android:launchMode="singleInstance"
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar">
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".activities.habits.list.ListHabitsActivity" />
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".notifications.SnoozeDelayPickerActivity"
|
||||
android:excludeFromRecents="true"
|
||||
android:launchMode="singleInstance"
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar"></activity>
|
||||
|
||||
<receiver
|
||||
android:name=".widgets.CheckmarkWidgetProvider"
|
||||
android:label="@string/checkmark">
|
||||
android:name=".widgets.CheckmarkWidgetProvider"
|
||||
android:label="@string/checkmark">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/widget_checkmark_info"/>
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/widget_checkmark_info" />
|
||||
</receiver>
|
||||
<service android:name=".widgets.StackWidgetService"
|
||||
android:permission="android.permission.BIND_REMOTEVIEWS"
|
||||
android:exported="false" />
|
||||
|
||||
<service
|
||||
android:name=".widgets.StackWidgetService"
|
||||
android:exported="false"
|
||||
android:permission="android.permission.BIND_REMOTEVIEWS" />
|
||||
|
||||
<receiver
|
||||
android:name=".widgets.HistoryWidgetProvider"
|
||||
android:label="@string/history">
|
||||
android:name=".widgets.HistoryWidgetProvider"
|
||||
android:label="@string/history">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/widget_history_info"/>
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/widget_history_info" />
|
||||
</receiver>
|
||||
<receiver
|
||||
android:name=".widgets.ScoreWidgetProvider"
|
||||
android:label="@string/habit_strength">
|
||||
android:name=".widgets.ScoreWidgetProvider"
|
||||
android:label="@string/habit_strength">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/widget_score_info"/>
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/widget_score_info" />
|
||||
</receiver>
|
||||
<receiver
|
||||
android:name=".widgets.StreakWidgetProvider"
|
||||
android:label="@string/streaks">
|
||||
android:name=".widgets.StreakWidgetProvider"
|
||||
android:label="@string/streaks">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/widget_streak_info"/>
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/widget_streak_info" />
|
||||
</receiver>
|
||||
<receiver
|
||||
android:name=".widgets.FrequencyWidgetProvider"
|
||||
android:label="@string/frequency">
|
||||
android:name=".widgets.FrequencyWidgetProvider"
|
||||
android:label="@string/frequency">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/widget_frequency_info"/>
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/widget_frequency_info" />
|
||||
</receiver>
|
||||
<receiver android:name=".receivers.ReminderReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED"/>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<receiver android:name=".receivers.WidgetReceiver">
|
||||
<intent-filter>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
|
||||
<action android:name="org.isoron.uhabits.ACTION_TOGGLE_REPETITION"/>
|
||||
<action android:name="org.isoron.uhabits.ACTION_TOGGLE_REPETITION" />
|
||||
|
||||
<data
|
||||
android:host="org.isoron.uhabits"
|
||||
android:scheme="content"/>
|
||||
android:host="org.isoron.uhabits"
|
||||
android:scheme="content" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
|
||||
<action android:name="org.isoron.uhabits.ACTION_ADD_REPETITION"/>
|
||||
<action android:name="org.isoron.uhabits.ACTION_ADD_REPETITION" />
|
||||
|
||||
<data
|
||||
android:host="org.isoron.uhabits"
|
||||
android:scheme="content"/>
|
||||
android:host="org.isoron.uhabits"
|
||||
android:scheme="content" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
|
||||
<action android:name="org.isoron.uhabits.ACTION_REMOVE_REPETITION"/>
|
||||
<action android:name="org.isoron.uhabits.ACTION_REMOVE_REPETITION" />
|
||||
|
||||
<data
|
||||
android:host="org.isoron.uhabits"
|
||||
android:scheme="content"/>
|
||||
android:host="org.isoron.uhabits"
|
||||
android:scheme="content" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<!-- Locale/Tasker -->
|
||||
</receiver> <!-- Locale/Tasker -->
|
||||
<activity
|
||||
android:name=".automation.EditSettingActivity"
|
||||
android:exported="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name">
|
||||
android:name=".automation.EditSettingActivity"
|
||||
android:exported="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="com.twofortyfouram.locale.intent.action.EDIT_SETTING"/>
|
||||
<action android:name="com.twofortyfouram.locale.intent.action.EDIT_SETTING" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<!-- Locale/Tasker -->
|
||||
</activity> <!-- Locale/Tasker -->
|
||||
<receiver
|
||||
android:name=".automation.FireSettingReceiver"
|
||||
android:exported="true">
|
||||
android:name=".automation.FireSettingReceiver"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="com.twofortyfouram.locale.intent.action.FIRE_SETTING"/>
|
||||
<action android:name="com.twofortyfouram.locale.intent.action.FIRE_SETTING" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="org.isoron.uhabits"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="org.isoron.uhabits"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_paths"/>
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_paths" />
|
||||
</provider>
|
||||
|
||||
<service
|
||||
android:name=".sync.SyncService"
|
||||
android:enabled="true"
|
||||
android:exported="false">
|
||||
</service>
|
||||
android:name=".sync.SyncService"
|
||||
android:enabled="true"
|
||||
android:exported="false"></service>
|
||||
</application>
|
||||
|
||||
</manifest>
|
@ -0,0 +1,172 @@
|
||||
/*
|
||||
* 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.common.dialogs
|
||||
|
||||
import android.app.*
|
||||
import android.os.*
|
||||
import android.util.*
|
||||
import android.view.*
|
||||
import android.widget.*
|
||||
import androidx.appcompat.app.*
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import kotlinx.android.synthetic.main.frequency_picker_dialog.view.*
|
||||
import org.isoron.uhabits.*
|
||||
|
||||
|
||||
class FrequencyPickerDialog(var freqNumerator: Int,
|
||||
var freqDenominator: Int
|
||||
) : AppCompatDialogFragment() {
|
||||
|
||||
lateinit var contentView: View
|
||||
var onFrequencyPicked: (num: Int, den: Int) -> Unit = {_,_ -> }
|
||||
|
||||
constructor() : this(1, 1)
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val inflater = LayoutInflater.from(activity!!)
|
||||
contentView = inflater.inflate(R.layout.frequency_picker_dialog, null)
|
||||
|
||||
contentView.everyDayRadioButton.setOnClickListener {
|
||||
check(contentView.everyDayRadioButton)
|
||||
unfocusAll()
|
||||
}
|
||||
|
||||
contentView.everyXDaysRadioButton.setOnClickListener {
|
||||
check(contentView.everyXDaysRadioButton)
|
||||
val everyXDaysTextView = contentView.everyXDaysTextView
|
||||
focus(everyXDaysTextView)
|
||||
}
|
||||
|
||||
contentView.everyXDaysTextView.setOnFocusChangeListener { v, hasFocus ->
|
||||
if(hasFocus) check(contentView.everyXDaysRadioButton)
|
||||
}
|
||||
|
||||
contentView.xTimesPerWeekRadioButton.setOnClickListener {
|
||||
check(contentView.xTimesPerWeekRadioButton)
|
||||
focus(contentView.xTimesPerWeekTextView)
|
||||
}
|
||||
|
||||
contentView.xTimesPerWeekTextView.setOnFocusChangeListener { v, hasFocus ->
|
||||
if(hasFocus) check(contentView.xTimesPerWeekRadioButton)
|
||||
}
|
||||
|
||||
contentView.xTimesPerMonthRadioButton.setOnClickListener {
|
||||
check(contentView.xTimesPerMonthRadioButton)
|
||||
focus(contentView.xTimesPerMonthTextView)
|
||||
}
|
||||
|
||||
contentView.xTimesPerMonthTextView.setOnFocusChangeListener { v, hasFocus ->
|
||||
if(hasFocus) check(contentView.xTimesPerMonthRadioButton)
|
||||
}
|
||||
|
||||
return AlertDialog.Builder(activity!!)
|
||||
.setView(contentView)
|
||||
.setPositiveButton(R.string.save) { _, _ -> onSaveClicked() }
|
||||
.create()
|
||||
}
|
||||
|
||||
private fun onSaveClicked() {
|
||||
var numerator = 1
|
||||
var denominator = 1
|
||||
when {
|
||||
contentView.everyDayRadioButton.isChecked -> {
|
||||
// NOP
|
||||
}
|
||||
contentView.everyXDaysRadioButton.isChecked -> {
|
||||
if (contentView.everyXDaysTextView.text.isNotEmpty()) {
|
||||
denominator = Integer.parseInt(contentView.everyXDaysTextView.text.toString())
|
||||
}
|
||||
}
|
||||
contentView.xTimesPerWeekRadioButton.isChecked -> {
|
||||
if (contentView.xTimesPerWeekTextView.text.isNotEmpty()) {
|
||||
numerator = Integer.parseInt(contentView.xTimesPerWeekTextView.text.toString())
|
||||
denominator = 7
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
if (contentView.xTimesPerMonthTextView.text.isNotEmpty()) {
|
||||
numerator = Integer.parseInt(contentView.xTimesPerMonthTextView.text.toString())
|
||||
denominator = 30
|
||||
}
|
||||
}
|
||||
}
|
||||
if (numerator >= denominator || numerator < 1) {
|
||||
numerator = 1
|
||||
denominator = 1
|
||||
}
|
||||
onFrequencyPicked(numerator, denominator)
|
||||
dismiss()
|
||||
}
|
||||
|
||||
private fun check(view: RadioButton?) {
|
||||
uncheckAll()
|
||||
view?.isChecked = true
|
||||
view?.requestFocus()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
populateViews()
|
||||
}
|
||||
|
||||
private fun populateViews() {
|
||||
uncheckAll()
|
||||
if (freqNumerator == 1) {
|
||||
if(freqDenominator == 1) {
|
||||
contentView.everyDayRadioButton.isChecked = true
|
||||
} else {
|
||||
contentView.everyXDaysRadioButton.isChecked = true
|
||||
contentView.everyXDaysTextView.setText(freqDenominator.toString())
|
||||
focus(contentView.everyXDaysTextView)
|
||||
}
|
||||
} else {
|
||||
if(freqDenominator == 7) {
|
||||
contentView.xTimesPerWeekRadioButton.isChecked = true
|
||||
contentView.xTimesPerWeekTextView.setText(freqNumerator.toString())
|
||||
focus(contentView.xTimesPerWeekTextView)
|
||||
} else if (freqDenominator == 30 || freqDenominator == 31) {
|
||||
contentView.xTimesPerMonthRadioButton.isChecked = true
|
||||
contentView.xTimesPerMonthTextView.setText(freqNumerator.toString())
|
||||
focus(contentView.xTimesPerMonthTextView)
|
||||
} else {
|
||||
Log.w("FrequencyPickerDialog", "Unknown frequency: $freqNumerator/$freqDenominator")
|
||||
contentView.everyDayRadioButton.isChecked = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun focus(view: EditText) {
|
||||
view.requestFocus()
|
||||
view.setSelection(view.text.length)
|
||||
}
|
||||
|
||||
private fun uncheckAll() {
|
||||
contentView.everyDayRadioButton.isChecked = false
|
||||
contentView.everyXDaysRadioButton.isChecked = false
|
||||
contentView.xTimesPerWeekRadioButton.isChecked = false
|
||||
contentView.xTimesPerMonthRadioButton.isChecked = false
|
||||
}
|
||||
|
||||
private fun unfocusAll() {
|
||||
contentView.everyXDaysTextView.clearFocus()
|
||||
contentView.xTimesPerWeekTextView.clearFocus()
|
||||
contentView.xTimesPerMonthTextView.clearFocus()
|
||||
}
|
||||
}
|
@ -0,0 +1,250 @@
|
||||
/*
|
||||
* 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.content.res.*
|
||||
import android.graphics.*
|
||||
import android.os.*
|
||||
import android.text.format.*
|
||||
import android.view.*
|
||||
import androidx.appcompat.app.*
|
||||
import androidx.fragment.app.*
|
||||
import com.android.datetimepicker.time.*
|
||||
import kotlinx.android.synthetic.main.activity_edit_habit.*
|
||||
import org.isoron.androidbase.utils.*
|
||||
import org.isoron.uhabits.*
|
||||
import org.isoron.uhabits.activities.*
|
||||
import org.isoron.uhabits.activities.common.dialogs.*
|
||||
import org.isoron.uhabits.core.commands.*
|
||||
import org.isoron.uhabits.core.models.*
|
||||
import org.isoron.uhabits.databinding.*
|
||||
import org.isoron.uhabits.utils.*
|
||||
|
||||
class EditHabitActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var themeSwitcher: AndroidThemeSwitcher
|
||||
private lateinit var binding: ActivityEditHabitBinding
|
||||
private lateinit var commandRunner: CommandRunner
|
||||
|
||||
var habitId = -1L
|
||||
var paletteColor = 11
|
||||
var androidColor = 0
|
||||
var freqNum = 1
|
||||
var freqDen = 1
|
||||
var reminderHour = -1
|
||||
var reminderMin = -1
|
||||
var reminderDays: WeekdayList = WeekdayList.EVERY_DAY
|
||||
|
||||
override fun onCreate(state: Bundle?) {
|
||||
super.onCreate(state)
|
||||
|
||||
val component = (application as HabitsApplication).component
|
||||
themeSwitcher = AndroidThemeSwitcher(this, component.preferences)
|
||||
themeSwitcher.apply()
|
||||
|
||||
binding = ActivityEditHabitBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
if (intent.hasExtra("habitId")) {
|
||||
binding.toolbar.title = getString(R.string.edit_habit)
|
||||
habitId = intent.getLongExtra("habitId", -1)
|
||||
val habit = component.habitList.getById(habitId)!!
|
||||
paletteColor = habit.color
|
||||
freqNum = habit.frequency.numerator
|
||||
freqDen = habit.frequency.denominator
|
||||
if (habit.hasReminder()) {
|
||||
reminderHour = habit.reminder.hour
|
||||
reminderMin = habit.reminder.minute
|
||||
reminderDays = habit.reminder.days
|
||||
}
|
||||
binding.nameInput.setText(habit.name)
|
||||
binding.questionInput.setText(habit.question)
|
||||
binding.notesInput.setText(habit.description)
|
||||
}
|
||||
|
||||
if (state != null) {
|
||||
habitId = state.getLong("habitId")
|
||||
paletteColor = state.getInt("paletteColor")
|
||||
freqNum = state.getInt("freqNum")
|
||||
freqDen = state.getInt("freqDen")
|
||||
reminderHour = state.getInt("reminderHour")
|
||||
reminderMin = state.getInt("reminderMin")
|
||||
reminderDays = WeekdayList(state.getInt("reminderDays"))
|
||||
}
|
||||
|
||||
updateColors()
|
||||
|
||||
setSupportActionBar(binding.toolbar)
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
supportActionBar?.setDisplayShowHomeEnabled(true)
|
||||
supportActionBar?.elevation = 10.0f
|
||||
|
||||
val colorPickerDialogFactory = ColorPickerDialogFactory(this)
|
||||
binding.colorButton.setOnClickListener {
|
||||
val dialog = colorPickerDialogFactory.create(paletteColor)
|
||||
dialog.setListener { paletteColor ->
|
||||
this.paletteColor = paletteColor
|
||||
updateColors()
|
||||
}
|
||||
dialog.show(supportFragmentManager, "colorPicker")
|
||||
}
|
||||
|
||||
populateFrequency()
|
||||
binding.frequencyPicker.setOnClickListener {
|
||||
val dialog = FrequencyPickerDialog(freqNum, freqDen)
|
||||
dialog.onFrequencyPicked = { num, den ->
|
||||
freqNum = num
|
||||
freqDen = den
|
||||
populateFrequency()
|
||||
}
|
||||
dialog.show(supportFragmentManager, "frequencyPicker")
|
||||
}
|
||||
|
||||
populateReminder()
|
||||
binding.reminderTimePicker.setOnClickListener {
|
||||
val currentHour = if (reminderHour >= 0) reminderHour else 8
|
||||
val currentMin = if (reminderMin >= 0) reminderMin else 0
|
||||
val is24HourMode = DateFormat.is24HourFormat(this)
|
||||
val dialog = TimePickerDialog.newInstance(object : TimePickerDialog.OnTimeSetListener {
|
||||
override fun onTimeSet(view: RadialPickerLayout?, hourOfDay: Int, minute: Int) {
|
||||
reminderHour = hourOfDay
|
||||
reminderMin = minute
|
||||
populateReminder()
|
||||
}
|
||||
override fun onTimeCleared(view: RadialPickerLayout?) {
|
||||
reminderHour = -1
|
||||
reminderMin = -1
|
||||
reminderDays = WeekdayList.EVERY_DAY
|
||||
populateReminder()
|
||||
}
|
||||
}, currentHour, currentMin, is24HourMode, androidColor)
|
||||
dialog.show(supportFragmentManager, "timePicker")
|
||||
}
|
||||
|
||||
binding.reminderDatePicker.setOnClickListener {
|
||||
val dialog = WeekdayPickerDialog()
|
||||
dialog.setListener { days ->
|
||||
reminderDays = days
|
||||
if (reminderDays.isEmpty) reminderDays = WeekdayList.EVERY_DAY
|
||||
populateReminder()
|
||||
}
|
||||
dialog.setSelectedDays(reminderDays)
|
||||
dialog.show(supportFragmentManager, "dayPicker")
|
||||
}
|
||||
|
||||
binding.buttonSave.setOnClickListener {
|
||||
if(validate()) save()
|
||||
}
|
||||
|
||||
for (fragment in supportFragmentManager.fragments) {
|
||||
(fragment as DialogFragment).dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
private fun save() {
|
||||
val component = (application as HabitsApplication).component
|
||||
val habit = component.modelFactory.buildHabit()
|
||||
|
||||
var original: Habit? = null
|
||||
if (habitId >= 0) {
|
||||
original = component.habitList.getById(habitId)!!
|
||||
habit.copyFrom(original)
|
||||
}
|
||||
|
||||
habit.name = nameInput.text.trim().toString()
|
||||
habit.question = questionInput.text.trim().toString()
|
||||
habit.description = notesInput.text.trim().toString()
|
||||
habit.color = paletteColor
|
||||
if (reminderHour >= 0) {
|
||||
habit.setReminder(Reminder(reminderHour, reminderMin, reminderDays))
|
||||
}
|
||||
habit.frequency = Frequency(freqNum, freqDen)
|
||||
habit.unit = ""
|
||||
habit.targetValue = 1.0
|
||||
habit.type = Habit.YES_NO_HABIT
|
||||
|
||||
val command = if (habitId >= 0) {
|
||||
component.editHabitCommandFactory.create(component.habitList, original, habit)
|
||||
} else {
|
||||
component.createHabitCommandFactory.create(component.habitList, habit)
|
||||
}
|
||||
component.commandRunner.execute(command, null)
|
||||
finish()
|
||||
}
|
||||
|
||||
private fun validate(): Boolean {
|
||||
if (nameInput.text.isEmpty()) {
|
||||
nameInput.error = getString(R.string.validation_name_should_not_be_blank)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun populateReminder() {
|
||||
if (reminderHour < 0) {
|
||||
binding.reminderTimePicker.text = getString(R.string.reminder_off)
|
||||
binding.reminderDatePicker.visibility = View.GONE
|
||||
binding.reminderDivider.visibility = View.GONE
|
||||
} else {
|
||||
val time = AndroidDateUtils.formatTime(this, reminderHour, reminderMin)
|
||||
val daysArray = reminderDays.toArray()
|
||||
binding.reminderTimePicker.text = time
|
||||
binding.reminderDatePicker.visibility = View.VISIBLE
|
||||
binding.reminderDivider.visibility = View.VISIBLE
|
||||
binding.reminderDatePicker.text = AndroidDateUtils.formatWeekdayList(this, daysArray)
|
||||
}
|
||||
}
|
||||
|
||||
private fun populateFrequency() {
|
||||
val label = when {
|
||||
freqNum == 1 && freqDen == 1 -> getString(R.string.every_day)
|
||||
freqNum == 1 && freqDen == 7 -> getString(R.string.every_week)
|
||||
freqNum == 1 && freqDen > 1 -> getString(R.string.every_x_days, freqDen)
|
||||
freqDen == 7 -> getString(R.string.x_times_per_week, freqNum)
|
||||
freqDen == 31 -> getString(R.string.x_times_per_month, freqNum)
|
||||
else -> "Unknown"
|
||||
}
|
||||
binding.frequencyPicker.text = label
|
||||
}
|
||||
|
||||
private fun updateColors() {
|
||||
androidColor = PaletteUtils.getColor(this, paletteColor)
|
||||
binding.colorButton.backgroundTintList = ColorStateList.valueOf(androidColor)
|
||||
if (!themeSwitcher.isNightMode) {
|
||||
val darkerAndroidColor = ColorUtils.mixColors(Color.BLACK, androidColor, 0.15f)
|
||||
window.statusBarColor = darkerAndroidColor
|
||||
binding.toolbar.setBackgroundColor(androidColor)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(state: Bundle) {
|
||||
super.onSaveInstanceState(state)
|
||||
with(state) {
|
||||
putLong("habitId", habitId)
|
||||
putInt("paletteColor", paletteColor)
|
||||
putInt("androidColor", androidColor)
|
||||
putInt("freqNum", freqNum)
|
||||
putInt("freqDen", freqDen)
|
||||
putInt("reminderHour", reminderHour)
|
||||
putInt("reminderMin", reminderMin)
|
||||
putInt("reminderDays", reminderDays.toInteger())
|
||||
}
|
||||
}
|
||||
}
|
@ -1,290 +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.app.*;
|
||||
import android.content.*;
|
||||
import android.os.*;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.*;
|
||||
import android.text.format.*;
|
||||
import android.view.*;
|
||||
|
||||
import com.android.datetimepicker.time.TimePickerDialog;
|
||||
|
||||
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.core.commands.*;
|
||||
import org.isoron.uhabits.core.models.*;
|
||||
import org.isoron.uhabits.core.preferences.*;
|
||||
|
||||
import butterknife.*;
|
||||
|
||||
import static android.view.View.*;
|
||||
|
||||
public class EditHabitDialog extends AppCompatDialogFragment
|
||||
{
|
||||
public static final String BUNDLE_HABIT_ID = "habitId";
|
||||
|
||||
public static final String BUNDLE_HABIT_TYPE = "habitType";
|
||||
|
||||
private static final String WEEKDAY_PICKER_TAG = "weekdayPicker";
|
||||
|
||||
protected Habit originalHabit;
|
||||
|
||||
protected Preferences prefs;
|
||||
|
||||
protected CommandRunner commandRunner;
|
||||
|
||||
protected HabitList habitList;
|
||||
|
||||
protected HabitsApplicationComponent component;
|
||||
|
||||
protected ModelFactory modelFactory;
|
||||
|
||||
@BindView(R.id.namePanel)
|
||||
NameDescriptionPanel namePanel;
|
||||
|
||||
@BindView(R.id.reminderPanel)
|
||||
ReminderPanel reminderPanel;
|
||||
|
||||
@BindView(R.id.frequencyPanel)
|
||||
FrequencyPanel frequencyPanel;
|
||||
|
||||
@BindView(R.id.targetPanel)
|
||||
TargetPanel targetPanel;
|
||||
|
||||
private ColorPickerDialogFactory colorPickerDialogFactory;
|
||||
|
||||
@Override
|
||||
public int getTheme()
|
||||
{
|
||||
HabitsActivity activity = (HabitsActivity) getActivity();
|
||||
return activity.getComponent().getThemeSwitcher().getDialogTheme();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState)
|
||||
{
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
HabitsActivity activity = (HabitsActivity) getActivity();
|
||||
colorPickerDialogFactory =
|
||||
activity.getComponent().getColorPickerDialogFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater,
|
||||
ViewGroup container,
|
||||
Bundle savedInstanceState)
|
||||
{
|
||||
View view;
|
||||
view = inflater.inflate(R.layout.edit_habit, container, false);
|
||||
|
||||
initDependencies();
|
||||
ButterKnife.bind(this, view);
|
||||
|
||||
originalHabit = parseHabitFromArguments();
|
||||
getDialog().setTitle(getTitle());
|
||||
|
||||
populateForm();
|
||||
setupReminderController();
|
||||
setupNameController();
|
||||
|
||||
restoreChildFragmentListeners();
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
final Dialog dialog = super.onCreateDialog(savedInstanceState);
|
||||
final Window window = dialog.getWindow();
|
||||
if (window != null) {
|
||||
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
|
||||
}
|
||||
return dialog;
|
||||
}
|
||||
|
||||
protected int getTitle()
|
||||
{
|
||||
if (originalHabit != null) return R.string.edit_habit;
|
||||
else return R.string.create_habit;
|
||||
}
|
||||
|
||||
protected void saveHabit(@NonNull Habit habit)
|
||||
{
|
||||
if (originalHabit == null)
|
||||
{
|
||||
commandRunner.execute(component
|
||||
.getCreateHabitCommandFactory()
|
||||
.create(habitList, habit), null);
|
||||
}
|
||||
else
|
||||
{
|
||||
commandRunner.execute(component.getEditHabitCommandFactory().
|
||||
create(habitList, originalHabit, habit), originalHabit.getId());
|
||||
}
|
||||
}
|
||||
|
||||
private int getTypeFromArguments()
|
||||
{
|
||||
return getArguments().getInt(BUNDLE_HABIT_TYPE);
|
||||
}
|
||||
|
||||
private void initDependencies()
|
||||
{
|
||||
Context appContext = getContext().getApplicationContext();
|
||||
HabitsApplication app = (HabitsApplication) appContext;
|
||||
|
||||
component = app.getComponent();
|
||||
prefs = component.getPreferences();
|
||||
habitList = component.getHabitList();
|
||||
commandRunner = component.getCommandRunner();
|
||||
modelFactory = component.getModelFactory();
|
||||
}
|
||||
|
||||
@OnClick(R.id.buttonDiscard)
|
||||
void onButtonDiscardClick()
|
||||
{
|
||||
dismiss();
|
||||
}
|
||||
|
||||
@OnClick(R.id.buttonSave)
|
||||
void onSaveButtonClick()
|
||||
{
|
||||
int type = getTypeFromArguments();
|
||||
|
||||
if (!namePanel.validate()) return;
|
||||
if (type == Habit.YES_NO_HABIT && !frequencyPanel.validate()) return;
|
||||
if (type == Habit.NUMBER_HABIT && !targetPanel.validate()) return;
|
||||
|
||||
Habit habit = modelFactory.buildHabit();
|
||||
if( originalHabit != null )
|
||||
habit.copyFrom(originalHabit);
|
||||
habit.setName(namePanel.getName());
|
||||
habit.setDescription(namePanel.getDescription());
|
||||
habit.setQuestion(namePanel.getQuestion());
|
||||
habit.setColor(namePanel.getColor());
|
||||
habit.setReminder(reminderPanel.getReminder());
|
||||
habit.setFrequency(frequencyPanel.getFrequency());
|
||||
habit.setUnit(targetPanel.getUnit());
|
||||
habit.setTargetValue(targetPanel.getTargetValue());
|
||||
habit.setType(type);
|
||||
|
||||
saveHabit(habit);
|
||||
dismiss();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Habit parseHabitFromArguments()
|
||||
{
|
||||
Bundle arguments = getArguments();
|
||||
if (arguments == null) return null;
|
||||
|
||||
Long id = (Long) arguments.get(BUNDLE_HABIT_ID);
|
||||
if (id == null) return null;
|
||||
|
||||
Habit habit = habitList.getById(id);
|
||||
if (habit == null) throw new IllegalStateException();
|
||||
|
||||
return habit;
|
||||
}
|
||||
|
||||
private void populateForm()
|
||||
{
|
||||
Habit habit = modelFactory.buildHabit();
|
||||
habit.setFrequency(Frequency.DAILY);
|
||||
habit.setColor(prefs.getDefaultHabitColor(habit.getColor()));
|
||||
habit.setType(getTypeFromArguments());
|
||||
|
||||
if (originalHabit != null) habit.copyFrom(originalHabit);
|
||||
|
||||
if (habit.isNumerical()) frequencyPanel.setVisibility(GONE);
|
||||
else targetPanel.setVisibility(GONE);
|
||||
|
||||
namePanel.populateFrom(habit);
|
||||
frequencyPanel.setFrequency(habit.getFrequency());
|
||||
targetPanel.setTargetValue(habit.getTargetValue());
|
||||
targetPanel.setUnit(habit.getUnit());
|
||||
if (habit.hasReminder()) reminderPanel.setReminder(habit.getReminder());
|
||||
}
|
||||
|
||||
private void setupNameController()
|
||||
{
|
||||
namePanel.setController(new NameDescriptionPanel.Controller()
|
||||
{
|
||||
@Override
|
||||
public void onColorPickerClicked(int previousColor)
|
||||
{
|
||||
ColorPickerDialog picker =
|
||||
colorPickerDialogFactory.create(previousColor);
|
||||
|
||||
picker.setListener(c ->
|
||||
{
|
||||
prefs.setDefaultHabitColor(c);
|
||||
namePanel.setColor(c);
|
||||
});
|
||||
|
||||
picker.show(getFragmentManager(), "picker");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setupReminderController()
|
||||
{
|
||||
reminderPanel.setController(new ReminderPanel.Controller()
|
||||
{
|
||||
@Override
|
||||
public void onTimeClicked(int currentHour, int currentMin)
|
||||
{
|
||||
TimePickerDialog timePicker;
|
||||
boolean is24HourMode = DateFormat.is24HourFormat(getContext());
|
||||
timePicker =
|
||||
TimePickerDialog.newInstance(reminderPanel, currentHour,
|
||||
currentMin, is24HourMode);
|
||||
timePicker.show(getFragmentManager(), "timePicker");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWeekdayClicked(WeekdayList currentDays)
|
||||
{
|
||||
WeekdayPickerDialog dialog = new WeekdayPickerDialog();
|
||||
dialog.setListener(reminderPanel);
|
||||
dialog.setSelectedDays(currentDays);
|
||||
dialog.show(getChildFragmentManager(), WEEKDAY_PICKER_TAG);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void restoreChildFragmentListeners()
|
||||
{
|
||||
final WeekdayPickerDialog dialog =
|
||||
(WeekdayPickerDialog) getChildFragmentManager()
|
||||
.findFragmentByTag(WEEKDAY_PICKER_TAG);
|
||||
if(dialog != null) dialog.setListener(reminderPanel);
|
||||
}
|
||||
}
|
@ -1,69 +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.os.*;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.isoron.uhabits.core.models.*;
|
||||
|
||||
import javax.inject.*;
|
||||
|
||||
import static org.isoron.uhabits.activities.habits.edit.EditHabitDialog.*;
|
||||
|
||||
public class EditHabitDialogFactory
|
||||
{
|
||||
@Inject
|
||||
public EditHabitDialogFactory()
|
||||
{
|
||||
}
|
||||
|
||||
public EditHabitDialog createBoolean()
|
||||
{
|
||||
EditHabitDialog dialog = new EditHabitDialog();
|
||||
Bundle args = new Bundle();
|
||||
args.putInt(BUNDLE_HABIT_TYPE, Habit.YES_NO_HABIT);
|
||||
dialog.setArguments(args);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public EditHabitDialog createNumerical()
|
||||
{
|
||||
EditHabitDialog dialog = new EditHabitDialog();
|
||||
Bundle args = new Bundle();
|
||||
args.putInt(BUNDLE_HABIT_TYPE, Habit.NUMBER_HABIT);
|
||||
dialog.setArguments(args);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public EditHabitDialog edit(@NonNull Habit habit)
|
||||
{
|
||||
if (habit.getId() == null)
|
||||
throw new IllegalArgumentException("habit not saved");
|
||||
|
||||
EditHabitDialog dialog = new EditHabitDialog();
|
||||
Bundle args = new Bundle();
|
||||
args.putLong(BUNDLE_HABIT_ID, habit.getId());
|
||||
args.putInt(BUNDLE_HABIT_TYPE, habit.getType());
|
||||
dialog.setArguments(args);
|
||||
return dialog;
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2020 Á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.os.*
|
||||
import android.view.*
|
||||
import androidx.appcompat.app.*
|
||||
import org.isoron.uhabits.*
|
||||
import org.isoron.uhabits.databinding.*
|
||||
import org.isoron.uhabits.intents.*
|
||||
|
||||
class HabitTypeDialog : AppCompatDialogFragment() {
|
||||
override fun getTheme() = R.style.Translucent
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
val binding = SelectHabitTypeBinding.inflate(inflater, container, false)
|
||||
|
||||
binding.buttonYesNo.setOnClickListener {
|
||||
val intent = IntentFactory().startEditActivity(activity!!)
|
||||
startActivity(intent)
|
||||
dismiss()
|
||||
}
|
||||
|
||||
binding.buttonMeasurable.setOnClickListener {
|
||||
dismiss()
|
||||
}
|
||||
|
||||
binding.buttonSubjective.setOnClickListener{
|
||||
dismiss()
|
||||
}
|
||||
|
||||
binding.background.setOnClickListener {
|
||||
dismiss()
|
||||
}
|
||||
|
||||
return binding.root
|
||||
}
|
||||
}
|
@ -1,116 +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.views;
|
||||
|
||||
import android.content.*;
|
||||
import android.text.*;
|
||||
import android.util.*;
|
||||
import android.view.*;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.AppCompatEditText;
|
||||
|
||||
import org.isoron.androidbase.utils.*;
|
||||
import org.isoron.uhabits.*;
|
||||
|
||||
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 AppCompatEditText
|
||||
implements View.OnFocusChangeListener
|
||||
{
|
||||
|
||||
private String example;
|
||||
|
||||
private String realText;
|
||||
|
||||
private int color;
|
||||
|
||||
private int exampleColor;
|
||||
|
||||
private int inputType;
|
||||
|
||||
public ExampleEditText(Context context, @Nullable AttributeSet attrs)
|
||||
{
|
||||
super(context, attrs);
|
||||
|
||||
if (attrs != null)
|
||||
example = getAttribute(context, attrs, "example", "");
|
||||
|
||||
inputType = getInputType();
|
||||
realText = getText().toString();
|
||||
color = getCurrentTextColor();
|
||||
init();
|
||||
}
|
||||
|
||||
public String getRealText()
|
||||
{
|
||||
if(hasFocus()) return getText().toString();
|
||||
else return realText;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFocusChange(View v, boolean hasFocus)
|
||||
{
|
||||
if (!hasFocus) realText = getText().toString();
|
||||
updateText();
|
||||
}
|
||||
|
||||
public void setExample(String example)
|
||||
{
|
||||
this.example = example;
|
||||
updateText();
|
||||
}
|
||||
|
||||
public void setRealText(@NonNull String realText)
|
||||
{
|
||||
this.realText = realText;
|
||||
updateText();
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
StyledResources sr = new StyledResources(getContext());
|
||||
exampleColor = sr.getColor(R.attr.mediumContrastTextColor);
|
||||
setOnFocusChangeListener(this);
|
||||
updateText();
|
||||
}
|
||||
|
||||
private void updateText()
|
||||
{
|
||||
if (realText.isEmpty() && !isFocused())
|
||||
{
|
||||
setTextColor(exampleColor);
|
||||
setText(example);
|
||||
setInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||
}
|
||||
else
|
||||
{
|
||||
setText(realText);
|
||||
setTextColor(color);
|
||||
setInputType(inputType);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,166 +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.views;
|
||||
|
||||
import android.annotation.*;
|
||||
import android.content.*;
|
||||
import android.content.res.*;
|
||||
import android.util.*;
|
||||
import android.view.*;
|
||||
import android.widget.*;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.isoron.uhabits.R;
|
||||
import org.isoron.uhabits.core.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);
|
||||
}
|
||||
}
|
@ -1,164 +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.views;
|
||||
|
||||
import android.content.*;
|
||||
import android.content.res.*;
|
||||
import android.os.*;
|
||||
import android.util.*;
|
||||
import android.view.*;
|
||||
import android.widget.*;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.isoron.uhabits.R;
|
||||
import org.isoron.uhabits.activities.common.views.*;
|
||||
import org.isoron.uhabits.core.models.*;
|
||||
import org.isoron.uhabits.utils.*;
|
||||
|
||||
import butterknife.*;
|
||||
|
||||
|
||||
public class NameDescriptionPanel extends FrameLayout
|
||||
{
|
||||
@BindView(R.id.tvName)
|
||||
EditText tvName;
|
||||
|
||||
@BindView(R.id.tvQuestion)
|
||||
ExampleEditText tvQuestion;
|
||||
|
||||
@BindView(R.id.tvDescription)
|
||||
ExampleEditText tvDescription;
|
||||
|
||||
private int color;
|
||||
|
||||
@NonNull
|
||||
private Controller controller;
|
||||
|
||||
public NameDescriptionPanel(@NonNull Context context,
|
||||
@Nullable AttributeSet attrs)
|
||||
{
|
||||
super(context, attrs);
|
||||
|
||||
View view = inflate(context, R.layout.edit_habit_name, null);
|
||||
ButterKnife.bind(this, view);
|
||||
addView(view);
|
||||
|
||||
controller = new Controller() {};
|
||||
}
|
||||
|
||||
public int getColor()
|
||||
{
|
||||
return color;
|
||||
}
|
||||
|
||||
public void setColor(int color)
|
||||
{
|
||||
this.color = color;
|
||||
tvName.setTextColor(PaletteUtils.getColor(getContext(), color));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getDescription()
|
||||
{
|
||||
return tvDescription.getRealText().trim();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getQuestion()
|
||||
{
|
||||
return tvQuestion.getRealText().trim();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getName()
|
||||
{
|
||||
return tvName.getText().toString().trim();
|
||||
}
|
||||
|
||||
public void populateFrom(@NonNull Habit habit)
|
||||
{
|
||||
Resources res = getResources();
|
||||
|
||||
if(habit.isNumerical())
|
||||
tvQuestion.setExample(res.getString(R.string.example_question_numerical));
|
||||
else
|
||||
tvQuestion.setExample(res.getString(R.string.example_question_boolean));
|
||||
|
||||
setColor(habit.getColor());
|
||||
tvName.setText(habit.getName());
|
||||
tvQuestion.setRealText(habit.getQuestion());
|
||||
tvDescription.setRealText(habit.getDescription());
|
||||
}
|
||||
|
||||
public boolean validate()
|
||||
{
|
||||
Resources res = getResources();
|
||||
|
||||
if (getName().isEmpty())
|
||||
{
|
||||
tvName.setError(
|
||||
res.getString(R.string.validation_name_should_not_be_blank));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Parcelable state)
|
||||
{
|
||||
BundleSavedState bss = (BundleSavedState) state;
|
||||
setColor(bss.bundle.getInt("color"));
|
||||
super.onRestoreInstanceState(bss.getSuperState());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Parcelable onSaveInstanceState()
|
||||
{
|
||||
Parcelable superState = super.onSaveInstanceState();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putInt("color", color);
|
||||
return new BundleSavedState(superState, bundle);
|
||||
}
|
||||
|
||||
@OnClick(R.id.buttonPickColor)
|
||||
void showColorPicker()
|
||||
{
|
||||
controller.onColorPickerClicked(color);
|
||||
}
|
||||
|
||||
public void setController(@NonNull Controller controller)
|
||||
{
|
||||
this.controller = controller;
|
||||
}
|
||||
|
||||
public interface Controller
|
||||
{
|
||||
/**
|
||||
* Called when the user has clicked the widget to select a new
|
||||
* color for the habit.
|
||||
*
|
||||
* @param previousColor the color previously selected
|
||||
*/
|
||||
default void onColorPickerClicked(int previousColor) {}
|
||||
}
|
||||
}
|
@ -1,197 +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.views;
|
||||
|
||||
import android.content.*;
|
||||
import android.os.*;
|
||||
import android.util.*;
|
||||
import android.view.*;
|
||||
import android.widget.*;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
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.core.models.*;
|
||||
import org.isoron.uhabits.utils.*;
|
||||
|
||||
import butterknife.*;
|
||||
|
||||
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 = AndroidDateUtils.formatTime(ctx, reminder.getHour(), reminder.getMinute());
|
||||
tvReminderTime.setText(time);
|
||||
llReminderDays.setVisibility(View.VISIBLE);
|
||||
|
||||
boolean weekdays[] = reminder.getDays().toArray();
|
||||
tvReminderDays.setText(AndroidDateUtils.formatWeekdayList(ctx, weekdays));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTimeCleared(RadialPickerLayout view)
|
||||
{
|
||||
setReminder(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTimeSet(RadialPickerLayout view, int hour, int minute)
|
||||
{
|
||||
WeekdayList days = WeekdayList.EVERY_DAY;
|
||||
if (reminder != null) days = reminder.getDays();
|
||||
setReminder(new Reminder(hour, minute, days));
|
||||
}
|
||||
|
||||
@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) {}
|
||||
}
|
||||
}
|
@ -1,93 +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.views;
|
||||
|
||||
import android.content.*;
|
||||
import android.content.res.*;
|
||||
import android.util.*;
|
||||
import android.view.*;
|
||||
import android.widget.*;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.isoron.uhabits.R;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
import butterknife.*;
|
||||
|
||||
|
||||
public class TargetPanel extends FrameLayout
|
||||
{
|
||||
private DecimalFormat valueFormatter = new DecimalFormat("#.##");
|
||||
|
||||
@BindView(R.id.tvUnit)
|
||||
ExampleEditText tvUnit;
|
||||
|
||||
@BindView(R.id.tvTargetCount)
|
||||
TextView tvTargetValue;
|
||||
|
||||
public TargetPanel(@NonNull Context context, @Nullable AttributeSet attrs)
|
||||
{
|
||||
super(context, attrs);
|
||||
|
||||
View view = inflate(context, R.layout.edit_habit_target, null);
|
||||
ButterKnife.bind(this, view);
|
||||
addView(view);
|
||||
}
|
||||
|
||||
public double getTargetValue()
|
||||
{
|
||||
String sValue = tvTargetValue.getText().toString();
|
||||
return Double.parseDouble(sValue);
|
||||
}
|
||||
|
||||
public void setTargetValue(double targetValue)
|
||||
{
|
||||
tvTargetValue.setText(valueFormatter.format(targetValue));
|
||||
}
|
||||
|
||||
public String getUnit()
|
||||
{
|
||||
return tvUnit.getRealText();
|
||||
}
|
||||
|
||||
public void setUnit(String unit)
|
||||
{
|
||||
tvUnit.setRealText(unit);
|
||||
}
|
||||
|
||||
public boolean validate()
|
||||
{
|
||||
Resources res = getResources();
|
||||
String sValue = tvTargetValue.getText().toString();
|
||||
double value = Double.parseDouble(sValue);
|
||||
|
||||
if (value <= 0)
|
||||
{
|
||||
tvTargetValue.setError(
|
||||
res.getString(R.string.validation_number_should_be_positive));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="?attr/highContrastReverseTextColor"/>
|
||||
<stroke android:width="1dp" android:color="?attr/lowContrastTextColor" />
|
||||
<corners android:radius="4dp"/>
|
||||
<padding
|
||||
android:left="8dp"
|
||||
android:top="8dp"
|
||||
android:right="8dp"
|
||||
android:bottom="8dp" />
|
||||
</shape>
|
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="?attr/highContrastReverseTextColor"/>
|
||||
<stroke android:width="1dp" android:color="?attr/lowContrastTextColor" />
|
||||
<corners android:radius="4dp"/>
|
||||
<padding
|
||||
android:left="0dp"
|
||||
android:top="8dp"
|
||||
android:right="0dp"
|
||||
android:bottom="0dp" />
|
||||
</shape>
|
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="?attr/mediumContrastTextColor"
|
||||
android:pathData="M7,10l5,5 5,-5z"/>
|
||||
</vector>
|
@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2016-2020 Á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/>.
|
||||
-->
|
||||
|
||||
<ripple
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:color="?colorAccent">
|
||||
<item android:gravity="center">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="?cardBgColor"/>
|
||||
<corners android:radius="5dp" />
|
||||
</shape>
|
||||
</item>
|
||||
</ripple>
|
@ -0,0 +1,220 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/highContrastReverseTextColor"
|
||||
android:fitsSystemWindows="true"
|
||||
android:orientation="vertical"
|
||||
tools:context=".activities.habits.edit.EditHabitActivity">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/colorPrimary"
|
||||
android:elevation="2dp"
|
||||
android:gravity="end"
|
||||
android:minHeight="?attr/actionBarSize"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
|
||||
app:title="@string/create_habit"
|
||||
app:titleTextColor="@color/white">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/buttonSave"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="@string/save"
|
||||
android:textColor="@color/white"
|
||||
app:rippleColor="@color/white"
|
||||
app:strokeColor="@color/white" />
|
||||
</androidx.appcompat.widget.Toolbar>
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="8dp">
|
||||
|
||||
|
||||
<!-- Title and color -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<!-- Habit Title -->
|
||||
<FrameLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="vertical"
|
||||
android:padding="8dp">
|
||||
|
||||
<LinearLayout style="@style/FormInnerBox">
|
||||
<TextView
|
||||
style="@style/FormLabel"
|
||||
android:text="@string/name" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/nameInput"
|
||||
style="@style/FormInput"
|
||||
android:maxLines="1"
|
||||
android:inputType="textCapSentences"
|
||||
android:hint="@string/exercise_habit_name"
|
||||
/>
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
|
||||
<!-- Habit Color -->
|
||||
<FrameLayout
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="match_parent"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="vertical"
|
||||
android:padding="8dp"
|
||||
android:paddingStart="0dp">
|
||||
|
||||
<LinearLayout style="@style/FormInnerBox">
|
||||
<TextView
|
||||
style="@style/FormLabel"
|
||||
android:text="Color" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/colorButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:backgroundTint="#E23673" />
|
||||
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<!-- Habit Question -->
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="vertical"
|
||||
android:padding="8dp"
|
||||
android:paddingTop="4dp">
|
||||
|
||||
<LinearLayout style="@style/FormInnerBox">
|
||||
<TextView
|
||||
style="@style/FormLabel"
|
||||
android:text="@string/question" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/questionInput"
|
||||
style="@style/FormInput"
|
||||
android:inputType="textCapSentences|textMultiLine"
|
||||
android:hint="@string/example_question_boolean"
|
||||
/>
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
|
||||
<!-- Frequency -->
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="vertical"
|
||||
android:padding="8dp"
|
||||
android:paddingTop="4dp">
|
||||
|
||||
<LinearLayout style="@style/FormInnerBox">
|
||||
<TextView
|
||||
style="@style/FormLabel"
|
||||
android:text="@string/frequency" />
|
||||
|
||||
<TextView
|
||||
style="@style/FormDropdown"
|
||||
android:id="@+id/frequencyPicker"
|
||||
android:textColor="?attr/highContrastTextColor"
|
||||
/>
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
|
||||
<!-- Reminder -->
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="vertical"
|
||||
android:padding="8dp">
|
||||
|
||||
<LinearLayout style="@style/FormInnerBox">
|
||||
<TextView
|
||||
style="@style/FormLabel"
|
||||
android:text="@string/reminder" />
|
||||
|
||||
<TextView
|
||||
style="@style/FormDropdown"
|
||||
android:id="@+id/reminderTimePicker"
|
||||
android:text="@string/reminder_off" />
|
||||
|
||||
<View
|
||||
style="@style/FormDivider"
|
||||
android:id="@+id/reminderDivider"/>
|
||||
|
||||
<TextView
|
||||
style="@style/FormDropdown"
|
||||
android:id="@+id/reminderDatePicker"
|
||||
android:text="" />
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
|
||||
|
||||
<!-- Notes -->
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="vertical"
|
||||
android:padding="8dp">
|
||||
|
||||
<LinearLayout style="@style/FormInnerBox">
|
||||
<TextView
|
||||
style="@style/FormLabel"
|
||||
android:text="@string/notes" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/notesInput"
|
||||
style="@style/FormInput"
|
||||
android:inputType="textCapSentences|textMultiLine"
|
||||
android:hint="@string/example_notes" />
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
@ -1,82 +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/>.
|
||||
-->
|
||||
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/container"
|
||||
style="@style/dialogForm"
|
||||
tools:context=".activities.habits.edit.EditHabitDialog"
|
||||
tools:ignore="MergeRootFrame">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/formPanel"
|
||||
style="@style/dialogFormPanel">
|
||||
|
||||
<org.isoron.uhabits.activities.habits.edit.views.NameDescriptionPanel
|
||||
android:id="@+id/namePanel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<org.isoron.uhabits.activities.habits.edit.views.FrequencyPanel
|
||||
android:id="@+id/frequencyPanel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<org.isoron.uhabits.activities.habits.edit.views.TargetPanel
|
||||
android:id="@+id/targetPanel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<org.isoron.uhabits.activities.habits.edit.views.ReminderPanel
|
||||
android:id="@+id/reminderPanel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
style="?android:attr/buttonBarStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="end"
|
||||
android:paddingStart="0dp"
|
||||
android:paddingLeft="0dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingRight="16dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/buttonDiscard"
|
||||
style="?android:attr/buttonBarButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/discard" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/buttonSave"
|
||||
style="?android:attr/buttonBarButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/save" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
@ -1,69 +0,0 @@
|
||||
<?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:layout_marginTop="12dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
style="@style/dialogFormLabel"
|
||||
android:text="@string/repeat"/>
|
||||
|
||||
<androidx.appcompat.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>
|
@ -1,98 +0,0 @@
|
||||
<?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/>.
|
||||
-->
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://isoron.org/android"
|
||||
xmlns:app1="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minWidth="300dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/tilName"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app1:layout_constraintEnd_toStartOf="@+id/buttonPickColor"
|
||||
app1:layout_constraintHorizontal_weight="6"
|
||||
app1:layout_constraintStart_toStartOf="parent"
|
||||
app1:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/tvName"
|
||||
style="@style/dialogFormInput"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="start"
|
||||
android:gravity="center_vertical"
|
||||
android:hint="@string/name">
|
||||
|
||||
<requestFocus />
|
||||
</EditText>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/buttonPickColor"
|
||||
style="@style/dialogFormInputColor"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/color_picker_default_title"
|
||||
android:src="?dialogIconChangeColor"
|
||||
app1:layout_constraintBottom_toBottomOf="@id/tilName"
|
||||
app1:layout_constraintEnd_toEndOf="parent"
|
||||
app1:layout_constraintHorizontal_weight="1"
|
||||
app1:layout_constraintStart_toEndOf="@+id/tilName"
|
||||
app1:layout_constraintTop_toTopOf="@id/tilName" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/tilQuestion"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/question"
|
||||
app1:layout_constraintEnd_toEndOf="parent"
|
||||
app1:layout_constraintStart_toStartOf="parent"
|
||||
app1:layout_constraintTop_toBottomOf="@id/tilName">
|
||||
|
||||
<org.isoron.uhabits.activities.habits.edit.views.ExampleEditText
|
||||
android:id="@+id/tvQuestion"
|
||||
style="@style/dialogFormInput"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:example="@string/example_question_numerical" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:hint="@string/notes"
|
||||
app1:layout_constraintBottom_toBottomOf="parent"
|
||||
app1:layout_constraintEnd_toEndOf="parent"
|
||||
app1:layout_constraintStart_toStartOf="parent"
|
||||
app1:layout_constraintTop_toBottomOf="@id/tilQuestion">
|
||||
|
||||
<org.isoron.uhabits.activities.habits.edit.views.ExampleEditText
|
||||
android:id="@+id/tvDescription"
|
||||
style="@style/dialogFormInputMultiline"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="top"
|
||||
app:example="@string/example_notes" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -1,52 +0,0 @@
|
||||
<?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:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
style="@style/dialogFormRow"
|
||||
android:layout_marginTop="12dp">
|
||||
|
||||
<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"
|
||||
android:layout_marginTop="12dp">
|
||||
|
||||
<TextView
|
||||
style="@style/dialogFormLabel"
|
||||
android:text=""/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvReminderDays"
|
||||
style="@style/dialogFormSpinner"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
@ -1,62 +0,0 @@
|
||||
<?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"
|
||||
xmlns:app="http://isoron.org/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
style="@style/dialogFormLabel"
|
||||
android:text="@string/target"/>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="2">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/tvTargetCount"
|
||||
style="@style/dialogFormInput"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/count"
|
||||
android:inputType="numberDecimal"
|
||||
android:text="@string/default_count"
|
||||
/>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="2">
|
||||
|
||||
<org.isoron.uhabits.activities.habits.edit.views.ExampleEditText
|
||||
android:id="@+id/tvUnit"
|
||||
style="@style/dialogFormInput"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/unit"
|
||||
android:inputType="text"
|
||||
app:example="@string/example_units"/>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
</LinearLayout>
|
@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_margin="0dp"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/everyDayRadioButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/every_day" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/everyXDaysRadioButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Every" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/everyXDaysTextView"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="40dp"
|
||||
android:gravity="center"
|
||||
android:background="@drawable/bg_input_box"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:inputType="number"
|
||||
android:maxLength="2"
|
||||
android:text="3" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="days" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/xTimesPerWeekRadioButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/xTimesPerWeekTextView"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="40dp"
|
||||
android:gravity="center"
|
||||
android:background="@drawable/bg_input_box"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:inputType="number"
|
||||
android:maxLength="2"
|
||||
android:text="5" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="times per week" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/xTimesPerMonthRadioButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/xTimesPerMonthTextView"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="40dp"
|
||||
android:gravity="center"
|
||||
android:background="@drawable/bg_input_box"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:inputType="number"
|
||||
android:maxLength="2"
|
||||
android:text="10" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="times per month" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
@ -0,0 +1,89 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2016-2020 Á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:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:background="#a0000000"
|
||||
android:clickable="true"
|
||||
android:id="@+id/background"
|
||||
>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/buttonYesNo"
|
||||
style="@style/SelectHabitTypeButton">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/SelectHabitTypeButtonTitle"
|
||||
android:text="@string/yes_or_no" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/SelectHabitTypeButtonBody"
|
||||
android:text="@string/yes_or_no_example" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/buttonMeasurable"
|
||||
style="@style/SelectHabitTypeButton">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/SelectHabitTypeButtonTitle"
|
||||
android:text="@string/measurable" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/SelectHabitTypeButtonBody"
|
||||
android:text="@string/measurable_example" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/buttonSubjective"
|
||||
style="@style/SelectHabitTypeButton">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/SelectHabitTypeButtonTitle"
|
||||
android:text="@string/subjective" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/SelectHabitTypeButtonBody"
|
||||
android:text="@string/subjective_example" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
Loading…
Reference in new issue