Skip to content

Commit

Permalink
feat: Rework PID list window
Browse files Browse the repository at this point in the history
  • Loading branch information
tzebrowski committed Aug 28, 2023
1 parent 8a16396 commit 8aff3a3
Show file tree
Hide file tree
Showing 17 changed files with 336 additions and 252 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import org.obd.graphs.preferences.dtc.DiagnosticTroubleCodeListPreferences
import org.obd.graphs.preferences.dtc.DiagnosticTroubleCodePreferenceDialog
import org.obd.graphs.preferences.metadata.VehicleMetadataListPreferences
import org.obd.graphs.preferences.metadata.VehicleMetadataPreferenceDialog
import org.obd.graphs.preferences.supported_pids.SupportedPIDsListPreferences
import org.obd.graphs.preferences.supported_pids.SupportedPIDsPreferenceDialog
import org.obd.graphs.preferences.pid.PIDsListPreferences
import org.obd.graphs.preferences.pid.PIDsListPreferenceDialog
import org.obd.graphs.preferences.trips.TripsListPreferences
import org.obd.graphs.preferences.trips.TripsPreferenceDialog
import org.obd.graphs.sendBroadcastEvent
Expand Down Expand Up @@ -50,8 +50,9 @@ class PreferencesFragment : PreferenceFragmentCompat() {
VehicleMetadataPreferenceDialog().show(parentFragmentManager, null)
}

