mirror of https://github.com/iSoron/uhabits.git
parent
71a05d598a
commit
908eb4ac99
@ -1,128 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
|
||||||
*
|
|
||||||
* 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.Dialog
|
|
||||||
import android.content.Context
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.View.GONE
|
|
||||||
import android.view.View.VISIBLE
|
|
||||||
import org.isoron.uhabits.R
|
|
||||||
import org.isoron.uhabits.core.models.Entry.Companion.NO
|
|
||||||
import org.isoron.uhabits.core.models.Entry.Companion.SKIP
|
|
||||||
import org.isoron.uhabits.core.models.Entry.Companion.UNKNOWN
|
|
||||||
import org.isoron.uhabits.core.models.Entry.Companion.YES_AUTO
|
|
||||||
import org.isoron.uhabits.core.models.Entry.Companion.YES_MANUAL
|
|
||||||
import org.isoron.uhabits.core.preferences.Preferences
|
|
||||||
import org.isoron.uhabits.databinding.CheckmarkPopupBinding
|
|
||||||
import org.isoron.uhabits.utils.InterfaceUtils.getFontAwesome
|
|
||||||
import org.isoron.uhabits.utils.dimBehind
|
|
||||||
import org.isoron.uhabits.utils.dismissCurrentAndShow
|
|
||||||
import org.isoron.uhabits.utils.dp
|
|
||||||
import org.isoron.uhabits.utils.sres
|
|
||||||
|
|
||||||
const val POPUP_WIDTH = 4 * 48f + 16f
|
|
||||||
const val POPUP_HEIGHT = 48f * 2.5f + 8f
|
|
||||||
|
|
||||||
class CheckmarkPopup(
|
|
||||||
private val context: Context,
|
|
||||||
private val color: Int,
|
|
||||||
private var notes: String,
|
|
||||||
private var value: Int,
|
|
||||||
private val prefs: Preferences,
|
|
||||||
private val anchor: View,
|
|
||||||
) {
|
|
||||||
var onToggle: (Int, String) -> Unit = { _, _ -> }
|
|
||||||
private lateinit var dialog: Dialog
|
|
||||||
|
|
||||||
private val view = CheckmarkPopupBinding.inflate(LayoutInflater.from(context)).apply {
|
|
||||||
// Required for round corners
|
|
||||||
container.clipToOutline = true
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
view.booleanButtons.visibility = VISIBLE
|
|
||||||
initColors()
|
|
||||||
initTypefaces()
|
|
||||||
hideDisabledButtons()
|
|
||||||
populate()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initColors() {
|
|
||||||
arrayOf(view.yesBtn, view.skipBtn).forEach {
|
|
||||||
it.setTextColor(color)
|
|
||||||
}
|
|
||||||
arrayOf(view.noBtn, view.unknownBtn).forEach {
|
|
||||||
it.setTextColor(view.root.sres.getColor(R.attr.contrast60))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initTypefaces() {
|
|
||||||
arrayOf(view.yesBtn, view.noBtn, view.skipBtn, view.unknownBtn).forEach {
|
|
||||||
it.typeface = getFontAwesome(context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun hideDisabledButtons() {
|
|
||||||
if (!prefs.isSkipEnabled) view.skipBtn.visibility = GONE
|
|
||||||
if (!prefs.areQuestionMarksEnabled) view.unknownBtn.visibility = GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun populate() {
|
|
||||||
val selectedBtn = when (value) {
|
|
||||||
YES_MANUAL -> view.yesBtn
|
|
||||||
YES_AUTO -> view.noBtn
|
|
||||||
NO -> view.noBtn
|
|
||||||
UNKNOWN -> if (prefs.areQuestionMarksEnabled) view.unknownBtn else view.noBtn
|
|
||||||
SKIP -> if (prefs.isSkipEnabled) view.skipBtn else view.noBtn
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
view.notes.setText(notes)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun show() {
|
|
||||||
dialog = Dialog(context, android.R.style.Theme_NoTitleBar)
|
|
||||||
dialog.setContentView(view.root)
|
|
||||||
dialog.window?.apply {
|
|
||||||
setLayout(
|
|
||||||
view.root.dp(POPUP_WIDTH).toInt(),
|
|
||||||
view.root.dp(POPUP_HEIGHT).toInt()
|
|
||||||
)
|
|
||||||
setBackgroundDrawableResource(android.R.color.transparent)
|
|
||||||
}
|
|
||||||
fun onClick(v: Int) {
|
|
||||||
this.value = v
|
|
||||||
save()
|
|
||||||
}
|
|
||||||
view.yesBtn.setOnClickListener { onClick(YES_MANUAL) }
|
|
||||||
view.noBtn.setOnClickListener { onClick(NO) }
|
|
||||||
view.skipBtn.setOnClickListener { onClick(SKIP) }
|
|
||||||
view.unknownBtn.setOnClickListener { onClick(UNKNOWN) }
|
|
||||||
dialog.setCanceledOnTouchOutside(true)
|
|
||||||
dialog.dimBehind()
|
|
||||||
dialog.dismissCurrentAndShow()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun save() {
|
|
||||||
onToggle(value, view.notes.text.toString().trim())
|
|
||||||
dialog.dismiss()
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,104 @@
|
|||||||
|
package org.isoron.uhabits.activities.common.dialogs
|
||||||
|
|
||||||
|
import android.app.Dialog
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.text.method.DigitsKeyListener
|
||||||
|
import android.view.KeyEvent
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import android.view.View
|
||||||
|
import androidx.appcompat.app.AppCompatDialogFragment
|
||||||
|
import org.isoron.uhabits.HabitsApplication
|
||||||
|
import org.isoron.uhabits.R
|
||||||
|
import org.isoron.uhabits.core.models.Entry
|
||||||
|
import org.isoron.uhabits.databinding.CheckmarkPopupBinding
|
||||||
|
import org.isoron.uhabits.utils.InterfaceUtils
|
||||||
|
import org.isoron.uhabits.utils.requestFocusWithKeyboard
|
||||||
|
import org.isoron.uhabits.utils.sres
|
||||||
|
import java.text.DecimalFormat
|
||||||
|
import java.text.DecimalFormatSymbols
|
||||||
|
import java.text.NumberFormat
|
||||||
|
import java.text.ParseException
|
||||||
|
|
||||||
|
class NumberDialog : AppCompatDialogFragment() {
|
||||||
|
|
||||||
|
var onToggle: (Double, String) -> Unit = { _, _ -> }
|
||||||
|
var onDismiss: () -> Unit = {}
|
||||||
|
|
||||||
|
private var originalNotes: String = ""
|
||||||
|
private var originalValue: Double = 0.0
|
||||||
|
private lateinit var view: CheckmarkPopupBinding
|
||||||
|
|
||||||
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
|
val appComponent = (requireActivity().application as HabitsApplication).component
|
||||||
|
val prefs = appComponent.preferences
|
||||||
|
view = CheckmarkPopupBinding.inflate(LayoutInflater.from(context))
|
||||||
|
arrayOf(view.yesBtn, view.skipBtn).forEach {
|
||||||
|
it.setTextColor(requireArguments().getInt("color"))
|
||||||
|
}
|
||||||
|
arrayOf(view.noBtn, view.unknownBtn).forEach {
|
||||||
|
it.setTextColor(view.root.sres.getColor(R.attr.contrast60))
|
||||||
|
}
|
||||||
|
arrayOf(view.yesBtn, view.noBtn, view.skipBtn, view.unknownBtn).forEach {
|
||||||
|
it.typeface = InterfaceUtils.getFontAwesome(requireContext())
|
||||||
|
}
|
||||||
|
if (!prefs.isSkipEnabled) view.skipBtnNumber.visibility = View.GONE
|
||||||
|
view.numberButtons.visibility = View.VISIBLE
|
||||||
|
fixDecimalSeparator(view)
|
||||||
|
originalNotes = requireArguments().getString("notes")!!
|
||||||
|
originalValue = requireArguments().getDouble("value")
|
||||||
|
view.notes.setText(originalNotes)
|
||||||
|
view.value.setText(
|
||||||
|
when {
|
||||||
|
originalValue < 0.01 -> "0"
|
||||||
|
else -> DecimalFormat("#.##").format(originalValue)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
view.value.setOnKeyListener { _, keyCode, event ->
|
||||||
|
if (event.action == MotionEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_ENTER) {
|
||||||
|
save()
|
||||||
|
return@setOnKeyListener true
|
||||||
|
}
|
||||||
|
return@setOnKeyListener false
|
||||||
|
}
|
||||||
|
view.saveBtn.setOnClickListener {
|
||||||
|
save()
|
||||||
|
}
|
||||||
|
view.skipBtnNumber.setOnClickListener {
|
||||||
|
view.value.setText((Entry.SKIP.toDouble() / 1000).toString())
|
||||||
|
save()
|
||||||
|
}
|
||||||
|
view.notes.setOnEditorActionListener { v, actionId, event ->
|
||||||
|
save()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
view.value.requestFocusWithKeyboard()
|
||||||
|
val dialog = Dialog(requireContext())
|
||||||
|
dialog.setContentView(view.root)
|
||||||
|
dialog.window?.apply {
|
||||||
|
setBackgroundDrawableResource(android.R.color.transparent)
|
||||||
|
}
|
||||||
|
dialog.setOnDismissListener { onDismiss() }
|
||||||
|
return dialog
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun fixDecimalSeparator(view: CheckmarkPopupBinding) {
|
||||||
|
// https://stackoverflow.com/a/34256139
|
||||||
|
val separator = DecimalFormatSymbols.getInstance().decimalSeparator
|
||||||
|
view.value.keyListener = DigitsKeyListener.getInstance("0123456789$separator")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun save() {
|
||||||
|
var value = originalValue
|
||||||
|
try {
|
||||||
|
val numberFormat = NumberFormat.getInstance()
|
||||||
|
val valueStr = view.value.text.toString()
|
||||||
|
value = numberFormat.parse(valueStr)!!.toDouble()
|
||||||
|
} catch (e: ParseException) {
|
||||||
|
// NOP
|
||||||
|
}
|
||||||
|
val notes = view.notes.text.toString()
|
||||||
|
onToggle(value, notes)
|
||||||
|
requireDialog().dismiss()
|
||||||
|
}
|
||||||
|
}
|
@ -1,134 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
|
||||||
*
|
|
||||||
* 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.Dialog
|
|
||||||
import android.content.Context
|
|
||||||
import android.text.method.DigitsKeyListener
|
|
||||||
import android.view.KeyEvent.KEYCODE_ENTER
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.MotionEvent.ACTION_DOWN
|
|
||||||
import android.view.View
|
|
||||||
import android.view.View.GONE
|
|
||||||
import android.view.View.VISIBLE
|
|
||||||
import org.isoron.uhabits.core.models.Entry
|
|
||||||
import org.isoron.uhabits.core.preferences.Preferences
|
|
||||||
import org.isoron.uhabits.databinding.CheckmarkPopupBinding
|
|
||||||
import org.isoron.uhabits.utils.dimBehind
|
|
||||||
import org.isoron.uhabits.utils.dismissCurrentAndShow
|
|
||||||
import org.isoron.uhabits.utils.dp
|
|
||||||
import org.isoron.uhabits.utils.requestFocusWithKeyboard
|
|
||||||
import java.text.DecimalFormat
|
|
||||||
import java.text.DecimalFormatSymbols
|
|
||||||
import java.text.NumberFormat
|
|
||||||
import java.text.ParseException
|
|
||||||
|
|
||||||
class NumberPopup(
|
|
||||||
private val context: Context,
|
|
||||||
private var notes: String,
|
|
||||||
private var value: Double,
|
|
||||||
private val prefs: Preferences,
|
|
||||||
private val anchor: View,
|
|
||||||
) {
|
|
||||||
var onToggle: (Double, String) -> Unit = { _, _ -> }
|
|
||||||
var onDismiss: () -> Unit = {}
|
|
||||||
private val originalValue = value
|
|
||||||
private lateinit var dialog: Dialog
|
|
||||||
|
|
||||||
private val view = CheckmarkPopupBinding.inflate(LayoutInflater.from(context)).apply {
|
|
||||||
// Required for round corners
|
|
||||||
container.clipToOutline = true
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
view.numberButtons.visibility = VISIBLE
|
|
||||||
fixDecimalSeparator()
|
|
||||||
hideDisabledButtons()
|
|
||||||
populate()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun fixDecimalSeparator() {
|
|
||||||
// https://stackoverflow.com/a/34256139
|
|
||||||
val separator = DecimalFormatSymbols.getInstance().decimalSeparator
|
|
||||||
view.value.keyListener = DigitsKeyListener.getInstance("0123456789$separator")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun hideDisabledButtons() {
|
|
||||||
if (!prefs.isSkipEnabled) view.skipBtnNumber.visibility = GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun populate() {
|
|
||||||
view.notes.setText(notes)
|
|
||||||
view.value.setText(
|
|
||||||
when {
|
|
||||||
value < 0.01 -> "0"
|
|
||||||
else -> DecimalFormat("#.##").format(value)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun show() {
|
|
||||||
dialog = Dialog(context, android.R.style.Theme_NoTitleBar)
|
|
||||||
dialog.setContentView(view.root)
|
|
||||||
dialog.window?.apply {
|
|
||||||
setLayout(
|
|
||||||
view.root.dp(POPUP_WIDTH).toInt(),
|
|
||||||
view.root.dp(POPUP_HEIGHT).toInt()
|
|
||||||
)
|
|
||||||
setBackgroundDrawableResource(android.R.color.transparent)
|
|
||||||
}
|
|
||||||
dialog.setOnDismissListener {
|
|
||||||
onDismiss()
|
|
||||||
}
|
|
||||||
|
|
||||||
view.value.setOnKeyListener { _, keyCode, event ->
|
|
||||||
if (event.action == ACTION_DOWN && keyCode == KEYCODE_ENTER) {
|
|
||||||
save()
|
|
||||||
return@setOnKeyListener true
|
|
||||||
}
|
|
||||||
return@setOnKeyListener false
|
|
||||||
}
|
|
||||||
view.saveBtn.setOnClickListener {
|
|
||||||
save()
|
|
||||||
}
|
|
||||||
view.skipBtnNumber.setOnClickListener {
|
|
||||||
view.value.setText((Entry.SKIP.toDouble() / 1000).toString())
|
|
||||||
save()
|
|
||||||
}
|
|
||||||
view.value.requestFocusWithKeyboard()
|
|
||||||
dialog.setCanceledOnTouchOutside(true)
|
|
||||||
dialog.dimBehind()
|
|
||||||
dialog.dismissCurrentAndShow()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun save() {
|
|
||||||
var value = originalValue
|
|
||||||
try {
|
|
||||||
val numberFormat = NumberFormat.getInstance()
|
|
||||||
val valueStr = view.value.text.toString()
|
|
||||||
value = numberFormat.parse(valueStr)!!.toDouble()
|
|
||||||
} catch (e: ParseException) {
|
|
||||||
// NOP
|
|
||||||
}
|
|
||||||
val notes = view.notes.text.toString()
|
|
||||||
onToggle(value, notes)
|
|
||||||
dialog.dismiss()
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in new issue