/** * TrackerMap * Copyright (C) 2021-2022 Iván Ávalos , Henoch Ojeda * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ package mx.trackermap.TrackerMap.android.shared import android.content.Context import android.graphics.Color import android.util.TypedValue import android.view.Gravity import android.view.View import android.widget.Button import android.widget.GridLayout import android.widget.ImageView import android.widget.TextView import androidx.cardview.widget.CardView import androidx.core.content.ContextCompat import com.zerobranch.layout.SwipeLayout import kotlinx.serialization.json.longOrNull import mx.trackermap.TrackerMap.android.R import mx.trackermap.TrackerMap.client.models.UnitInformation import mx.trackermap.TrackerMap.utils.Formatter import mx.trackermap.TrackerMap.utils.SpeedUnit typealias ActionCallback = (unit: UnitInformation, action: UnitRenderData.Action) -> Unit class UnitRenderData { data class UnitRenderViewHolder( val unitName: TextView, val unitIcon: ImageView? = null, val statusIcon: ImageView, val engineStopIcon: ImageView, val gridLayout: GridLayout, val detailsButton: Button? = null, val reportsButton: Button? = null, val commandsButton: Button? = null, val unitCard: CardView? = null, val swipeLayout: SwipeLayout? = null ) enum class Action { CLICK, DETAILS, REPORTS, COMMANDS } companion object { fun render( viewHolder: UnitRenderViewHolder, context: Context, unit: UnitInformation, actionCallback: ActionCallback? ) { viewHolder.apply { val details: MutableList> = mutableListOf() /* Device name */ unitName.text = unit.device.name /* Device icon */ unitIcon?.setImageResource( MarkerTransformations.categoryToResourceId(unit.device.category) ) unitIcon?.contentDescription = context.getString( MarkerTransformations.categoryToStringId(unit.device.category) ) /* Contact */ unit.device.contact?.let { contact -> if (contact.isNotEmpty()) { details.add( Triple( R.drawable.device_contact, contact, context.getString(R.string.unit_driver_name) ) ) } } /* Status icon */ when (unit.getStatus()) { UnitInformation.Status.ONLINE -> { statusIcon.setColorFilter( ContextCompat.getColor(context, R.color.colorOnline) ) } UnitInformation.Status.OFFLINE -> { statusIcon.setColorFilter( ContextCompat.getColor(context, R.color.colorOffline) ) } else -> { statusIcon.setColorFilter(Color.GRAY) } } /* Engine stop */ when(unit.getEngineStop()) { UnitInformation.EngineStop.ON -> { engineStopIcon.visibility = View.VISIBLE engineStopIcon.setImageResource(R.drawable.device_unlocked) engineStopIcon.contentDescription = context.getString(R.string.unit_lock_on) } UnitInformation.EngineStop.OFF -> { engineStopIcon.visibility = View.VISIBLE engineStopIcon.setImageResource(R.drawable.device_locked) engineStopIcon.contentDescription = context.getString(R.string.unit_lock_off) } UnitInformation.EngineStop.UNKNOWN -> { engineStopIcon.visibility = View.GONE } } unit.position?.let { position -> /* Speed */ position.speed?.let { speed -> details.add( Triple( R.drawable.position_speed, Formatter.formatSpeed(speed, SpeedUnit.KMH), context.getString(R.string.unit_speed) ) ) } /* Address */ position.address?.let { address -> details.add( Triple( R.drawable.position_address, address, context.getString(R.string.unit_last_address) ) ) } /* Hourmeter */ unit.getHourmeter()?.let { if (it > 0) { details.add( Triple( R.drawable.position_hourmeter, Formatter.formatHours(it), context.getString(R.string.unit_hourmeter) ) ) } } /* Date time */ position.fixTime?.let { fixTime -> details.add( Triple( R.drawable.position_datetime, Formatter.formatDate(fixTime), context.getString(R.string.unit_last_date) ) ) } } gridLayout.removeAllViewsInLayout() val metrics = context.resources.displayMetrics details.forEachIndexed { i, detail -> /* Property icon */ val imageView = ImageView(gridLayout.context) imageView.setImageResource(detail.first) imageView.contentDescription = detail.third imageView.setColorFilter( ContextCompat.getColor( context, androidx.appcompat.R.color.secondary_text_default_material_light ) ) val imageLayout = GridLayout.LayoutParams() imageLayout.width = GridLayout.LayoutParams.WRAP_CONTENT imageLayout.height = GridLayout.LayoutParams.WRAP_CONTENT imageLayout.marginEnd = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 6f, metrics).toInt() imageLayout.rowSpec = GridLayout.spec(i) imageLayout.columnSpec = GridLayout.spec(0) imageView.layoutParams = imageLayout /* Property text */ val textView = TextView(gridLayout.context) textView.text = detail.second val textLayout = GridLayout.LayoutParams() textLayout.width = 0 textLayout.height = GridLayout.LayoutParams.MATCH_PARENT textLayout.rowSpec = GridLayout.spec(i) textLayout.columnSpec = GridLayout.spec(1, 1, 5f) textView.layoutParams = textLayout gridLayout.addView(imageView) gridLayout.addView(textView) imageLayout.setGravity(Gravity.CENTER) } actionCallback?.let { callback -> unitCard?.setOnClickListener { swipeLayout?.close() callback(unit, Action.CLICK) } detailsButton?.setOnClickListener { swipeLayout?.close() callback(unit, Action.DETAILS) } reportsButton?.setOnClickListener { swipeLayout?.close() callback(unit, Action.REPORTS) } commandsButton?.setOnClickListener { swipeLayout?.close() callback(unit, Action.COMMANDS) } } } } } }