/** * 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 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 ignitionIcon: 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 */ if (unit.getIgnition()) { statusIcon.setColorFilter( ContextCompat.getColor(context, R.color.colorOnline) ) statusIcon.contentDescription = context.getString(R.string.unit_ignition_on) } else { statusIcon.setColorFilter( ContextCompat.getColor(context, R.color.colorOffline) ) statusIcon.contentDescription = context.getString(R.string.unit_ignition_off) } /* 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) } } } } } }