forked from github/szkolny
[UI] Add event type colors to type dropdown.
This commit is contained in:
parent
db598af28a
commit
297867cbf3
@ -4,8 +4,6 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik.ui.dialogs.event
|
package pl.szczodrzynski.edziennik.ui.dialogs.event
|
||||||
|
|
||||||
import android.graphics.PorterDuff
|
|
||||||
import android.graphics.PorterDuffColorFilter
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
@ -26,7 +24,6 @@ import pl.szczodrzynski.edziennik.data.api.events.ApiTaskErrorEvent
|
|||||||
import pl.szczodrzynski.edziennik.data.api.events.ApiTaskFinishedEvent
|
import pl.szczodrzynski.edziennik.data.api.events.ApiTaskFinishedEvent
|
||||||
import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi
|
import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Event
|
import pl.szczodrzynski.edziennik.data.db.entity.Event
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.EventType
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||||
import pl.szczodrzynski.edziennik.data.db.full.EventFull
|
import pl.szczodrzynski.edziennik.data.db.full.EventFull
|
||||||
@ -35,7 +32,6 @@ import pl.szczodrzynski.edziennik.databinding.DialogEventManualV2Binding
|
|||||||
import pl.szczodrzynski.edziennik.ui.dialogs.sync.RegistrationConfigDialog
|
import pl.szczodrzynski.edziennik.ui.dialogs.sync.RegistrationConfigDialog
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.views.TimeDropdown.Companion.DISPLAY_LESSONS
|
import pl.szczodrzynski.edziennik.ui.modules.views.TimeDropdown.Companion.DISPLAY_LESSONS
|
||||||
import pl.szczodrzynski.edziennik.utils.Anim
|
import pl.szczodrzynski.edziennik.utils.Anim
|
||||||
import pl.szczodrzynski.edziennik.utils.TextInputDropDown
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
@ -323,57 +319,41 @@ class EventManualDialog(
|
|||||||
selectDefault(defaultLesson?.displayTeacherId)
|
selectDefault(defaultLesson?.displayTeacherId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
with (b.typeDropdown) {
|
||||||
|
db = app.db
|
||||||
|
profileId = this@EventManualDialog.profileId
|
||||||
|
loadItems()
|
||||||
|
selectDefault(editingEvent?.type)
|
||||||
|
selectDefault(defaultType)
|
||||||
|
|
||||||
val deferred = async(Dispatchers.Default) {
|
onTypeSelected = {
|
||||||
// get the event type list
|
b.typeColor.background.setTintColor(it.color)
|
||||||
var eventTypes = app.db.eventTypeDao().getAllNow(profileId)
|
customColor = null
|
||||||
|
|
||||||
if (eventTypes.none { it.id in -1L..10L }) {
|
|
||||||
eventTypes = app.db.eventTypeDao().addDefaultTypes(activity, profileId)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
b.typeDropdown.clear()
|
|
||||||
b.typeDropdown += eventTypes.map { TextInputDropDown.Item(it.id, it.name, tag = it) }
|
|
||||||
}
|
|
||||||
deferred.await()
|
|
||||||
|
|
||||||
b.typeDropdown.isEnabled = true
|
|
||||||
|
|
||||||
defaultType?.let {
|
|
||||||
b.typeDropdown.select(it)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
b.typeDropdown.selected?.let { item ->
|
// copy data from event being edited
|
||||||
customColor = (item.tag as EventType).color
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy IDs from event being edited
|
|
||||||
editingEvent?.let {
|
editingEvent?.let {
|
||||||
b.topic.setText(it.topic)
|
b.topic.setText(it.topic)
|
||||||
b.typeDropdown.select(it.type)?.let { item ->
|
if (it.color != -1)
|
||||||
customColor = (item.tag as EventType).color
|
|
||||||
}
|
|
||||||
if (it.color != null && it.color != -1)
|
|
||||||
customColor = it.color
|
customColor = it.color
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b.typeColor.background.setTintColor(
|
||||||
|
customColor
|
||||||
|
?: b.typeDropdown.getSelected()?.color
|
||||||
|
?: Event.COLOR_DEFAULT
|
||||||
|
)
|
||||||
|
|
||||||
// copy IDs from the LessonFull
|
// copy IDs from the LessonFull
|
||||||
defaultLesson?.let {
|
defaultLesson?.let {
|
||||||
b.teamDropdown.select(it.displayTeamId)
|
b.teamDropdown.select(it.displayTeamId)
|
||||||
}
|
}
|
||||||
|
|
||||||
b.typeDropdown.setOnChangeListener {
|
|
||||||
b.typeColor.background.colorFilter = PorterDuffColorFilter((it.tag as EventType).color, PorterDuff.Mode.SRC_ATOP)
|
|
||||||
customColor = null
|
|
||||||
return@setOnChangeListener true
|
|
||||||
}
|
|
||||||
|
|
||||||
(customColor ?: Event.COLOR_DEFAULT).let {
|
|
||||||
b.typeColor.background.colorFilter = PorterDuffColorFilter(it, PorterDuff.Mode.SRC_ATOP)
|
|
||||||
}
|
|
||||||
|
|
||||||
b.typeColor.onClick {
|
b.typeColor.onClick {
|
||||||
val currentColor = (b.typeDropdown.selected?.tag as EventType?)?.color ?: Event.COLOR_DEFAULT
|
val currentColor = customColor
|
||||||
|
?: b.typeDropdown.getSelected()?.color
|
||||||
|
?: Event.COLOR_DEFAULT
|
||||||
val colorPickerDialog = ColorPickerDialog.newBuilder()
|
val colorPickerDialog = ColorPickerDialog.newBuilder()
|
||||||
.setColor(currentColor)
|
.setColor(currentColor)
|
||||||
.create()
|
.create()
|
||||||
@ -381,7 +361,7 @@ class EventManualDialog(
|
|||||||
object : ColorPickerDialogListener {
|
object : ColorPickerDialogListener {
|
||||||
override fun onDialogDismissed(dialogId: Int) {}
|
override fun onDialogDismissed(dialogId: Int) {}
|
||||||
override fun onColorSelected(dialogId: Int, color: Int) {
|
override fun onColorSelected(dialogId: Int, color: Int) {
|
||||||
b.typeColor.background.colorFilter = PorterDuffColorFilter(color, PorterDuff.Mode.SRC_ATOP)
|
b.typeColor.background.setTintColor(color)
|
||||||
customColor = color
|
customColor = color
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -597,7 +577,12 @@ class EventManualDialog(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onSaveListener?.invoke(eventObject.withMetadata(metadataObject))
|
onSaveListener?.invoke(eventObject.withMetadata(metadataObject).also {
|
||||||
|
it.subjectLongName = b.subjectDropdown.selected?.text?.toString()
|
||||||
|
it.teacherName = b.teacherDropdown.selected?.text?.toString()
|
||||||
|
it.teamName = b.teamDropdown.selected?.text?.toString()
|
||||||
|
it.typeName = b.typeDropdown.selected?.text?.toString()
|
||||||
|
})
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
Toast.makeText(activity, R.string.saved, Toast.LENGTH_SHORT).show()
|
Toast.makeText(activity, R.string.saved, Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2021-4-14.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.ui.modules.views
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.ContextWrapper
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import com.mikepenz.iconics.IconicsDrawable
|
||||||
|
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
|
||||||
|
import com.mikepenz.iconics.utils.colorInt
|
||||||
|
import com.mikepenz.iconics.utils.sizeDp
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.AppDb
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.entity.EventType
|
||||||
|
import pl.szczodrzynski.edziennik.utils.TextInputDropDown
|
||||||
|
|
||||||
|
class EventTypeDropdown : TextInputDropDown {
|
||||||
|
constructor(context: Context) : super(context)
|
||||||
|
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
|
||||||
|
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
|
||||||
|
|
||||||
|
private val activity: AppCompatActivity?
|
||||||
|
get() {
|
||||||
|
var context: Context? = context ?: return null
|
||||||
|
if (context is AppCompatActivity) return context
|
||||||
|
while (context is ContextWrapper) {
|
||||||
|
if (context is AppCompatActivity)
|
||||||
|
return context
|
||||||
|
context = context.baseContext
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
lateinit var db: AppDb
|
||||||
|
var profileId: Int = 0
|
||||||
|
var onTypeSelected: ((eventType: EventType) -> Unit)? = null
|
||||||
|
|
||||||
|
override fun create(context: Context) {
|
||||||
|
super.create(context)
|
||||||
|
isEnabled = false
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun loadItems() {
|
||||||
|
val types = withContext(Dispatchers.Default) {
|
||||||
|
val list = mutableListOf<Item>()
|
||||||
|
|
||||||
|
var types = db.eventTypeDao().getAllNow(profileId)
|
||||||
|
|
||||||
|
if (types.none { it.id in -1L..10L }) {
|
||||||
|
types = db.eventTypeDao().addDefaultTypes(context, profileId)
|
||||||
|
}
|
||||||
|
|
||||||
|
list += types.map {
|
||||||
|
Item(it.id, it.name, tag = it, icon = IconicsDrawable(context).apply {
|
||||||
|
icon = CommunityMaterial.Icon.cmd_circle
|
||||||
|
sizeDp = 24
|
||||||
|
colorInt = it.color
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
list
|
||||||
|
}
|
||||||
|
|
||||||
|
clear().append(types)
|
||||||
|
isEnabled = true
|
||||||
|
|
||||||
|
setOnChangeListener {
|
||||||
|
when (it.tag) {
|
||||||
|
is EventType -> {
|
||||||
|
// selected an event type
|
||||||
|
onTypeSelected?.invoke(it.tag)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select an event type by the [typeId].
|
||||||
|
*/
|
||||||
|
fun selectType(typeId: Long) {
|
||||||
|
select(typeId)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select an event type by the [typeId] **if it's not selected yet**.
|
||||||
|
*/
|
||||||
|
fun selectDefault(typeId: Long?) {
|
||||||
|
if (typeId == null || selected != null)
|
||||||
|
return
|
||||||
|
selectType(typeId)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the currently selected event type.
|
||||||
|
* ### Returns:
|
||||||
|
* - null if no valid type is selected
|
||||||
|
* - [EventType] - the selected event type
|
||||||
|
*/
|
||||||
|
fun getSelected(): EventType? {
|
||||||
|
return when (selected?.tag) {
|
||||||
|
is EventType -> selected?.tag as EventType
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -84,6 +84,9 @@ class TeacherDropdown : TextInputDropDown {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select a teacher by the [teacherId].
|
||||||
|
*/
|
||||||
fun selectTeacher(teacherId: Long) {
|
fun selectTeacher(teacherId: Long) {
|
||||||
if (select(teacherId) == null)
|
if (select(teacherId) == null)
|
||||||
select(Item(
|
select(Item(
|
||||||
@ -93,6 +96,9 @@ class TeacherDropdown : TextInputDropDown {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select a teacher by the [teacherId] **if it's not selected yet**.
|
||||||
|
*/
|
||||||
fun selectDefault(teacherId: Long?) {
|
fun selectDefault(teacherId: Long?) {
|
||||||
if (teacherId == null || selected != null)
|
if (teacherId == null || selected != null)
|
||||||
return
|
return
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
package pl.szczodrzynski.edziennik.utils
|
package pl.szczodrzynski.edziennik.utils
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
|
import androidx.appcompat.view.menu.MenuBuilder
|
||||||
|
import androidx.appcompat.view.menu.MenuPopupHelper
|
||||||
import androidx.appcompat.widget.PopupMenu
|
import androidx.appcompat.widget.PopupMenu
|
||||||
import com.google.android.material.textfield.TextInputEditText
|
import com.google.android.material.textfield.TextInputEditText
|
||||||
import com.mikepenz.iconics.IconicsDrawable
|
import com.mikepenz.iconics.IconicsDrawable
|
||||||
@ -33,6 +37,7 @@ open class TextInputDropDown : TextInputEditText {
|
|||||||
setText(selected?.displayText ?: selected?.text)
|
setText(selected?.displayText ?: selected?.text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("RestrictedApi")
|
||||||
open fun create(context: Context) {
|
open fun create(context: Context) {
|
||||||
val drawable = IconicsDrawable(context, CommunityMaterial.Icon.cmd_chevron_down).apply {
|
val drawable = IconicsDrawable(context, CommunityMaterial.Icon.cmd_chevron_down).apply {
|
||||||
colorInt = Themes.getPrimaryTextColor(context)
|
colorInt = Themes.getPrimaryTextColor(context)
|
||||||
@ -58,7 +63,9 @@ open class TextInputDropDown : TextInputEditText {
|
|||||||
val popup = PopupMenu(context, this)
|
val popup = PopupMenu(context, this)
|
||||||
|
|
||||||
items.forEachIndexed { index, item ->
|
items.forEachIndexed { index, item ->
|
||||||
popup.menu.add(0, item.id.toInt(), index, item.text)
|
popup.menu.add(0, item.id.toInt(), index, item.text).also {
|
||||||
|
it.icon = item.icon
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
popup.setOnMenuItemClickListener { menuItem ->
|
popup.setOnMenuItemClickListener { menuItem ->
|
||||||
@ -70,29 +77,46 @@ open class TextInputDropDown : TextInputEditText {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
popup.setOnDismissListener {
|
val helper = MenuPopupHelper(context, popup.menu as MenuBuilder, this)
|
||||||
|
helper.setForceShowIcon(true)
|
||||||
|
helper.setOnDismissListener {
|
||||||
clearFocus()
|
clearFocus()
|
||||||
}
|
}
|
||||||
|
helper.show()
|
||||||
popup.show()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun select(item: Item): Item? {
|
/**
|
||||||
|
* Select an arbitrary [item]. Allows to select an item not present
|
||||||
|
* in the original list.
|
||||||
|
*/
|
||||||
|
fun select(item: Item): Item {
|
||||||
selected = item
|
selected = item
|
||||||
updateText()
|
updateText()
|
||||||
error = null
|
error = null
|
||||||
return item
|
return item
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select an item by its ID. Returns the selected item
|
||||||
|
* if found.
|
||||||
|
*/
|
||||||
fun select(id: Long?): Item? {
|
fun select(id: Long?): Item? {
|
||||||
return items.singleOrNull { it.id == id }?.let { select(it) }
|
return items.singleOrNull { it.id == id }?.let { select(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select an item by its tag. Returns the selected item
|
||||||
|
* if found.
|
||||||
|
*/
|
||||||
fun select(tag: Any?): Item? {
|
fun select(tag: Any?): Item? {
|
||||||
return items.singleOrNull { it.tag == tag }?.let { select(it) }
|
return items.singleOrNull { it.tag == tag }?.let { select(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select an item by its index. Returns the selected item
|
||||||
|
* if the index exists.
|
||||||
|
*/
|
||||||
fun select(index: Int): Item? {
|
fun select(index: Int): Item? {
|
||||||
return items.getOrNull(index)?.let { select(it) }
|
return items.getOrNull(index)?.let { select(it) }
|
||||||
}
|
}
|
||||||
@ -143,5 +167,11 @@ open class TextInputDropDown : TextInputEditText {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Item(val id: Long, val text: CharSequence, val displayText: CharSequence? = null, val tag: Any? = null)
|
class Item(
|
||||||
|
val id: Long,
|
||||||
|
val text: CharSequence,
|
||||||
|
val displayText: CharSequence? = null,
|
||||||
|
val tag: Any? = null,
|
||||||
|
val icon: Drawable? = null
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,7 @@
|
|||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:hint="@string/dialog_event_manual_type">
|
android:hint="@string/dialog_event_manual_type">
|
||||||
|
|
||||||
<pl.szczodrzynski.edziennik.utils.TextInputDropDown
|
<pl.szczodrzynski.edziennik.ui.modules.views.EventTypeDropdown
|
||||||
android:id="@+id/typeDropdown"
|
android:id="@+id/typeDropdown"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
Loading…
Reference in New Issue
Block a user