Skip to content

Commit

Permalink
Maintenance: replace output with recycler
Browse files Browse the repository at this point in the history
  • Loading branch information
robbi5 committed Jul 3, 2023
1 parent d787aec commit 3c248ef
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 59 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package eu.pretix.pretixprint.ui

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import eu.pretix.pretixprint.R
import eu.pretix.pretixprint.util.DirectedHexdumpByteArrayHolder
import eu.pretix.pretixprint.util.DirectedHexdumpCollection

class HexdumpAdapter:
ListAdapter<DirectedHexdumpByteArrayHolder, HexdumpAdapter.HexdumpViewHolder>(HexdumpDiffCallback) {

class HexdumpViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val tvDirection: TextView = itemView.findViewById(R.id.tvDirection)
private val tvHex: TextView = itemView.findViewById(R.id.tvHex)
private val tvAscii: TextView = itemView.findViewById(R.id.tvAscii)
private var currentHexdump: DirectedHexdumpByteArrayHolder? = null


fun bind(item: DirectedHexdumpByteArrayHolder) {
currentHexdump = item

tvDirection.text = item.direction.toString()
tvHex.text = item.toHex()
tvAscii.text = item.toAscii()
}
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HexdumpViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_maintenance_row, parent, false)
return HexdumpViewHolder(view)
}

override fun onBindViewHolder(holder: HexdumpViewHolder, position: Int) {
holder.bind(getItem(position))
}
}

object HexdumpDiffCallback : DiffUtil.ItemCallback<DirectedHexdumpByteArrayHolder>() {
override fun areItemsTheSame(oldItem: DirectedHexdumpByteArrayHolder, newItem: DirectedHexdumpByteArrayHolder): Boolean {
return oldItem == newItem
}

override fun areContentsTheSame(oldItem: DirectedHexdumpByteArrayHolder, newItem: DirectedHexdumpByteArrayHolder): Boolean {
return oldItem.same(newItem)
}
}

