Added Stat activity, helpers and cleanup
This commit is contained in:
@@ -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 {
|
||||
|
@@ -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
|
||||
|
||||
}
|
||||
|
@@ -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)))
|
||||
}
|
||||
|
||||
|
@@ -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()
|
||||
|
127
app/src/main/java/net/helcel/beendroid/activity/StatActivity.kt
Normal file
127
app/src/main/java/net/helcel/beendroid/activity/StatActivity.kt
Normal 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()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@@ -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)
|
||||
}
|
||||
|
||||
|
7
app/src/main/java/net/helcel/beendroid/helper/Data.kt
Normal file
7
app/src/main/java/net/helcel/beendroid/helper/Data.kt
Normal file
@@ -0,0 +1,7 @@
|
||||
package net.helcel.beendroid.helper
|
||||
|
||||
import net.helcel.beendroid.countries.Visited
|
||||
|
||||
|
||||
var visited : Visited? = null
|
||||
//= Visited(this)
|
@@ -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)
|
||||
}
|
@@ -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},
|
||||
|
@@ -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>")
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user