2021-04-16 22:39:19 -04:00
|
|
|
package eu.kanade.tachiyomi.widget
|
2021-03-27 16:28:49 -04:00
|
|
|
|
2021-04-16 22:39:19 -04:00
|
|
|
import android.annotation.SuppressLint
|
2021-03-27 16:28:49 -04:00
|
|
|
import android.content.Context
|
|
|
|
import android.util.AttributeSet
|
|
|
|
import android.view.Gravity
|
|
|
|
import android.view.LayoutInflater
|
|
|
|
import android.view.MenuItem
|
|
|
|
import android.widget.FrameLayout
|
|
|
|
import androidx.annotation.ArrayRes
|
2021-08-27 16:33:12 -04:00
|
|
|
import androidx.appcompat.content.res.AppCompatResources
|
2021-04-16 22:39:19 -04:00
|
|
|
import androidx.appcompat.view.menu.MenuBuilder
|
2021-03-27 16:28:49 -04:00
|
|
|
import androidx.appcompat.widget.PopupMenu
|
2021-04-16 22:39:19 -04:00
|
|
|
import androidx.core.view.forEach
|
|
|
|
import androidx.core.view.get
|
2021-03-27 16:28:49 -04:00
|
|
|
import com.tfcporciuncula.flow.Preference
|
|
|
|
import eu.kanade.tachiyomi.R
|
|
|
|
import eu.kanade.tachiyomi.databinding.SpinnerPreferenceBinding
|
2021-04-16 22:39:19 -04:00
|
|
|
import eu.kanade.tachiyomi.util.system.getResourceColor
|
2021-03-27 16:28:49 -04:00
|
|
|
|
2021-04-16 22:39:19 -04:00
|
|
|
class MaterialSpinnerView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
2021-03-27 16:28:49 -04:00
|
|
|
FrameLayout(context, attrs) {
|
|
|
|
|
|
|
|
private var entries = emptyList<String>()
|
2021-04-16 22:39:19 -04:00
|
|
|
private var selectedPosition = 0
|
2021-03-27 16:28:49 -04:00
|
|
|
private var popup: PopupMenu? = null
|
|
|
|
|
|
|
|
var onItemSelectedListener: ((Int) -> Unit)? = null
|
|
|
|
set(value) {
|
|
|
|
field = value
|
|
|
|
if (value != null) {
|
|
|
|
popup = makeSettingsPopup()
|
|
|
|
setOnTouchListener(popup?.dragToOpenListener)
|
|
|
|
setOnClickListener {
|
|
|
|
popup?.show()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-16 22:39:19 -04:00
|
|
|
private val emptyIcon by lazy {
|
2021-08-27 16:33:12 -04:00
|
|
|
AppCompatResources.getDrawable(context, R.drawable.ic_blank_24dp)
|
2021-04-16 22:39:19 -04:00
|
|
|
}
|
|
|
|
private val checkmarkIcon by lazy {
|
2021-08-27 16:33:12 -04:00
|
|
|
AppCompatResources.getDrawable(context, R.drawable.ic_check_24dp)?.mutate()?.apply {
|
2021-04-16 22:39:19 -04:00
|
|
|
setTint(context.getResourceColor(android.R.attr.textColorPrimary))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-27 16:28:49 -04:00
|
|
|
private val binding = SpinnerPreferenceBinding.inflate(LayoutInflater.from(context), this, false)
|
|
|
|
|
|
|
|
init {
|
|
|
|
addView(binding.root)
|
|
|
|
|
2021-04-16 22:39:19 -04:00
|
|
|
val attr = context.obtainStyledAttributes(attrs, R.styleable.MaterialSpinnerView)
|
2021-03-27 16:28:49 -04:00
|
|
|
|
2021-04-16 22:39:19 -04:00
|
|
|
val title = attr.getString(R.styleable.MaterialSpinnerView_title).orEmpty()
|
2021-03-28 16:13:59 -04:00
|
|
|
binding.title.text = title
|
2021-03-27 16:28:49 -04:00
|
|
|
|
2021-04-16 22:39:19 -04:00
|
|
|
val entries = (attr.getTextArray(R.styleable.MaterialSpinnerView_android_entries) ?: emptyArray()).map { it.toString() }
|
2021-03-27 16:28:49 -04:00
|
|
|
this.entries = entries
|
|
|
|
binding.details.text = entries.firstOrNull().orEmpty()
|
|
|
|
|
2021-03-28 16:13:59 -04:00
|
|
|
attr.recycle()
|
2021-03-27 16:28:49 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
fun setSelection(selection: Int) {
|
2021-04-16 22:39:19 -04:00
|
|
|
popup?.menu?.get(selectedPosition)?.let {
|
|
|
|
it.icon = emptyIcon
|
|
|
|
it.title = entries[selectedPosition]
|
|
|
|
}
|
|
|
|
selectedPosition = selection
|
|
|
|
popup?.menu?.get(selectedPosition)?.let {
|
|
|
|
it.icon = checkmarkIcon
|
|
|
|
}
|
2021-03-27 16:28:49 -04:00
|
|
|
binding.details.text = entries.getOrNull(selection).orEmpty()
|
|
|
|
}
|
|
|
|
|
|
|
|
fun bindToPreference(pref: Preference<Int>, offset: Int = 0, block: ((Int) -> Unit)? = null) {
|
|
|
|
setSelection(pref.get() - offset)
|
2021-03-28 16:13:59 -04:00
|
|
|
|
2021-03-28 17:06:56 -04:00
|
|
|
popup = makeSettingsPopup(pref, offset, block)
|
2021-03-27 16:28:49 -04:00
|
|
|
setOnTouchListener(popup?.dragToOpenListener)
|
|
|
|
setOnClickListener {
|
|
|
|
popup?.show()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inline fun <reified T : Enum<T>> bindToPreference(pref: Preference<T>) {
|
|
|
|
val enumConstants = T::class.java.enumConstants
|
|
|
|
enumConstants?.indexOf(pref.get())?.let { setSelection(it) }
|
2021-03-28 16:13:59 -04:00
|
|
|
|
2021-03-27 16:28:49 -04:00
|
|
|
val popup = makeSettingsPopup(pref)
|
|
|
|
setOnTouchListener(popup.dragToOpenListener)
|
|
|
|
setOnClickListener {
|
|
|
|
popup.show()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fun bindToIntPreference(pref: Preference<Int>, @ArrayRes intValuesResource: Int, block: ((Int) -> Unit)? = null) {
|
|
|
|
val intValues = resources.getStringArray(intValuesResource).map { it.toIntOrNull() }
|
2021-03-28 17:06:56 -04:00
|
|
|
setSelection(intValues.indexOf(pref.get()))
|
2021-03-28 16:13:59 -04:00
|
|
|
|
2021-03-27 16:28:49 -04:00
|
|
|
popup = makeSettingsPopup(pref, intValues, block)
|
|
|
|
setOnTouchListener(popup?.dragToOpenListener)
|
|
|
|
setOnClickListener {
|
|
|
|
popup?.show()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inline fun <reified T : Enum<T>> makeSettingsPopup(preference: Preference<T>): PopupMenu {
|
2021-03-28 16:13:59 -04:00
|
|
|
return createPopupMenu { pos ->
|
2021-03-27 16:28:49 -04:00
|
|
|
onItemSelectedListener?.invoke(pos)
|
2021-03-28 16:13:59 -04:00
|
|
|
|
2021-03-27 16:28:49 -04:00
|
|
|
val enumConstants = T::class.java.enumConstants
|
2021-03-28 16:13:59 -04:00
|
|
|
enumConstants?.get(pos)?.let { enumValue -> preference.set(enumValue) }
|
2021-03-27 16:28:49 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun makeSettingsPopup(preference: Preference<Int>, intValues: List<Int?>, block: ((Int) -> Unit)? = null): PopupMenu {
|
2021-03-28 16:13:59 -04:00
|
|
|
return createPopupMenu { pos ->
|
2021-03-27 16:28:49 -04:00
|
|
|
preference.set(intValues[pos] ?: 0)
|
|
|
|
block?.invoke(pos)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun makeSettingsPopup(preference: Preference<Int>, offset: Int = 0, block: ((Int) -> Unit)? = null): PopupMenu {
|
2021-03-28 16:13:59 -04:00
|
|
|
return createPopupMenu { pos ->
|
2021-03-27 16:28:49 -04:00
|
|
|
preference.set(pos + offset)
|
|
|
|
block?.invoke(pos)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun makeSettingsPopup(): PopupMenu {
|
2021-03-28 16:13:59 -04:00
|
|
|
return createPopupMenu { pos ->
|
2021-03-27 16:28:49 -04:00
|
|
|
onItemSelectedListener?.invoke(pos)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-28 16:13:59 -04:00
|
|
|
private fun menuClicked(menuItem: MenuItem): Int {
|
2021-03-27 16:28:49 -04:00
|
|
|
val pos = menuItem.itemId
|
|
|
|
setSelection(pos)
|
|
|
|
return pos
|
|
|
|
}
|
|
|
|
|
2021-04-16 22:39:19 -04:00
|
|
|
@SuppressLint("RestrictedApi")
|
2021-03-28 16:13:59 -04:00
|
|
|
fun createPopupMenu(onItemClick: (Int) -> Unit): PopupMenu {
|
2021-03-27 16:28:49 -04:00
|
|
|
val popup = PopupMenu(context, this, Gravity.END, R.attr.actionOverflowMenuStyle, 0)
|
|
|
|
entries.forEachIndexed { index, entry ->
|
|
|
|
popup.menu.add(0, index, 0, entry)
|
|
|
|
}
|
2021-04-16 22:39:19 -04:00
|
|
|
(popup.menu as? MenuBuilder)?.setOptionalIconsVisible(true)
|
|
|
|
popup.menu.forEach {
|
|
|
|
it.icon = emptyIcon
|
|
|
|
}
|
|
|
|
popup.menu.getItem(selectedPosition)?.let {
|
|
|
|
it.icon = checkmarkIcon
|
|
|
|
}
|
2021-03-28 16:13:59 -04:00
|
|
|
popup.setOnMenuItemClickListener { menuItem ->
|
|
|
|
val pos = menuClicked(menuItem)
|
|
|
|
onItemClick(pos)
|
|
|
|
true
|
|
|
|
}
|
2021-03-27 16:28:49 -04:00
|
|
|
return popup
|
|
|
|
}
|
|
|
|
}
|