class AdapterBoundDirectedHexdumpCollection(maxSize: Int = 16, val listAdapter: HexdumpAdapter): DirectedHexdumpCollection(maxSize) {
init {
listAdapter.submitList(collection)
}

fun pushBytesAndNotify(dir: DirectedHexdumpByteArrayHolder.Direction, ba: ByteArray, forceNew: Boolean = false) {
var fN = forceNew
ba.forEach {
pushByteAndNotify(dir, it, fN)
fN = false
}
}

fun pushByteAndNotify(dir: DirectedHexdumpByteArrayHolder.Direction, b: Byte, forceNew: Boolean = false) {
var new = false
if (collection.isEmpty() || forceNew) {
collection.add(DirectedHexdumpByteArrayHolder(dir, maxSize))
new = true
}
if (collection.last().direction != dir) {
collection.add(DirectedHexdumpByteArrayHolder(dir, maxSize))
new = true
}
if (collection.last().isFull()) {
collection.add(DirectedHexdumpByteArrayHolder(dir, maxSize))
new = true
}
collection.last().push(b)
if (new) {
listAdapter.notifyItemInserted(collection.size - 1)
} else {
listAdapter.notifyItemChanged(collection.size - 1)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import androidx.preference.PreferenceManager
import eu.pretix.pretixprint.R
import eu.pretix.pretixprint.connections.*
import eu.pretix.pretixprint.databinding.FragmentMaintenanceBinding
import eu.pretix.pretixprint.util.DirectedHexdumpCollection
import eu.pretix.pretixprint.util.DirectedHexdumpByteArrayHolder
import kotlinx.coroutines.*
import java.io.DataInputStream
import java.io.IOException
Expand All @@ -32,7 +32,8 @@ class MaintenanceFragment : Fragment(R.layout.fragment_maintenance) {
private lateinit var connection: ConnectionType
private var streamHolder: StreamHolder? = null
private var responseListener: Job? = null
private var hexdump = DirectedHexdumpCollection(8)
private val hexdumpAdapter = HexdumpAdapter()
private var hexdump = AdapterBoundDirectedHexdumpCollection(16, hexdumpAdapter)
private var sendNewline = true

override fun onCreate(savedInstanceState: Bundle?) {
Expand Down Expand Up @@ -116,6 +117,8 @@ class MaintenanceFragment : Fragment(R.layout.fragment_maintenance) {
isEnabled = false
}

binding.rvOutput.adapter = hexdumpAdapter

lifecycleScope.launch {
try {
withContext(Dispatchers.IO) {
Expand All @@ -137,8 +140,7 @@ class MaintenanceFragment : Fragment(R.layout.fragment_maintenance) {
try {
val byte = dis.readByte()
withContext(Dispatchers.Main) {
hexdump.pushByte(DirectedHexdumpCollection.Direction.IN, byte)
binding.tvOutput.text = hexdump.toString()
hexdump.pushByteAndNotify(DirectedHexdumpByteArrayHolder.Direction.IN, byte)
}
} catch (e: IOException) {
if (!isActive) break // got canceled
Expand Down Expand Up @@ -178,7 +180,7 @@ class MaintenanceFragment : Fragment(R.layout.fragment_maintenance) {
}
}
}
hexdump.pushBytes(DirectedHexdumpCollection.Direction.OUT, ba, true)
hexdump.pushBytesAndNotify(DirectedHexdumpByteArrayHolder.Direction.OUT, ba, true)
}

override fun onStop() {
Expand Down
66 changes: 31 additions & 35 deletions pretixprint/app/src/main/java/eu/pretix/pretixprint/util/Hexdump.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package eu.pretix.pretixprint.util


class HexdumpByteArrayHolder(val maxSize: Int = 16) {
open class HexdumpByteArrayHolder(private val maxSize: Int = 16) {
private val bytes: ByteArray = ByteArray(maxSize)
private var elements = 0

Expand All @@ -13,6 +13,10 @@ class HexdumpByteArrayHolder(val maxSize: Int = 16) {
return elements == maxSize
}

fun same(other: HexdumpByteArrayHolder?): Boolean {
return other != null && elements == other.elements && bytes.contentEquals(other.bytes)
}

fun push(b: Byte) {
if (elements >= maxSize) throw IndexOutOfBoundsException("full")
bytes[elements++] = b
Expand All @@ -38,63 +42,55 @@ class HexdumpByteArrayHolder(val maxSize: Int = 16) {
}
}

class HexdumpCollection(val maxSize: Int = 16) {
private val collection = mutableListOf<HexdumpByteArrayHolder>()
class DirectedHexdumpByteArrayHolder(val direction: Direction, _maxSize: Int = 16):
HexdumpByteArrayHolder(_maxSize) {

fun pushBytes(ba: ByteArray, forceNew: Boolean = false) {
var fN = forceNew
ba.forEach {
pushByte(it, fN)
fN = false
enum class Direction {
IN, OUT;
override fun toString(): String = when(this) {
IN -> ""
OUT -> ""
}
}

fun pushByte(b: Byte, forceNew: Boolean = false) {
if (collection.isEmpty() || forceNew) {
collection.add(HexdumpByteArrayHolder(maxSize))
}
if (collection.last().isFull()) {
collection.add(HexdumpByteArrayHolder(maxSize))
}
collection.last().push(b)
fun same(other: DirectedHexdumpByteArrayHolder?): Boolean {
return other != null && direction == other.direction && super.same(other)
}

override fun toString(): String {
return collection.joinToString("\n") { it.toString() }
return "${direction} ${toHex()} | ${toAscii()}"
}
}

class DirectedHexdumpCollection(val maxSize: Int = 16) {
enum class Direction {
IN, OUT;
override fun toString(): String = when(this) {
IN -> ""
OUT -> ""
}
}
private val collection = mutableListOf<Pair<Direction, HexdumpCollection>>()
open class DirectedHexdumpCollection(val maxSize: Int = 16) {
protected val collection = mutableListOf<DirectedHexdumpByteArrayHolder>()

fun pushBytes(dir: Direction, ba: ByteArray, forceNew: Boolean = false) {
fun pushBytes(dir: DirectedHexdumpByteArrayHolder.Direction, ba: ByteArray, forceNew: Boolean = false) {
var fN = forceNew
ba.forEach {
pushByte(dir, it, fN)
fN = false
}
}

fun pushByte(dir: Direction, b: Byte, forceNew: Boolean = false) {
open fun pushByte(dir: DirectedHexdumpByteArrayHolder.Direction, b: Byte, forceNew: Boolean = false) {
if (collection.isEmpty() || forceNew) {
collection.add(Pair(dir, HexdumpCollection(maxSize)))
collection.add(DirectedHexdumpByteArrayHolder(dir, maxSize))
}
if (collection.last().direction != dir) {
collection.add(DirectedHexdumpByteArrayHolder(dir, maxSize))
}
if (collection.last().first != dir) {
collection.add(Pair(dir, HexdumpCollection(maxSize)))
if (collection.last().isFull()) {
collection.add(DirectedHexdumpByteArrayHolder(dir, maxSize))
}
collection.last().second.pushByte(b)
collection.last().push(b)
}

override fun toString(): String {
return collection.joinToString("\n") {
"${it.first} ${it.second.toString().replace("\n", "\n ")}"
}
return collection.joinToString("\n")
}

fun toList(): List<DirectedHexdumpByteArrayHolder> {
return collection.toList()
}
}
26 changes: 7 additions & 19 deletions pretixprint/app/src/main/res/layout/fragment_maintenance.xml
Original file line number Diff line number Diff line change
Expand Up @@ -86,25 +86,13 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/maintain_heading_log"
android:textAppearance="@style/TextAppearance.Material3.BodySmall" />
/>

<ScrollView
android:layout_width="wrap_content"
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvOutput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="200dp">

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">

<TextView
android:id="@+id/tvOutput"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minEms="68"
android:minLines="10"
android:typeface="monospace" />
</LinearLayout>
</ScrollView>
android:paddingBottom="16dp"
app:layoutManager="LinearLayoutManager"
app:stackFromEnd="true" />
</LinearLayout>
46 changes: 46 additions & 0 deletions pretixprint/app/src/main/res/layout/item_maintenance_row.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools">

<TextView
android:id="@+id/tvDirection"
android:layout_width="16dp"
android:layout_height="wrap_content"
android:layout_weight="0"
android:typeface="monospace"
tools:text="->" />

<TextView
android:id="@+id/tvHex"
android:ems="48"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="2"
android:typeface="monospace"
tools:text="00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f"/>

<LinearLayout
android:id="@+id/divider"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="0"
android:gravity="start|center_vertical"
android:paddingHorizontal="3dp"
android:orientation="horizontal">
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="?android:attr/listDivider" />
</LinearLayout>

<TextView
android:id="@+id/tvAscii"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="16"
android:layout_weight="2"
android:typeface="monospace"
tools:text="................" />
</LinearLayout>

0 comments on commit 3c248ef

Please sign in to comment.