Various refactoring to fix text edition bugs

hh
Laurent 6 years ago
parent 1c9932cd32
commit b1fa2d9020
  1. 4
      app/src/main/java/net/pokeranalytics/android/model/handhistory/ComputedAction.kt
  2. 6
      app/src/main/java/net/pokeranalytics/android/model/handhistory/HHBuilder.kt
  3. 1
      app/src/main/java/net/pokeranalytics/android/ui/adapter/FeedHandHistoryRowRepresentableAdapter.kt
  4. 1
      app/src/main/java/net/pokeranalytics/android/ui/adapter/FeedSessionRowRepresentableAdapter.kt
  5. 1
      app/src/main/java/net/pokeranalytics/android/ui/adapter/FeedTransactionRowRepresentableAdapter.kt
  6. 212
      app/src/main/java/net/pokeranalytics/android/ui/adapter/HandHistoryAdapter.kt
  7. 26
      app/src/main/java/net/pokeranalytics/android/ui/adapter/RecyclerAdapter.kt
  8. 18
      app/src/main/java/net/pokeranalytics/android/ui/adapter/RowRepresentableAdapter.kt
  9. 6
      app/src/main/java/net/pokeranalytics/android/ui/fragment/HandHistoryFragment.kt
  10. 303
      app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt
  11. 4
      app/src/main/java/net/pokeranalytics/android/ui/view/handhistory/StreetCardHeader.kt
  12. 2
      app/src/main/java/net/pokeranalytics/android/ui/view/holder/RowHandHistoryViewHolder.kt
  13. 170
      app/src/main/java/net/pokeranalytics/android/ui/view/holder/RowViewHolder.kt
  14. 8
      app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/CustomizableRowRepresentable.kt