is SupportedPIDsListPreferences -> {
SupportedPIDsPreferenceDialog().show(parentFragmentManager, null)
is PIDsListPreferences -> {
PIDsListPreferenceDialog(preference.key, preference.prio)
.show(parentFragmentManager, null)
}

is DiagnosticTroubleCodeListPreferences -> {
Expand Down
28 changes: 15 additions & 13 deletions app/src/main/java/org/obd/graphs/preferences/pid/DisplayString.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,21 @@ internal fun PidDefinition.displayString(): Spanned {

if (!stable){
val startIndexOf = text.indexOf(EXPERIMENTAL_LABEL)
endIndexOf = startIndexOf + EXPERIMENTAL_LABEL.length

setSpan(
RelativeSizeSpan(0.5f), startIndexOf, endIndexOf,
0
)

setSpan(
ForegroundColorSpan(COLOR_CARDINAL),
startIndexOf,
endIndexOf,
0
)
if (startIndexOf > -1) {
endIndexOf = text.length

setSpan(
RelativeSizeSpan(0.5f), startIndexOf, endIndexOf,
0
)

setSpan(
ForegroundColorSpan(COLOR_CARDINAL),
startIndexOf,
endIndexOf,
0
)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.obd.graphs.preferences.supported_pids
package org.obd.graphs.preferences.pid

import android.content.Context
import android.util.AttributeSet
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.obd.graphs.preferences.supported_pids
package org.obd.graphs.preferences.pid

import android.content.Context
import android.util.AttributeSet
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package org.obd.graphs.preferences.pid

import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.Window
import android.widget.Button
import androidx.fragment.app.DialogFragment
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import org.obd.graphs.R
import org.obd.graphs.bl.datalogger.dataLogger
import org.obd.graphs.bl.datalogger.vehicleCapabilitiesManager
import org.obd.graphs.preferences.Prefs
import org.obd.graphs.preferences.getStringSet
import org.obd.graphs.preferences.updateStringSet
import org.obd.metrics.pid.PIDsGroup
import org.obd.metrics.pid.PidDefinition
import java.util.*

private const val FILTER_BY_ECU_SUPPORTED_PIDS_PREF = "pref.pids.registry.filter_pids_ecu_supported"
private const val FILTER_BY_STABLE_PIDS_PREF = "pref.pids.registry.filter_pids_stable"


data class PidDefinitionWrapper(val source: PidDefinition, var checked: Boolean = false)


class PIDsListPreferenceDialog(private val key: String, private val priority: String) : DialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
dialog?.let {
it.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
it.window?.requestFeature(Window.FEATURE_NO_TITLE)
}
super.onViewCreated(view, savedInstanceState)
}


override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {

val root = inflater.inflate(R.layout.dialog_pids_list, container, false)

when (priority) {
"low" -> findPidDefinitionByPriority { pidDefinition -> pidDefinition.priority > 0 }
"high" -> findPidDefinitionByPriority { pidDefinition -> pidDefinition.priority == 0 }
else -> mutableListOf()
}.let {
val pref = Prefs.getStringSet(key).map { s -> s.toLong() }
it.forEach { p ->
if (pref.contains(p.source.id)) {
p.checked = true
}
}

val adapter = PIDsViewAdapter(context, it)
val recyclerView: RecyclerView = root.findViewById(R.id.recycler_view)
recyclerView.layoutManager = GridLayoutManager(context, 1)
recyclerView.adapter = adapter
}


root.findViewById<Button>(R.id.pid_list_close_window).apply {
setOnClickListener {
dialog?.dismiss()
}
}

root.findViewById<Button>(R.id.pid_list_save).apply {
setOnClickListener {
val pidList = getSelectedPIDs(root)
Log.i("PIDsListPreferenceDialog", "Key=$key, selected PIDs=$pidList")
Prefs.updateStringSet(key, pidList)
dialog?.dismiss()
}
}

return root
}

private fun getSelectedPIDs(root: View): List<String> =
(root.findViewById<RecyclerView>(R.id.recycler_view).adapter as PIDsViewAdapter).data
.filter { it.checked }
.map { it.source.id.toString() }.toList()


private fun findPidDefinitionByPriority(predicate: (PidDefinition) -> Boolean): MutableList<PidDefinitionWrapper> {
val entriesValues: MutableList<PidDefinitionWrapper> =
LinkedList()

val ecuSupportedPIDs = vehicleCapabilitiesManager.getCapabilities()
val ecuSupportedPIDsEnabled = Prefs.getBoolean(FILTER_BY_ECU_SUPPORTED_PIDS_PREF, false)
val stablePIDsEnabled = Prefs.getBoolean(FILTER_BY_STABLE_PIDS_PREF, false)

getPidList()
.asSequence()
.filter { p -> p.group == PIDsGroup.LIVEDATA }
.filter { p -> if (!stablePIDsEnabled) p.stable!! else true }
.filter { p -> predicate.invoke(p) }
.filter { p ->
if (ecuSupportedPIDs.size > 0 &&
!ecuSupportedPIDsEnabled && p.mode == "01"
)
ecuSupportedPIDs.contains(p.pid.lowercase()) else true
}
.sortedBy { p -> p.displayString().toString() }
.toList()
.forEach { p ->

entriesValues.add(PidDefinitionWrapper(p))
}

return entriesValues
}

private fun getPidList() = dataLogger.getPidDefinitionRegistry().findAll()
}
Original file line number Diff line number Diff line change
@@ -1,107 +1,23 @@
package org.obd.graphs.preferences.pid

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.util.AttributeSet
import androidx.preference.MultiSelectListPreference
import org.obd.graphs.bl.datalogger.WORKFLOW_RELOAD_EVENT
import org.obd.graphs.bl.datalogger.dataLogger
import org.obd.graphs.bl.datalogger.vehicleCapabilitiesManager
import org.obd.graphs.preferences.Prefs
import org.obd.metrics.pid.PIDsGroup
import org.obd.metrics.pid.PidDefinition
import java.util.*

private const val FILTER_BY_ECU_SUPPORTED_PIDS_PREF = "pref.pids.registry.filter_pids_ecu_supported"
private const val FILTER_BY_STABLE_PIDS_PREF = "pref.pids.registry.filter_pids_stable"
import androidx.preference.DialogPreference

class PIDsListPreferences(
context: Context?,
attrs: AttributeSet?
): MultiSelectListPreference(context, attrs) {

private val priority = getPriority(attrs)
private val broadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent) {
if (intent.action === WORKFLOW_RELOAD_EVENT) {
initialize()
}
}
}

init {
initialize()
}
private val attrs: AttributeSet?
) : DialogPreference(context, attrs) {

override fun onDetached() {
super.onDetached()
context?.unregisterReceiver(broadcastReceiver)
}

override fun onAttached() {
super.onAttached()
registerReceiver(context)
}

private fun registerReceiver(context: Context?) {
context?.registerReceiver(
broadcastReceiver,
IntentFilter().apply {
addAction(WORKFLOW_RELOAD_EVENT)
}
)
}
var prio = getPriority()

private fun initialize() {
setDefaultValue(hashSetOf<String>())
when (priority) {
"low" -> findPidDefinitionByPriority { pidDefinition -> pidDefinition.priority > 0 }
"high" -> findPidDefinitionByPriority { pidDefinition -> pidDefinition.priority == 0 }
else -> Pair(mutableListOf(), mutableListOf())
}.let {
entries = it.first.toTypedArray()
entryValues = it.second.toTypedArray()
}
}

private fun findPidDefinitionByPriority(predicate: (PidDefinition) -> Boolean): Pair<MutableList<CharSequence>, MutableList<CharSequence>> {
val entries: MutableList<CharSequence> =
LinkedList()
val entriesValues: MutableList<CharSequence> =
LinkedList()

val ecuSupportedPIDs = vehicleCapabilitiesManager.getCapabilities()
val ecuSupportedPIDsEnabled = Prefs.getBoolean(FILTER_BY_ECU_SUPPORTED_PIDS_PREF,false)
val stablePIDsEnabled = Prefs.getBoolean(FILTER_BY_STABLE_PIDS_PREF, false)

getPidList()
.asSequence()
.filter { p -> p.group == PIDsGroup.LIVEDATA}
.filter { p -> if (!stablePIDsEnabled) p.stable!! else true }
.filter { p -> predicate.invoke(p) }
.filter { p -> if (ecuSupportedPIDs.size > 0 &&
!ecuSupportedPIDsEnabled && p.mode == "01")
ecuSupportedPIDs.contains(p.pid.lowercase()) else true }
.sortedBy { p -> p.displayString() .toString()}
.toList()
.forEach { p ->
entries.add(p.displayString())
entriesValues.add(p.id.toString())
}

return Pair(entries, entriesValues)
}

private fun getPidList() = dataLogger.getPidDefinitionRegistry().findAll()

private fun getPriority(attrs: AttributeSet?): String = if (attrs == null) {
private fun getPriority(): String = if (attrs == null) {
""
} else {
val priority: String? = (0 until attrs.attributeCount)
.filter { index -> attrs.getAttributeName(index) == "priority" }
.map { index -> attrs.getAttributeValue(index) }.firstOrNull()
priority ?: ""
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package org.obd.graphs.preferences.pid


import android.content.Context
import android.graphics.Color
import android.graphics.Typeface
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.CheckBox
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import org.obd.graphs.R
import org.obd.graphs.ui.common.COLOR_DYNAMIC_SELECTOR_SPORT
import org.obd.graphs.ui.common.COLOR_PHILIPPINE_GREEN
import org.obd.graphs.ui.common.setText


class PIDsViewAdapter internal constructor(
context: Context?,
var data: MutableList<PidDefinitionWrapper>
) : RecyclerView.Adapter<PIDsViewAdapter.ViewHolder>() {

private val mInflater: LayoutInflater = LayoutInflater.from(context)

override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): ViewHolder {
return ViewHolder(mInflater.inflate(R.layout.item_pids, parent, false))
}

override fun onBindViewHolder(
holder: ViewHolder,
position: Int
) {
data.elementAt(position).run {
holder.mode.setText(source.resourceFile, COLOR_PHILIPPINE_GREEN, Typeface.NORMAL, 0.7f)
holder.name.setText(source.description, Color.GRAY, Typeface.NORMAL, 1f)
if (source.stable) {
holder.status.setText("Yes", Color.GRAY, Typeface.NORMAL, 0.8f)
} else {
holder.status.setText("No", COLOR_DYNAMIC_SELECTOR_SPORT, Typeface.NORMAL, 0.8f)
}

holder.selected.isChecked = checked
holder.selected.setOnCheckedChangeListener { buttonView, isChecked ->
if (buttonView.isShown) {
checked = isChecked
}
}
if (source.alertLowerThreshold != null || source.alertUpperThreshold != null){
var text = ""
if (source.alertLowerThreshold != null){
text += " x<" + source.alertLowerThreshold
}

if (source.alertUpperThreshold != null){
text += " x>" + source.alertUpperThreshold
}

holder.alert.setText(text, Color.GRAY, Typeface.NORMAL, 0.6f)
} else {
holder.alert.setText("", Color.GRAY, Typeface.NORMAL, 0.6f)
}
}
}

override fun getItemCount(): Int {
return data.size
}

inner class ViewHolder internal constructor(itemView: View) : RecyclerView.ViewHolder(itemView) {
val mode: TextView = itemView.findViewById(R.id.pid_file)
val name: TextView = itemView.findViewById(R.id.pid_name)
val status: TextView = itemView.findViewById(R.id.pid_status)
val selected: CheckBox = itemView.findViewById(R.id.pid_selected)
val alert: TextView = itemView.findViewById(R.id.pid_alert)
}
}
Loading

0 comments on commit 8aff3a3

Please sign in to comment.