Added Stat activity, helpers and cleanup

This commit is contained in:
soraefir
2024-02-09 00:12:01 +01:00
parent f9285d0f31
commit ca5465bc75
22 changed files with 229 additions and 107 deletions

View File

@@ -6,35 +6,24 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import net.helcel.beendroid.R
import net.helcel.beendroid.activity.fragment.AboutFragment
import net.helcel.beendroid.activity.fragment.LicenseFragment
import net.helcel.beendroid.activity.fragment.SettingsFragment
import net.helcel.beendroid.countries.Visited
import net.helcel.beendroid.countries.World
import net.helcel.beendroid.helper.colorPrimary
import net.helcel.beendroid.helper.createActionBar
import net.helcel.beendroid.helper.visited
class EditActivity : AppCompatActivity() {
private lateinit var list : RecyclerView
private lateinit var visited : Visited
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_edit)
// Create action bar
supportActionBar?.setBackgroundDrawable(colorPrimary(this))
supportActionBar?.title = getString(R.string.action_edit)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
visited = Visited(this)
visited.load()
createActionBar(this, getString(R.string.action_edit))
list = findViewById(R.id.list)
list.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false)
list.adapter = FoldingListAdapter(this, World.WWW.children, visited) { }
list.adapter = FoldingListAdapter(this, World.WWW.children, visited!!)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {

View File

@@ -1,10 +1,7 @@
package net.helcel.beendroid.activity
import android.content.Context
import android.graphics.Color
import android.graphics.Typeface
import android.graphics.drawable.ColorDrawable
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -15,16 +12,17 @@ import com.google.android.material.checkbox.MaterialCheckBox
import net.helcel.beendroid.R
import net.helcel.beendroid.countries.GeoLoc
import net.helcel.beendroid.countries.Visited
import net.helcel.beendroid.helper.colorBackground
import net.helcel.beendroid.helper.colorPanelBackground
import java.util.*
class FoldingListAdapter(
private val ctx: Context, l: List<GeoLoc>,
private val visited: Visited,
private val parentLambda: () -> Unit,
) : RecyclerView.Adapter<FoldingListAdapter.FoldingListViewHolder>() {
private var cg : MutableMap<GeoLoc,Boolean> = l.sortedBy { it.fullName }.fold(LinkedHashMap<GeoLoc,Boolean>()) { acc, e ->
private val cg : MutableMap<GeoLoc,Boolean> = l.sortedBy { it.fullName }.fold(LinkedHashMap<GeoLoc,Boolean>()) { acc, e ->
acc[e] = false
acc
}
@@ -38,8 +36,8 @@ class FoldingListAdapter(
override fun onBindViewHolder(holder: FoldingListViewHolder, position: Int) {
val el = cg.toList()[position]
holder.bind(el) { parentLambda() }
holder.bind(el)
holder.addListeners( {
if (!el.first.isEnd) {
cg[el.first] = !el.second
@@ -48,7 +46,6 @@ class FoldingListAdapter(
!el.first.isEnd
}, {
visited.setVisited(el.first, it)
parentLambda()
})
}
@@ -66,47 +63,32 @@ class FoldingListAdapter(
private val list: RecyclerView = itemView.findViewById(R.id.list_list)
init {
list.layoutManager = LinearLayoutManager(ctx, RecyclerView.VERTICAL, false)
list.setItemAnimator(null) //TODO: Fix slow recycler expansion
//list.setHasFixedSize(true)
}
fun bind(el: Pair<GeoLoc, Boolean>, parentLambda: () -> Unit) {
fun bind(el: Pair<GeoLoc, Boolean>) {
subItemView.visibility = if (el.second) View.VISIBLE else View.GONE
textView.text = el.first.fullName
if (el.first.children.isEmpty()) {
val colorBackgroundTyped = TypedValue()
ctx.theme.resolveAttribute(
android.R.attr.colorBackground,
colorBackgroundTyped,
true
)
textView.backgroundTintList = null
textView.background = ColorDrawable(colorBackgroundTyped.data)
textView.background = colorBackground(ctx)
textView.isActivated = false
}else {
textView.setTypeface(null, Typeface.BOLD)
progressView.text = "${(el.first.children.map { visited.visited(it) }.count { it })}/${el.first.children.size}"
progressView.text = ctx.getString(R.string.rate,(el.first.children.map { visited.getVisited(it) }.count { it }),el.first.children.size)
val colorGrayTyped = TypedValue()
ctx.theme.resolveAttribute(
android.R.attr.panelColorBackground,
colorGrayTyped,
true
)
val color = Color.valueOf(colorGrayTyped.data)
textView.setBackgroundColor(
Color.valueOf(
color.red(),
color.green(),
color.blue(),
0.5f
).toArgb()
)
list.adapter = FoldingListAdapter(ctx, el.first.children, visited, parentLambda)
textView.background = colorPanelBackground(ctx)
textView.background.alpha = 128
list.adapter = FoldingListAdapter(ctx, el.first.children, visited)
textView.parent.parent.requestChildFocus(textView, textView)
}
checkBox.checkedState =
if (visited.visited(el.first)) MaterialCheckBox.STATE_CHECKED
else if (el.first.children.any { visited.visited(it) }) MaterialCheckBox.STATE_INDETERMINATE
if (visited.getVisited(el.first)) MaterialCheckBox.STATE_CHECKED
else if (el.first.children.any { visited.getVisited(it) }) MaterialCheckBox.STATE_INDETERMINATE
else MaterialCheckBox.STATE_UNCHECKED
}

View File

@@ -2,9 +2,9 @@ package net.helcel.beendroid.activity
import android.content.Intent
import android.content.SharedPreferences
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.PictureDrawable
import android.os.Bundle
import android.util.Log
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
@@ -31,7 +31,6 @@ class MainActivity : AppCompatActivity() {
private lateinit var photoView : PhotoView
private lateinit var visited : Visited
private lateinit var psvg : PSVGWrapper
private lateinit var css : CSSWrapper
@@ -63,11 +62,10 @@ class MainActivity : AppCompatActivity() {
true
}
R.id.action_stats -> {
// TODO: Write stats activity
startActivity(Intent(this@MainActivity, StatActivity::class.java))
true
}
R.id.action_settings -> {
// Open settings
startActivity(Intent(this@MainActivity, SettingsActivity::class.java))
true
}
@@ -80,11 +78,12 @@ class MainActivity : AppCompatActivity() {
})
// Restore visited countries
visited = Visited(this)
visited = Visited(this).load()
// Wrap lists of countries
psvg = PSVGWrapper(this)
css = CSSWrapper(visited)
css = CSSWrapper(visited!!)
// Populate map from list of countries
setContentView(R.layout.activity_main)
@@ -97,12 +96,10 @@ class MainActivity : AppCompatActivity() {
}
private fun refreshMap() {
visited.load()
val opt : RenderOptions = RenderOptions.create()
CoroutineScope(Dispatchers.IO).launch {
opt.css(css.get())
}
photoView.setImageLevel(1)
photoView.setImageDrawable(PictureDrawable(psvg.get().renderToPicture(opt)))
}

View File

@@ -14,13 +14,8 @@ class SettingsActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Bind activity to XML layout with fragment view
setContentView(R.layout.activity_settings)
// Create action bar
supportActionBar?.setBackgroundDrawable(colorPrimary(this))
supportActionBar?.title = getString(R.string.action_settings)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
createActionBar(this, getString(R.string.action_settings))
// Populate activity with settings fragment
supportFragmentManager.beginTransaction()

View File

@@ -0,0 +1,127 @@
package net.helcel.beendroid.activity
import android.graphics.Color
import android.os.Bundle
import android.util.Log
import android.view.MenuItem
import androidx.appcompat.app.AppCompatActivity
import com.github.mikephil.charting.animation.Easing
import com.github.mikephil.charting.charts.PieChart
import com.github.mikephil.charting.components.Legend
import com.github.mikephil.charting.data.PieData
import com.github.mikephil.charting.data.PieDataSet
import com.github.mikephil.charting.data.PieEntry
import com.github.mikephil.charting.formatter.PercentFormatter
import com.github.mikephil.charting.utils.ColorTemplate
import com.github.mikephil.charting.utils.MPPointF
import net.helcel.beendroid.R
import net.helcel.beendroid.countries.World
import net.helcel.beendroid.helper.createActionBar
import net.helcel.beendroid.helper.visited
class StatActivity : AppCompatActivity() {
private lateinit var chart : PieChart
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_stat)
createActionBar(this, getString(R.string.action_stat))
chart = findViewById(R.id.chart)
chart.setUsePercentValues(true)
chart.description.isEnabled = false
chart.setExtraOffsets(5F, 10F, 5F, 5F)
chart.setDragDecelerationFrictionCoef(0.95f)
chart.centerText = "Country Area"
chart.isDrawHoleEnabled = true
chart.setTransparentCircleColor(Color.TRANSPARENT)
chart.setHoleColor(Color.TRANSPARENT)
chart.setCenterTextColor(Color.WHITE)
chart.setTransparentCircleAlpha(0)
chart.holeRadius = 40F
chart.transparentCircleRadius = 45F
chart.setDrawCenterText(true)
chart.setRotationAngle(0F)
chart.isRotationEnabled = true
chart.isHighlightPerTapEnabled = false
// chart.spin(2000, 0, 360);
val l: Legend = chart.legend
l.verticalAlignment = Legend.LegendVerticalAlignment.TOP
l.horizontalAlignment = Legend.LegendHorizontalAlignment.RIGHT
l.orientation = Legend.LegendOrientation.VERTICAL
l.setDrawInside(false)
l.xEntrySpace = 7F
l.yEntrySpace = 0F
l.yOffset = 0F
chart.setEntryLabelColor(Color.WHITE)
chart.setEntryLabelTextSize(12f)
bind()
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
finish()
return super.onOptionsItemSelected(item)
}
private fun bind() {
val entries = ArrayList<PieEntry>()
val VIS_continents = World.WWW.children.groupBy { visited!!.getVisited(it) }.map { Pair(it.key,it.value.map { c-> c.area }.fold(0){acc,i-> acc+i}) }
val VIS_country = World.WWW.children.map { it.children }.flatten().groupBy { visited!!.getVisited(it) }.map { Pair(it.key,it.value.map { c-> c.area }.fold(0){acc,i-> acc+i}) }
val vis = VIS_country
Log.d("VIS",vis.toString())
val max = vis.fold(0,) {acc, i -> acc+i.second}
vis.forEach {
entries.add(PieEntry(it.second.toFloat().div(max.toFloat()),it.first.toString()))
}
val dataSet = PieDataSet(entries, "GG1")
dataSet.valueTextColor = Color.BLACK
dataSet.sliceSpace = 3f
dataSet.iconsOffset = MPPointF(0f, 40f)
dataSet.selectionShift = 5f
// add a lot of colors
val colors = ArrayList<Int>()
for (c in ColorTemplate.VORDIPLOM_COLORS) colors.add(c)
for (c in ColorTemplate.JOYFUL_COLORS) colors.add(c)
for (c in ColorTemplate.COLORFUL_COLORS) colors.add(c)
for (c in ColorTemplate.LIBERTY_COLORS) colors.add(c)
for (c in ColorTemplate.PASTEL_COLORS) colors.add(c)
colors.add(ColorTemplate.getHoloBlue())
dataSet.colors = colors
val data = PieData(dataSet)
data.setDrawValues(false)
data.setValueFormatter(PercentFormatter())
data.setValueTextSize(11f)
data.setValueTextColor(Color.BLACK)
chart.setEntryLabelColor(Color.BLACK)
chart.data = data
chart.highlightValues(null)
chart.invalidate()
}
}

View File

@@ -11,8 +11,7 @@ class Visited(ctx: Context) {
private val pref = ctx.getSharedPreferences("Visited", Context.MODE_PRIVATE)
private val editor = pref.edit()
fun load() {
fun load(): Visited {
Group.entries.forEach {
locs[it] = pref.getBoolean(it.code, false)
}
@@ -23,9 +22,10 @@ class Visited(ctx: Context) {
locs[it] = pref.getBoolean(it.code, false)
}
editor.apply()
return this
}
fun setVisited(key: GeoLoc, b: Boolean){
fun setVisited(key: GeoLoc, b: Boolean) {
locs[key] = b
CoroutineScope(Dispatchers.Main).launch {
editor.putBoolean(key.code, b)
@@ -33,7 +33,7 @@ class Visited(ctx: Context) {
}
}
fun visited(key: GeoLoc): Boolean {
fun getVisited(key: GeoLoc): Boolean {
return locs.getOrDefault(key,false)
}

View File

@@ -0,0 +1,7 @@
package net.helcel.beendroid.helper
import net.helcel.beendroid.countries.Visited
var visited : Visited? = null
//= Visited(this)

View File

@@ -3,11 +3,28 @@ package net.helcel.beendroid.helper
import android.content.Context
import android.graphics.drawable.ColorDrawable
import android.util.TypedValue
import androidx.appcompat.app.AppCompatActivity
fun colorPrimary(ctx : Context): ColorDrawable {
fun colorWrapper(ctx : Context, res: Int): ColorDrawable {
val colorPrimaryTyped = TypedValue()
ctx.theme.resolveAttribute(android.R.attr.colorPrimary, colorPrimaryTyped, true)
ctx.theme.resolveAttribute(res, colorPrimaryTyped, true)
return ColorDrawable(colorPrimaryTyped.data)
}
fun colorPrimary(ctx : Context): ColorDrawable {
return colorWrapper(ctx, android.R.attr.colorPrimary)
}
fun colorBackground(ctx : Context): ColorDrawable {
return colorWrapper(ctx, android.R.attr.colorBackground)
}
fun colorPanelBackground(ctx: Context): ColorDrawable {
return colorWrapper(ctx, android.R.attr.panelColorBackground)
}
fun createActionBar(ctx: AppCompatActivity, title: String) {
ctx.supportActionBar?.setBackgroundDrawable(colorPrimary(ctx))
ctx.supportActionBar?.title = title
ctx.supportActionBar?.setDisplayHomeAsUpEnabled(true)
}

View File

@@ -9,13 +9,13 @@ class CSSWrapper(private val visited: Visited) {
fun get() : String {
return listOf(World.WWW.children
.filter { visited.visited(it)}
.filter { visited.getVisited(it)}
.map { ".${it.code}{fill:$colorPrimary;}"}
.fold(""){acc, s-> acc + s},
World.WWW.children
.filter { !visited.visited(it) }
.filter { !visited.getVisited(it) }
.map { cg -> cg.children
.filter { visited.visited(it) }
.filter { visited.getVisited(it) }
.map { ".${it.code}{fill:$colorPrimary;}"}
.fold(""){acc, s-> acc + s}
}.fold(""){acc,s->acc+s},

View File

@@ -1,30 +1,24 @@
package net.helcel.beendroid.svg
import android.content.Context
import android.util.TypedValue
import android.util.Log
import com.caverock.androidsvg.SVG
import net.helcel.beendroid.R
import net.helcel.beendroid.countries.Country
import net.helcel.beendroid.countries.GeoLoc
import net.helcel.beendroid.countries.World
import net.helcel.beendroid.helper.colorWrapper
@OptIn(ExperimentalStdlibApi::class)
class PSVGWrapper(ctx: Context) {
private val cm = HashMap<GeoLoc, PSVGLoader>()
private var fm = ""
private val colorForeground: String
private val colorBackground: String
private val colorForeground: String = colorWrapper(ctx, R.color.darkgray).color.toHexString().substring(2)
private val colorBackground: String = colorWrapper(ctx, R.color.black).color.toHexString().substring(2)
init {
val colorSecondaryTyped = TypedValue()
ctx.theme.resolveAttribute(android.R.attr.panelColorBackground, colorSecondaryTyped, true)
colorForeground = "\"#${Integer.toHexString(colorSecondaryTyped.data).subSequence(2, 8)}\""
val colorBackgroundTyped = TypedValue()
ctx.theme.resolveAttribute(android.R.attr.colorBackground, colorBackgroundTyped, true)
colorBackground = "\"#${Integer.toHexString(colorBackgroundTyped.data).subSequence(2, 8)}\""
Country.entries.forEach {
cm[it] = PSVGLoader(ctx, it, Level.ZERO).load()
}
@@ -45,7 +39,7 @@ class PSVGWrapper(ctx: Context) {
}
fun get(): SVG {
return SVG.getFromString("<svg id=\"map\" xmlns=\"http://www.w3.org/2000/svg\" width=\"1200\" height=\"1200\" x=\"0\" y=\"0\" fill=${colorForeground} stroke=${colorBackground} stroke-width=\"0.25px\">$fm</svg>")
return SVG.getFromString("<svg id=\"map\" xmlns=\"http://www.w3.org/2000/svg\" width=\"1200\" height=\"1200\" x=\"0\" y=\"0\" fill=\"#$colorForeground\" stroke=\"#$colorBackground\" stroke-width=\"0.25px\">$fm</svg>")
}
}