@ -1,8 +1,8 @@
package net.pokeranalytics.android.model.handhistory
import net.pokeranalytics.android.model.realm.handhistory.Action
import net.pokeranalytics.android.ui.adapter.HandRowType
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType
import timber.log.Timber
interface HandHistoryRow : RowRepresentable {
@ -42,7 +42,7 @@ class ComputedAction(var action: Action,
}
}
override val viewType: Int = RowViewType.ROW_HAND_ACTION.ordinal
override val viewType: Int = HandRowType.ACTION.ordinal
override fun keyboardForCompletion() : HHKeyboard? {
Timber.d("index = ${action.index} / type = ${this.action.type} / amount = ${this.action.amount}")

@ -4,8 +4,8 @@ import net.pokeranalytics.android.R
import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.realm.handhistory.Action
import net.pokeranalytics.android.model.realm.handhistory.HandHistory
import net.pokeranalytics.android.ui.adapter.HandRowType
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.ui.view.handhistory.StreetCardHeader
import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable
import timber.log.Timber
@ -286,7 +286,7 @@ class HHBuilder {
fun rowRepresentables() : List<RowRepresentable> {
val rows: MutableList<RowRepresentable> = mutableListOf()
rows.add(CustomizableRowRepresentable(customViewType = RowViewType.HEADER_TITLE, resId = R.string.settings))
rows.add(CustomizableRowRepresentable(customViewType = HandRowType.HEADER, resId = R.string.settings))
var potSize = 0.0
Street.values().forEach { street ->
@ -295,7 +295,7 @@ class HHBuilder {
if (actions.isNotEmpty()) {
// Name of the street + pot size if not preflop
rows.add(CustomizableRowRepresentable(customViewType = RowViewType.HEADER_TITLE, resId = street.resId))
rows.add(CustomizableRowRepresentable(customViewType = HandRowType.HEADER, resId = street.resId))
// Cards if not preflop
if (street.totalBoardCards > 0) {

@ -9,7 +9,6 @@ import io.realm.RealmResults
import kotlinx.android.synthetic.main.row_hand_history.view.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.realm.handhistory.HandHistory
import net.pokeranalytics.android.ui.view.BindableHolder
import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.util.NULL_TEXT
import net.pokeranalytics.android.util.extensions.getMonthAndYear

@ -15,7 +15,6 @@ import kotlinx.android.synthetic.main.row_feed_session.view.*
import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.realm.Filter
import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.ui.view.BindableHolder
import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.util.extensions.getMonthAndYear
import timber.log.Timber

@ -9,7 +9,6 @@ import io.realm.RealmResults
import kotlinx.android.synthetic.main.row_transaction.view.*
import net.pokeranalytics.android.R
import net.pokeranalytics.android.model.realm.Transaction
import net.pokeranalytics.android.ui.view.BindableHolder
import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.util.NULL_TEXT
import net.pokeranalytics.android.util.extensions.getMonthAndYear

@ -0,0 +1,212 @@
package net.pokeranalytics.android.ui.adapter
import android.text.Editable
import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.EditText
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import net.pokeranalytics.android.R
import net.pokeranalytics.android.exceptions.PAIllegalStateException
import net.pokeranalytics.android.model.handhistory.ComputedAction
import net.pokeranalytics.android.model.handhistory.HHKeyboard
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.holder.RowViewHolder
import net.pokeranalytics.android.ui.view.rowrepresentable.ViewIdentifier
import net.pokeranalytics.android.util.extensions.formatted
import timber.log.Timber
enum class HandRowType(var layoutRes: Int) : ViewIdentifier {
HEADER(R.layout.row_header_title),
ACTION(R.layout.row_hand_action),
STREET(R.layout.row_hand_cards);
override val identifier: Int
get() { return this.ordinal }
}
class HandHistoryAdapter(
override var dataSource: RowRepresentableDataSource,
override var delegate: RowRepresentableDelegate? = null) :
RecyclerView.Adapter<RecyclerView.ViewHolder>(), RecyclerAdapter {
override fun getItemViewType(position: Int): Int {
return this.dataSource.viewTypeForPosition(position)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val rowType: HandRowType = HandRowType.values()[viewType]
val layout = LayoutInflater.from(parent.context).inflate(rowType.layoutRes, parent, false)
return when (rowType) {
HandRowType.HEADER -> RowViewHolder(layout)
HandRowType.ACTION -> RowHandAction(layout)
HandRowType.STREET -> RowHandStreet(layout)
}
}
override fun getItemCount(): Int {
return this.dataSource.numberOfRows()
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
this.dataSource.rowRepresentableForPosition(position)?.let { rowRepresentable ->
(holder as BindableHolder).onBind(position, rowRepresentable, this)
}
}
/**
* Refresh the row in the adapter
*/
fun refreshRow(row: RowRepresentable) {
val rows = this.dataSource.adapterRows()
val index = rows?.indexOf(row) ?: -1
if (index >= 0) {
notifyItemChanged(index)
}
}
/**
* Update UI
*/
fun updateRows(diffResult: DiffUtil.DiffResult) {
diffResult.dispatchUpdatesTo(this)
}
inner class TextListener : TextWatcher {
var position: Int = 0
override fun afterTextChanged(s: Editable?) {}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
val row = dataSource.rowRepresentableForPosition(position)
?: throw PAIllegalStateException("Row Representable not found at index: $position")
delegate?.onRowValueChanged(s.toString(), row)
}
}
/**
* Display a hand action
*/
inner class RowHandAction(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder {
private var listener = TextListener()
init {
itemView.findViewById<EditText>(R.id.actionEditText)?.let { actionEditText ->
actionEditText.setOnFocusChangeListener { v, hasFocus ->
Timber.d("focus change = $hasFocus at position = $position")
actionEditText.setBackgroundColor(color(hasFocus))
}
}
itemView.findViewById<EditText>(R.id.amountEditText)?.let { amountEditText ->
amountEditText.setOnFocusChangeListener { v, hasFocus ->
Timber.d("focus change = $hasFocus at position = $position")
amountEditText.setBackgroundColor(color(hasFocus))
}
amountEditText.addTextChangedListener(this.listener)
}
}
private fun color(isFocused: Boolean) : Int {
val color = if (isFocused) R.color.green_light else R.color.kaki_medium
return itemView.context.getColor(color)
}
override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) {
this.listener.position = position
val computedAction = row as ComputedAction
// Position
itemView.findViewById<Button>(R.id.positionButton)?.let { button ->
button.text = computedAction.position.value
}
// Action
itemView.findViewById<EditText>(R.id.actionEditText)?.let { actionEditText ->
val tag = HHKeyboard.ACTION.ordinal
actionEditText.isFocusable = computedAction.actionTypeCanBeEdited
val selected = adapter.dataSource.isSelected(position, row, tag)
// Timber.d("Action at $position is selected: $selected")
actionEditText.setBackgroundColor(color(selected))
computedAction.action.type?.resId?.let {
actionEditText.setText(it)
} ?: run {
actionEditText.text = null
}
if (selected) actionEditText.requestFocus() else actionEditText.clearFocus()
// actionEditText.setOnClickListener {
//
// Timber.d("OnClickListener at $position")
// val isSelected = adapter.dataSource.isSelected(position, row, tag)
// if (!isSelected && computedAction.actionTypeCanBeEdited) {
// actionEditText.requestFocus()
// adapter.delegate?.onRowSelected(position, row, tag)
// actionEditText.setBackgroundColor(color(true))
// } else {
// adapter.delegate?.onRowDeselected(position, row)
// actionEditText.setBackgroundColor(color(false))
// }
// }
// actionEditText.setOnFocusChangeListener { v, hasFocus ->
// Timber.d("focus change = $hasFocus at position = $position")
// actionEditText.setBackgroundColor(color(hasFocus))
// }
}
// Amount
itemView.findViewById<EditText>(R.id.amountEditText)?.let { amountEditText ->
val tag = HHKeyboard.AMOUNT.ordinal
val selected = adapter.dataSource.isSelected(position, row, tag)
Timber.d("Amount at $position is selected: $selected")
amountEditText.setBackgroundColor(color(selected))
amountEditText.setText(computedAction.action.amount?.formatted())
if (selected) amountEditText.requestFocus() else amountEditText.clearFocus()
// amountEditText.setOnTouchListener { v, event ->
// Timber.d("OnClickListener at $position")
// adapter.delegate?.onRowSelected(position, row, tag)
// amountEditText.setBackgroundColor(color(true))
// return@setOnTouchListener true
// }
// amountEditText.setOnFocusChangeListener { v, hasFocus ->
// Timber.d("focus change = $hasFocus at position = $position")
// amountEditText.setBackgroundColor(color(hasFocus))
// }
// amountEditText.addTextChangedListener {
// adapter.delegate?.onRowValueChanged(it.toString(), row)
// }
}
}
}
/**
* Display a hand street
*/
inner class RowHandStreet(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder {
override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) {
}
}
}

@ -0,0 +1,26 @@
package net.pokeranalytics.android.ui.adapter
import android.view.View
import net.pokeranalytics.android.ui.view.RowRepresentable
interface RecyclerAdapter {
var dataSource: RowRepresentableDataSource
var delegate: RowRepresentableDelegate?
}
interface RowRepresentableDelegate {
fun onRowSelected(position: Int, row: RowRepresentable, tag: Int = 0) {}
fun onRowDeselected(position: Int, row: RowRepresentable) {}
fun onRowValueChanged(value: Any?, row: RowRepresentable) {}
fun onRowDeleted(row: RowRepresentable) {}
fun onRowLongClick(itemView: View, row: RowRepresentable, position: Int) {}
}
/**
* An interface used to factor the configuration of RecyclerView.ViewHolder
*/
interface BindableHolder {
fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) {
}
}

@ -4,29 +4,19 @@ import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import net.pokeranalytics.android.ui.view.BindableHolder
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.RowViewType
interface RowRepresentableDelegate {
fun onRowSelected(position: Int, row: RowRepresentable, tag: Int = 0) {}
fun onRowDeselected(position: Int, row: RowRepresentable) {}
fun onRowValueChanged(value: Any?, row: RowRepresentable) {}
fun onRowDeleted(row: RowRepresentable) {}
fun onRowLongClick(itemView: View, row: RowRepresentable, position: Int) {}
}
/**
* An adapter capable of displaying a list of RowRepresentables
* @param dataSource the datasource providing rows
* @param delegate the delegate, notified of UI actions
*/
class RowRepresentableAdapter(
var dataSource: RowRepresentableDataSource,
var delegate: RowRepresentableDelegate? = null
override var dataSource: RowRepresentableDataSource,
override var delegate: RowRepresentableDelegate? = null
) :
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
RecyclerView.Adapter<RecyclerView.ViewHolder>(), RecyclerAdapter {
override fun getItemViewType(position: Int): Int {
return this.dataSource.viewTypeForPosition(position)
@ -43,7 +33,7 @@ class RowRepresentableAdapter(
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
this.dataSource.rowRepresentableForPosition(position)?.let {
(holder as BindableHolder).bind(position, it, this)
(holder as BindableHolder).onBind(position, it, this)
}
}

@ -14,7 +14,7 @@ import net.pokeranalytics.android.model.handhistory.*
import net.pokeranalytics.android.model.realm.handhistory.Action
import net.pokeranalytics.android.model.realm.handhistory.Card
import net.pokeranalytics.android.model.realm.handhistory.HandHistory
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
import net.pokeranalytics.android.ui.adapter.HandHistoryAdapter
import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate
import net.pokeranalytics.android.ui.fragment.components.RealmFragment
@ -29,7 +29,7 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDataSource, RowRepr
private lateinit var model: HandHistoryViewModel
private lateinit var handHistoryAdapter: RowRepresentableAdapter
private lateinit var handHistoryAdapter: HandHistoryAdapter
private var rows: List<RowRepresentable> = listOf()
@ -85,7 +85,7 @@ class HandHistoryFragment : RealmFragment(), RowRepresentableDataSource, RowRepr
setDisplayHomeAsUpEnabled(true)
val viewManager = LinearLayoutManager(requireContext())
handHistoryAdapter = RowRepresentableAdapter(this, this)
handHistoryAdapter = HandHistoryAdapter(this, this)
recyclerView.apply {
setHasFixedSize(true)

@ -3,17 +3,12 @@ package net.pokeranalytics.android.ui.view
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.EditText
import android.widget.FrameLayout
import androidx.appcompat.widget.AppCompatImageView
import androidx.appcompat.widget.AppCompatTextView
import androidx.appcompat.widget.SwitchCompat
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.core.widget.ContentLoadingProgressBar
import androidx.core.widget.addTextChangedListener
import androidx.recyclerview.widget.RecyclerView
import com.github.mikephil.charting.charts.BarChart
import com.github.mikephil.charting.charts.LineChart
@ -28,38 +23,28 @@ import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.calculus.bankroll.BankrollReportManager
import net.pokeranalytics.android.model.TableSize
import net.pokeranalytics.android.model.extensions.getFormattedGameType
import net.pokeranalytics.android.model.handhistory.ComputedAction
import net.pokeranalytics.android.model.handhistory.HHKeyboard
import net.pokeranalytics.android.model.realm.CustomField
import net.pokeranalytics.android.model.realm.Player
import net.pokeranalytics.android.model.realm.Session
import net.pokeranalytics.android.model.realm.Transaction
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter
import net.pokeranalytics.android.ui.adapter.BindableHolder
import net.pokeranalytics.android.ui.adapter.RecyclerAdapter
import net.pokeranalytics.android.ui.extensions.ChipGroupExtension
import net.pokeranalytics.android.ui.extensions.addCircleRipple
import net.pokeranalytics.android.ui.extensions.px
import net.pokeranalytics.android.ui.extensions.setTextFormat
import net.pokeranalytics.android.ui.fragment.BankrollRowRepresentable
import net.pokeranalytics.android.ui.graph.AxisFormatting
import net.pokeranalytics.android.ui.graph.setStyle
import net.pokeranalytics.android.ui.view.holder.RowViewHolder
import net.pokeranalytics.android.ui.view.rowrepresentable.*
import net.pokeranalytics.android.util.extensions.formatted
import net.pokeranalytics.android.util.extensions.longDate
import timber.log.Timber
/**
* An interface used to factor the configuration of RecyclerView.ViewHolder
*/
interface BindableHolder {
fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) {
}
}
/**
* Row View Type for recyclerView's adapter
* [layoutRes] is the resource layout to display
*/
enum class RowViewType(private var layoutRes: Int) {
enum class RowViewType(private var layoutRes: Int) : ViewIdentifier {
// Header
HEADER_TITLE(R.layout.row_header_title),
@ -101,12 +86,17 @@ enum class RowViewType(private var layoutRes: Int) {
LIST(R.layout.row_list),
ROW_PLAYER(R.layout.row_player),
ROW_PLAYER_IMAGE(R.layout.row_player_image),
ROW_HAND_ACTION(R.layout.row_hand_action),
ROW_HAND_STREET(R.layout.row_hand_cards),
// ROW_HAND_ACTION(R.layout.row_hand_action),
// ROW_HAND_STREET(R.layout.row_hand_cards),
// Separator
SEPARATOR(R.layout.row_separator);
override val identifier: Int
get() {
return this.ordinal
}
/**
* View holder
*/
@ -152,8 +142,8 @@ enum class RowViewType(private var layoutRes: Int) {
// Hand History
// ROW_HAND_HISTORY -> RowHandHistoryViewHolder(layout)
ROW_HAND_ACTION -> RowHandAction(layout)
ROW_HAND_STREET -> RowHandStreet(layout)
// ROW_HAND_ACTION -> RowHandAction(layout)
// ROW_HAND_STREET -> RowHandStreet(layout)
// Separator
SEPARATOR -> SeparatorViewHolder(layout)
@ -162,161 +152,13 @@ enum class RowViewType(private var layoutRes: Int) {
}
}
/**
* Display a generic row (titleResId, value, container)
*/
@SuppressWarnings("ResourceType")
inner class RowViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder {
override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) {
when (row) {
is BankrollRowRepresentable -> {
// Title
itemView.findViewById<AppCompatTextView>(R.id.title)?.let {
it.text = row.localizedTitle(itemView.context)
}
Timber.d("RowViewHolder > bind > reportForBankroll")
BankrollReportManager.reportForBankroll(row.bankrollId) { report ->
itemView.findViewById<AppCompatTextView>(R.id.title)?.let {
it.text = row.localizedTitle(itemView.context)
}
val computedStat =
ComputedStat(Stat.NET_RESULT, report.total, currency = report.currency)
itemView.findViewById<AppCompatTextView?>(R.id.value)
?.setTextFormat(computedStat.format(), itemView.context)
}
val listener = View.OnClickListener {
adapter.delegate?.onRowSelected(position, row)
}
itemView.findViewById<View?>(R.id.container)?.setOnClickListener(listener)
}
is CustomizableRowRepresentable -> {
// Customizable Row
// Title
itemView.findViewById<AppCompatTextView>(R.id.title)?.let {
it.text = row.localizedTitle(itemView.context)
}
// Value
itemView.findViewById<AppCompatTextView?>(R.id.value)?.let {
if (row.computedStat != null) {
val format = row.computedStat!!.format()
it.setTextFormat(format, itemView.context)
} else if (row.value != null) {
it.text = row.value
}
}
// Listener
row.isSelectable?.let { isSelectable ->
if (isSelectable) {
val listener = View.OnClickListener {
adapter.delegate?.onRowSelected(position, row)
}
itemView.findViewById<View?>(R.id.container)
?.setOnClickListener(listener)
}
}
}
else -> {
// Classic row
// Title
itemView.findViewById<AppCompatTextView?>(R.id.title)?.let {
if (row.resId != null) {
it.text = row.localizedTitle(itemView.context)
} else {
it.text = row.getDisplayName(itemView.context)
}
}
// Value
itemView.findViewById<AppCompatTextView?>(R.id.value)?.let {
it.text = adapter.dataSource.stringForRow(row, itemView.context)
}
// Icon
itemView.findViewById<AppCompatImageView?>(R.id.icon)?.let { imageView ->
imageView.setImageDrawable(null)
row.imageRes?.let { imageRes ->
imageView.setImageResource(imageRes)
}
}
// Action
itemView.findViewById<AppCompatImageView>(R.id.action)?.let { imageView ->
imageView.setImageDrawable(null)
row.imageRes?.let { imageRes ->
imageView.visibility = View.VISIBLE
imageView.setImageResource(imageRes)
}
row.imageTint?.let { color ->
imageView.setColorFilter(
ContextCompat.getColor(
imageView.context,
color
)
)
}
if (row.imageClickable == true) {
imageView.addCircleRipple()
imageView.setOnClickListener {
adapter.delegate?.onRowSelected(position, row, 1)
}
} else {
imageView.setBackgroundResource(0)
}
}
// Listener
val listener = View.OnClickListener {
itemView.findViewById<SwitchCompat?>(R.id.switchView)?.let {
if (adapter.dataSource.isEnabled(row, 0)) {
it.isChecked = !it.isChecked
}
} ?: run {
adapter.delegate?.onRowSelected(position, row)
}
}
itemView.findViewById<View?>(R.id.container)?.setOnClickListener(listener)
}
}
// Switch
itemView.findViewById<SwitchCompat?>(R.id.switchView)?.let {
it.isChecked = adapter.dataSource.boolForRow(row)
it.isEnabled = adapter.dataSource.isEnabled(row, 0)
it.setOnCheckedChangeListener { _, isChecked ->
adapter.delegate?.onRowValueChanged(isChecked, row)
}
}
// Selected row
itemView.findViewById<AppCompatImageView?>(R.id.check)?.let {
it.isSelected = adapter.dataSource.isSelected(position, row, 0)
}
}
}
/**
* Display a follow us row
*/
inner class RowFollowUsViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
BindableHolder {
override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) {
override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) {
itemView.findViewById<AppCompatImageView?>(R.id.icon1)?.setOnClickListener {
adapter.delegate?.onRowSelected(0, row)
}
@ -337,7 +179,7 @@ enum class RowViewType(private var layoutRes: Int) {
*/
inner class StatsTitleValueViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
BindableHolder {
override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) {
override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) {
// Title
itemView.findViewById<AppCompatTextView?>(R.id.title)?.text =
@ -368,7 +210,7 @@ enum class RowViewType(private var layoutRes: Int) {
*/
inner class StatsDoubleViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
BindableHolder {
override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) {
override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) {
if (row is StatDoubleRow) {
@ -446,7 +288,7 @@ enum class RowViewType(private var layoutRes: Int) {
}
override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) {
override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) {
when (row) {
is BankrollGraphRow -> {
@ -478,7 +320,7 @@ enum class RowViewType(private var layoutRes: Int) {
inner class LegendDefaultViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
BindableHolder {
override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) {
override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) {
if (row is BankrollRowRepresentable) {
@ -517,7 +359,7 @@ enum class RowViewType(private var layoutRes: Int) {
*/
inner class ListViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
BindableHolder {
override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) {
override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) {
if (row is CustomFieldRow) {
@ -568,7 +410,7 @@ enum class RowViewType(private var layoutRes: Int) {
*/
inner class RowButtonViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
BindableHolder {
override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) {
override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) {
itemView.findViewById<AppCompatTextView>(R.id.title).text =
row.localizedTitle(itemView.context)
itemView.findViewById<AppCompatTextView>(R.id.title).isVisible =
@ -587,7 +429,7 @@ enum class RowViewType(private var layoutRes: Int) {
*/
inner class RowSessionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
BindableHolder {
override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) {
override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) {
itemView.sessionRow.setData(row as Session)
val listener = View.OnClickListener {
adapter.delegate?.onRowSelected(position, row)
@ -601,7 +443,7 @@ enum class RowViewType(private var layoutRes: Int) {
*/
inner class RowTransactionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
BindableHolder {
override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) {
override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) {
itemView.transactionRow.setData(row as Transaction)
val listener = View.OnClickListener {
adapter.delegate?.onRowSelected(position, row)
@ -615,7 +457,7 @@ enum class RowViewType(private var layoutRes: Int) {
*/
inner class RowTop10ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
BindableHolder {
override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) {
override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) {
if (row is Session) {
@ -683,7 +525,7 @@ enum class RowViewType(private var layoutRes: Int) {
*/
inner class RowPlayerViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
BindableHolder {
override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) {
override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) {
if (row is Player) {
itemView.findViewById<PlayerImageView?>(R.id.playerImage)?.let { playerImageView ->
@ -710,7 +552,7 @@ enum class RowViewType(private var layoutRes: Int) {
*/
inner class RowPlayerImageViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
BindableHolder {
override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) {
override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) {
itemView.findViewById<PlayerImageView?>(R.id.playerImageView)?.let { playerImageView ->
val listener = View.OnClickListener {
adapter.delegate?.onRowSelected(position, PlayerRow.IMAGE)
@ -721,106 +563,13 @@ enum class RowViewType(private var layoutRes: Int) {
}
}
/**
* Display a hand action
*/
inner class RowHandAction(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder {
private fun color(isFocused: Boolean) : Int {
val color = if (isFocused) R.color.green_light else R.color.kaki_medium
return itemView.context.getColor(color)
}
override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) {
val computedAction = row as ComputedAction
// Position
itemView.findViewById<Button>(R.id.positionButton)?.let { button ->
button.text = computedAction.position.value
}
// Action
itemView.findViewById<EditText>(R.id.actionEditText)?.let { actionEditText ->
val tag = HHKeyboard.ACTION.ordinal
actionEditText.isFocusable = computedAction.actionTypeCanBeEdited
val selected = adapter.dataSource.isSelected(position, row, tag)
// Timber.d("Action at $position is selected: $selected")
actionEditText.setBackgroundColor(color(selected))
computedAction.action.type?.resId?.let {
actionEditText.setText(it)
} ?: run {
actionEditText.text = null
}
if (selected) actionEditText.requestFocus() else actionEditText.clearFocus()
actionEditText.setOnClickListener {
Timber.d("OnClickListener at $position")
val isSelected = adapter.dataSource.isSelected(position, row, tag)
if (!isSelected && computedAction.actionTypeCanBeEdited) {
actionEditText.requestFocus()
adapter.delegate?.onRowSelected(position, row, tag)
actionEditText.setBackgroundColor(color(true))
} else {
adapter.delegate?.onRowDeselected(position, row)
actionEditText.setBackgroundColor(color(false))
}
}
actionEditText.setOnFocusChangeListener { v, hasFocus ->
Timber.d("focus change = $hasFocus at position = $position")
actionEditText.setBackgroundColor(color(hasFocus))
}
}
// Amount
itemView.findViewById<EditText>(R.id.amountEditText)?.let { amountEditText ->
val tag = HHKeyboard.AMOUNT.ordinal
val selected = adapter.dataSource.isSelected(position, row, tag)
Timber.d("Amount at $position is selected: $selected")
amountEditText.setBackgroundColor(color(selected))
amountEditText.setText(computedAction.action.amount?.formatted())
if (selected) amountEditText.requestFocus() else amountEditText.clearFocus()
amountEditText.setOnTouchListener { v, event ->
Timber.d("OnClickListener at $position")
adapter.delegate?.onRowSelected(position, row, tag)
amountEditText.setBackgroundColor(color(true))
return@setOnTouchListener true
}
amountEditText.setOnFocusChangeListener { v, hasFocus ->
Timber.d("focus change = $hasFocus at position = $position")
amountEditText.setBackgroundColor(color(hasFocus))
}
amountEditText.addTextChangedListener {
adapter.delegate?.onRowValueChanged(it.toString(), row)
}
}
}
}
/**
* Display a hand street
*/
inner class RowHandStreet(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder {
override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) {
}
}
/**
* Display a separator
*/
inner class SeparatorViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
BindableHolder {
override fun bind(position: Int, row: RowRepresentable, adapter: RowRepresentableAdapter) {
override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) {
}
}

@ -4,11 +4,11 @@ import net.pokeranalytics.android.model.handhistory.HHKeyboard
import net.pokeranalytics.android.model.handhistory.HandHistoryRow
import net.pokeranalytics.android.model.handhistory.Street
import net.pokeranalytics.android.model.realm.handhistory.Card
import net.pokeranalytics.android.ui.view.RowViewType
import net.pokeranalytics.android.ui.adapter.HandRowType
class StreetCardHeader(var street: Street, var cards: List<Card>, var potSize: Double) : HandHistoryRow {
override val viewType: Int = RowViewType.ROW_HAND_STREET.ordinal
override val viewType: Int = HandRowType.STREET.ordinal
override fun keyboardForCompletion(): HHKeyboard? {
return if (cards.size != street.totalBoardCards) {

@ -4,8 +4,8 @@ import android.view.View
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.row_hand_history.view.*
import net.pokeranalytics.android.model.realm.handhistory.HandHistory
import net.pokeranalytics.android.ui.adapter.BindableHolder
import net.pokeranalytics.android.ui.adapter.FeedHandHistoryRowRepresentableAdapter
import net.pokeranalytics.android.ui.view.BindableHolder
class RowHandHistoryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
BindableHolder {

@ -0,0 +1,170 @@
package net.pokeranalytics.android.ui.view.holder
import android.view.View
import androidx.appcompat.widget.AppCompatImageView
import androidx.appcompat.widget.AppCompatTextView
import androidx.appcompat.widget.SwitchCompat
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import net.pokeranalytics.android.R
import net.pokeranalytics.android.calculus.ComputedStat
import net.pokeranalytics.android.calculus.Stat
import net.pokeranalytics.android.calculus.bankroll.BankrollReportManager
import net.pokeranalytics.android.ui.adapter.BindableHolder
import net.pokeranalytics.android.ui.adapter.RecyclerAdapter
import net.pokeranalytics.android.ui.extensions.addCircleRipple
import net.pokeranalytics.android.ui.extensions.setTextFormat
import net.pokeranalytics.android.ui.fragment.BankrollRowRepresentable
import net.pokeranalytics.android.ui.view.RowRepresentable
import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable
import timber.log.Timber
/**
* Display a generic row (titleResId, value, container)
*/
@SuppressWarnings("ResourceType")
class RowViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder {
override fun onBind(position: Int, row: RowRepresentable, adapter: RecyclerAdapter) {
when (row) {
is BankrollRowRepresentable -> {
// Title
itemView.findViewById<AppCompatTextView>(R.id.title)?.let {
it.text = row.localizedTitle(itemView.context)
}
Timber.d("RowViewHolder > bind > reportForBankroll")
BankrollReportManager.reportForBankroll(row.bankrollId) { report ->
itemView.findViewById<AppCompatTextView>(R.id.title)?.let {
it.text = row.localizedTitle(itemView.context)
}
val computedStat =
ComputedStat(Stat.NET_RESULT, report.total, currency = report.currency)
itemView.findViewById<AppCompatTextView?>(R.id.value)
?.setTextFormat(computedStat.format(), itemView.context)
}
val listener = View.OnClickListener {
adapter.delegate?.onRowSelected(position, row)
}
itemView.findViewById<View?>(R.id.container)?.setOnClickListener(listener)
}
is CustomizableRowRepresentable -> {
// Customizable Row
// Title
itemView.findViewById<AppCompatTextView>(R.id.title)?.let {
it.text = row.localizedTitle(itemView.context)
}
// Value
itemView.findViewById<AppCompatTextView?>(R.id.value)?.let {
if (row.computedStat != null) {
val format = row.computedStat!!.format()
it.setTextFormat(format, itemView.context)
} else if (row.value != null) {
it.text = row.value
}
}
// Listener
row.isSelectable?.let { isSelectable ->
if (isSelectable) {
val listener = View.OnClickListener {
adapter.delegate?.onRowSelected(position, row)
}
itemView.findViewById<View?>(R.id.container)
?.setOnClickListener(listener)
}
}
}
else -> {
// Classic row
// Title
itemView.findViewById<AppCompatTextView?>(R.id.title)?.let {
if (row.resId != null) {
it.text = row.localizedTitle(itemView.context)
} else {
it.text = row.getDisplayName(itemView.context)
}
}
// Value
itemView.findViewById<AppCompatTextView?>(R.id.value)?.let {
it.text = adapter.dataSource.stringForRow(row, itemView.context)
}
// Icon
itemView.findViewById<AppCompatImageView?>(R.id.icon)?.let { imageView ->
imageView.setImageDrawable(null)
row.imageRes?.let { imageRes ->
imageView.setImageResource(imageRes)
}
}
// Action
itemView.findViewById<AppCompatImageView>(R.id.action)?.let { imageView ->
imageView.setImageDrawable(null)
row.imageRes?.let { imageRes ->
imageView.visibility = View.VISIBLE
imageView.setImageResource(imageRes)
}
row.imageTint?.let { color ->
imageView.setColorFilter(
ContextCompat.getColor(
imageView.context,
color
)
)
}
if (row.imageClickable == true) {
imageView.addCircleRipple()
imageView.setOnClickListener {
adapter.delegate?.onRowSelected(position, row, 1)
}
} else {
imageView.setBackgroundResource(0)
}
}
// Listener
val listener = View.OnClickListener {
itemView.findViewById<SwitchCompat?>(R.id.switchView)?.let {
if (adapter.dataSource.isEnabled(row, 0)) {
it.isChecked = !it.isChecked
}
} ?: run {
adapter.delegate?.onRowSelected(position, row)
}
}
itemView.findViewById<View?>(R.id.container)?.setOnClickListener(listener)
}
}
// Switch
itemView.findViewById<SwitchCompat?>(R.id.switchView)?.let {
it.isChecked = adapter.dataSource.boolForRow(row)
it.isEnabled = adapter.dataSource.isEnabled(row, 0)
it.setOnCheckedChangeListener { _, isChecked ->
adapter.delegate?.onRowValueChanged(isChecked, row)
}
}
// Selected row
itemView.findViewById<AppCompatImageView?>(R.id.check)?.let {
it.isSelected = adapter.dataSource.isSelected(position, row, 0)
}
}
}

@ -16,11 +16,15 @@ class BankrollTotalRow(override var bankrollId: String?, var name: String) : Ban
}
interface ViewIdentifier {
val identifier: Int
}
/**
* A class to display a titleResId (and a value) as a Row Representable object
*/
class CustomizableRowRepresentable(
var customViewType: RowViewType? = RowViewType.HEADER_TITLE,
var customViewType: ViewIdentifier? = RowViewType.HEADER_TITLE,
override var resId: Int? = null,
var title: String? = null,
var value: String? = null,
@ -39,7 +43,7 @@ class CustomizableRowRepresentable(
return "LOCALISATION NOT FOUND"
}
override val viewType: Int = customViewType?.ordinal ?: RowViewType.HEADER_TITLE.ordinal
override val viewType: Int = customViewType?.identifier ?: RowViewType.HEADER_TITLE.ordinal
// override var id: String = ""
}

Loading…
Cancel
Save