From 44b0cccbd9c2d1a5de4f00408f721085cf7574da Mon Sep 17 00:00:00 2001 From: fgerber Date: Sun, 30 Jul 2023 15:19:02 +0200 Subject: [PATCH 1/4] Perform some layout changes The idea is to make it as practical as possible for the user: - I would use the long click for something else, maybe a small menu about the continent/country - The edit button at the top should enable/disable the checkboxes (but it should be aligned on the right) - Issue: When enabling a country, then the whole continent it belongs to, and then disabling the continent again, there is no undetermined state anymore, the box is unchecked --- .../beendroid/activity/FoldingListAdapter.kt | 13 ++++-- app/src/main/res/drawable/edit.xml | 11 +++++ app/src/main/res/layout/activity_main.xml | 45 ++++++++++++++++++- app/src/main/res/layout/item_list.xml | 38 +++++++++------- app/src/main/res/values/en.xml | 2 +- 5 files changed, 87 insertions(+), 22 deletions(-) create mode 100644 app/src/main/res/drawable/edit.xml diff --git a/app/src/main/java/net/helcel/beendroid/activity/FoldingListAdapter.kt b/app/src/main/java/net/helcel/beendroid/activity/FoldingListAdapter.kt index c7cca73..42f4914 100644 --- a/app/src/main/java/net/helcel/beendroid/activity/FoldingListAdapter.kt +++ b/app/src/main/java/net/helcel/beendroid/activity/FoldingListAdapter.kt @@ -1,6 +1,7 @@ package net.helcel.beendroid.activity import android.content.Context +import android.graphics.Typeface import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -12,6 +13,7 @@ import androidx.recyclerview.widget.RecyclerView import com.google.android.material.checkbox.MaterialCheckBox import net.helcel.beendroid.R import net.helcel.beendroid.countries.GeoLoc +import net.helcel.beendroid.countries.LocType import net.helcel.beendroid.countries.Visited import java.util.* @@ -79,11 +81,14 @@ class FoldingListAdapter( fun bind(el: Pair, parentLambda: () -> Unit) { expand.rotation = if(el.second) 90f else 0f subItemView.visibility = if (el.second) View.VISIBLE else View.GONE - expand.visibility = if(!el.first.isEnd) View.VISIBLE else View.GONE + expand.visibility = if(!el.first.isEnd) View.VISIBLE else View.INVISIBLE textView.text = el.first.fullName + if (el.first.type == LocType.GROUP) { + textView.setTypeface(null, Typeface.BOLD) + } checkBox.checkedState = - if(visited.visited(el.first)) MaterialCheckBox.STATE_CHECKED + if (visited.visited(el.first)) MaterialCheckBox.STATE_CHECKED else if (el.first.children.any { visited.visited(it) }) MaterialCheckBox.STATE_INDETERMINATE else MaterialCheckBox.STATE_UNCHECKED @@ -93,12 +98,12 @@ class FoldingListAdapter( fun addListeners(expandLambda: ()->Boolean, visitedLambda: (Boolean)->Unit) { - textView.setOnClickListener { checkBox.toggle() } + textView.setOnClickListener { expandLambda() } checkBox.addOnCheckedStateChangedListener { _, e -> visitedLambda(e == MaterialCheckBox.STATE_CHECKED) } - textView.setOnLongClickListener{ expandLambda() } + //textView.setOnLongClickListener{ checkBox.toggle(); true } expand.setOnClickListener { expandLambda() } } diff --git a/app/src/main/res/drawable/edit.xml b/app/src/main/res/drawable/edit.xml new file mode 100644 index 0000000..a4df5f3 --- /dev/null +++ b/app/src/main/res/drawable/edit.xml @@ -0,0 +1,11 @@ + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index ea24711..30c760d 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -5,7 +5,48 @@ android:layout_width="fill_parent" android:layout_height="fill_parent"> - + + + + + + + + + + + + + + + - - - Beendroid + BeenDroid Settings Welcome! -- 2.47.1 From 6e5e5c944f26b06c4a0c7f9feaf0da70b20cff72 Mon Sep 17 00:00:00 2001 From: fgerber Date: Wed, 17 Jan 2024 22:47:22 +0100 Subject: [PATCH 2/4] Push the long-awaited changes - Apply consistent blue theming, including setting to switch between dark/light modes - Hide edit button and all checkboxes in front of continents - Use material design for clickable buttons and checkboxes - Show percentages of visited countries per continent (possibly enable/disable in settings?) --- app/build.gradle | 4 +- app/src/main/AndroidManifest.xml | 13 +++- .../beendroid/activity/FoldingListAdapter.kt | 44 ++++++++++--- .../helcel/beendroid/activity/MainActivity.kt | 63 ++++++++++++++++++- .../beendroid/activity/SettingsActivity.kt | 39 ++++++++++++ .../beendroid/activity/SettingsFragment.kt | 54 ++++++++++++++++ .../net/helcel/beendroid/countries/Visited.kt | 6 +- .../net/helcel/beendroid/svg/CSSWrapper.kt | 7 ++- .../net/helcel/beendroid/svg/PSVGWrapper.kt | 29 +++++++-- .../{chevron_right_solid.xml => chevron.xml} | 2 +- app/src/main/res/drawable/edit.xml | 3 +- app/src/main/res/drawable/palette.xml | 11 ++++ app/src/main/res/layout/activity_main.xml | 47 ++------------ app/src/main/res/layout/activity_settings.xml | 16 +++++ app/src/main/res/layout/item_list.xml | 63 +++++++++---------- app/src/main/res/menu/menu_main.xml | 11 +++- app/src/main/res/values-night/themes.xml | 8 ++- app/src/main/res/values/arrays.xml | 8 +++ app/src/main/res/values/colors.xml | 13 ++++ app/src/main/res/values/en.xml | 6 +- app/src/main/res/values/themes.xml | 15 ++--- app/src/main/res/xml/fragment_settings.xml | 17 +++++ 22 files changed, 361 insertions(+), 118 deletions(-) create mode 100644 app/src/main/java/net/helcel/beendroid/activity/SettingsActivity.kt create mode 100644 app/src/main/java/net/helcel/beendroid/activity/SettingsFragment.kt rename app/src/main/res/drawable/{chevron_right_solid.xml => chevron.xml} (89%) create mode 100644 app/src/main/res/drawable/palette.xml create mode 100644 app/src/main/res/layout/activity_settings.xml create mode 100644 app/src/main/res/values/arrays.xml create mode 100644 app/src/main/res/values/colors.xml create mode 100644 app/src/main/res/xml/fragment_settings.xml diff --git a/app/build.gradle b/app/build.gradle index 245a569..4c65cee 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -5,12 +5,12 @@ plugins { android { namespace 'net.helcel.beendroid' - compileSdk 33 + compileSdk 34 defaultConfig { applicationId 'net.helcel.beendroid' minSdk 28 - targetSdk 33 + targetSdk 34 versionCode 1 versionName "1.0" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 13b483f..805e8eb 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -16,14 +16,21 @@ > + android:exported="true" > - + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/net/helcel/beendroid/activity/FoldingListAdapter.kt b/app/src/main/java/net/helcel/beendroid/activity/FoldingListAdapter.kt index 42f4914..a1e0b6c 100644 --- a/app/src/main/java/net/helcel/beendroid/activity/FoldingListAdapter.kt +++ b/app/src/main/java/net/helcel/beendroid/activity/FoldingListAdapter.kt @@ -1,15 +1,20 @@ 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.Log +import android.util.TypedValue import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.ImageView import android.widget.TextView -import androidx.appcompat.content.res.AppCompatResources +import androidx.appcompat.content.res.AppCompatResources.getDrawable import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView +import com.google.android.material.button.MaterialButton import com.google.android.material.checkbox.MaterialCheckBox import net.helcel.beendroid.R import net.helcel.beendroid.countries.GeoLoc @@ -63,15 +68,14 @@ class FoldingListAdapter( private val visited: Visited, ) : RecyclerView.ViewHolder(itemView) { private val textView: TextView - private val expand: ImageView + //private val expand: MaterialButton private val checkBox: MaterialCheckBox private val subItemView: View private val list: RecyclerView init { textView = itemView.findViewById(R.id.textView) - expand = itemView.findViewById(R.id.expand) - expand.setImageDrawable(AppCompatResources.getDrawable(ctx,R.drawable.chevron_right_solid)) + //expand = itemView.findViewById(R.id.expand) checkBox = itemView.findViewById(R.id.checkBox) subItemView = itemView.findViewById(R.id.sub_item) list = itemView.findViewById(R.id.list_list) @@ -79,13 +83,39 @@ class FoldingListAdapter( } fun bind(el: Pair, parentLambda: () -> Unit) { - expand.rotation = if(el.second) 90f else 0f + //expand.rotation = if(el.second) 90f else 0f subItemView.visibility = if (el.second) View.VISIBLE else View.GONE - expand.visibility = if(!el.first.isEnd) View.VISIBLE else View.INVISIBLE + //expand.visibility = if(!el.first.isEnd) View.VISIBLE else View.INVISIBLE textView.text = el.first.fullName if (el.first.type == LocType.GROUP) { textView.setTypeface(null, Typeface.BOLD) + + val colorGrayTyped = TypedValue() + ctx.theme.resolveAttribute(android.R.attr.textColorTertiary, colorGrayTyped, true) + val color = Color.valueOf(colorGrayTyped.data) + textView.setBackgroundColor(Color.valueOf(color.red(), color.green(), color.blue(), 0.5f).toArgb()) + checkBox.visibility = View.INVISIBLE + + el.first.children.apply { + val nbCountries = this.size + val nbVisited = this.map { if (visited.visited(it)) 1 else 0 }.reduce{ a, b -> (a + b) } + val ratio = nbVisited.toFloat() / nbCountries.toFloat() + val percentage = (ratio * 100).toInt() + textView.text = "${textView.text as String} (${percentage}%)" + } + } else { + val colorBackgroundTyped = TypedValue() + ctx.theme.resolveAttribute(android.R.attr.colorBackground, colorBackgroundTyped, true) + textView.backgroundTintList = null + textView.background = ColorDrawable(colorBackgroundTyped.data) + textView.isActivated = false + + val layoutParam = checkBox.layoutParams + layoutParam.width = 125 + checkBox.layoutParams = layoutParam + + checkBox.visibility = View.VISIBLE } checkBox.checkedState = if (visited.visited(el.first)) MaterialCheckBox.STATE_CHECKED @@ -104,7 +134,7 @@ class FoldingListAdapter( } //textView.setOnLongClickListener{ checkBox.toggle(); true } - expand.setOnClickListener { expandLambda() } + //expand.setOnClickListener { expandLambda() } } } diff --git a/app/src/main/java/net/helcel/beendroid/activity/MainActivity.kt b/app/src/main/java/net/helcel/beendroid/activity/MainActivity.kt index a45386b..853cea5 100644 --- a/app/src/main/java/net/helcel/beendroid/activity/MainActivity.kt +++ b/app/src/main/java/net/helcel/beendroid/activity/MainActivity.kt @@ -1,9 +1,20 @@ package net.helcel.beendroid.activity +import android.content.Intent +import android.content.SharedPreferences import android.graphics.Bitmap import android.graphics.Canvas +import android.graphics.Color +import android.graphics.drawable.ColorDrawable import android.os.Bundle +import android.util.Log +import android.util.TypedValue +import android.view.Menu +import android.view.MenuInflater +import android.view.MenuItem import androidx.appcompat.app.AppCompatActivity +import androidx.core.view.MenuProvider +import androidx.preference.PreferenceManager import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.caverock.androidsvg.RenderOptions @@ -17,6 +28,8 @@ import net.helcel.beendroid.svg.PSVGWrapper class MainActivity : AppCompatActivity() { + private lateinit var sharedPreferences: SharedPreferences + private lateinit var map : SVGImageView private lateinit var list : RecyclerView @@ -30,26 +43,70 @@ class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - canvas.drawRGB(255, 255, 255) + // Create action bar + val colorPrimaryTyped = TypedValue() + theme.resolveAttribute(android.R.attr.colorPrimary, colorPrimaryTyped, true) + supportActionBar?.setBackgroundDrawable(ColorDrawable(colorPrimaryTyped.data)) + // Fetch shared preferences to restore app theme upon startup + sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this) + SettingsFragment.setTheme(this, sharedPreferences.getString(getString(R.string.key_theme), getString(R.string.system))) + + // Create menu in action bar + addMenuProvider(object : MenuProvider { + override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) { + menuInflater.inflate(R.menu.menu_main, menu) + } + + override fun onMenuItemSelected(menuItem: MenuItem): Boolean { + return when (menuItem.itemId) { + R.id.action_edit -> { + // TODO: Enable editing selected countries + true + } + R.id.action_settings -> { + // Open settings + startActivity(Intent(this@MainActivity, SettingsActivity::class.java)) + true + } + else -> { + false + } + } + } + + }) + + // Restore visited countries visited = Visited(this) visited.load() + // Wrap lists of countries psvg = PSVGWrapper(this) css = CSSWrapper(visited) + // Populate map from list of countries setContentView(R.layout.activity_main) map = findViewById(R.id.map) map.setImageBitmap(bitmap) - refreshMap() + // Populate list below the map list = findViewById(R.id.list) list.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false) list.adapter = FoldingListAdapter(this, World.WWW.children, visited) { refreshMap() } } private fun refreshMap(){ - psvg.get().renderToCanvas(canvas,RenderOptions.create().css(css.get())) + // Set or reset background (replaces canvas.drawColor(0, 0, 0)) + val colorBackgroundTyped = TypedValue() + theme.resolveAttribute(android.R.attr.colorBackground, colorBackgroundTyped, true) + canvas.drawColor(colorBackgroundTyped.data) + + // Render all countries and visited ones + psvg.getFill().renderToCanvas(canvas, RenderOptions.create().css(css.get())) + + // Render all contours in the same color as the background to make them much clearer + psvg.getDraw().renderToCanvas(canvas) } } \ No newline at end of file diff --git a/app/src/main/java/net/helcel/beendroid/activity/SettingsActivity.kt b/app/src/main/java/net/helcel/beendroid/activity/SettingsActivity.kt new file mode 100644 index 0000000..168899b --- /dev/null +++ b/app/src/main/java/net/helcel/beendroid/activity/SettingsActivity.kt @@ -0,0 +1,39 @@ +package net.helcel.beendroid.activity + +import android.graphics.drawable.ColorDrawable +import android.content.Intent +import android.os.Bundle +import android.os.PersistableBundle +import android.util.TypedValue +import android.view.MenuItem +import androidx.activity.addCallback +import androidx.appcompat.app.AppCompatActivity +import net.helcel.beendroid.R + +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 + val colorPrimaryTyped = TypedValue() + theme.resolveAttribute(android.R.attr.colorPrimary, colorPrimaryTyped, true) + supportActionBar?.setBackgroundDrawable(ColorDrawable(colorPrimaryTyped.data)) + supportActionBar?.title = getString(R.string.action_settings) + supportActionBar?.setDisplayHomeAsUpEnabled(true) + + // Populate activity with settings fragment + supportFragmentManager.beginTransaction() + .replace(R.id.fragment_view, SettingsFragment()) + .commit() + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + // Configure on back pressed + finish() + return super.onOptionsItemSelected(item) + } +} \ No newline at end of file diff --git a/app/src/main/java/net/helcel/beendroid/activity/SettingsFragment.kt b/app/src/main/java/net/helcel/beendroid/activity/SettingsFragment.kt new file mode 100644 index 0000000..ba3c155 --- /dev/null +++ b/app/src/main/java/net/helcel/beendroid/activity/SettingsFragment.kt @@ -0,0 +1,54 @@ +package net.helcel.beendroid.activity + +import android.content.Context +import android.graphics.drawable.ColorDrawable +import android.os.Bundle +import android.util.TypedValue +import androidx.appcompat.app.AppCompatDelegate +import androidx.preference.ListPreference +import androidx.preference.PreferenceFragmentCompat +import net.helcel.beendroid.R + + +class SettingsFragment: PreferenceFragmentCompat() { + private lateinit var themePreference: ListPreference + + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { + setPreferencesFromResource(R.xml.fragment_settings, rootKey) + + // Select Light/Dark/System Mode + themePreference = findPreference(getString(R.string.key_theme))!! + themePreference.setOnPreferenceChangeListener { _, key -> + setTheme(requireContext(), key as String) + } + + } + + companion object { + fun setTheme(context: Context, key: String?): Boolean { + when (key) { + context.getString(R.string.system) -> { + // Set SYSTEM Theme + AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) + return true + } + + context.getString(R.string.light) -> { + // Set LIGHT Theme + AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) + return true + } + + context.getString(R.string.dark) -> { + // Set DARK Theme + AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) + return true + } + + else -> { + return false + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/net/helcel/beendroid/countries/Visited.kt b/app/src/main/java/net/helcel/beendroid/countries/Visited.kt index 07c1a97..b7513fa 100644 --- a/app/src/main/java/net/helcel/beendroid/countries/Visited.kt +++ b/app/src/main/java/net/helcel/beendroid/countries/Visited.kt @@ -10,13 +10,13 @@ class Visited(ctx: Context) { fun load() { - Group.values().forEach { + Group.entries.forEach { locs[it] = pref.getBoolean(it.code, false) } - Country.values().forEach { + Country.entries.forEach { locs[it] = pref.getBoolean(it.code, false) } - State.values().forEach { + State.entries.forEach { locs[it] = pref.getBoolean(it.code, false) } editor.apply() diff --git a/app/src/main/java/net/helcel/beendroid/svg/CSSWrapper.kt b/app/src/main/java/net/helcel/beendroid/svg/CSSWrapper.kt index d5705ec..e95e26e 100644 --- a/app/src/main/java/net/helcel/beendroid/svg/CSSWrapper.kt +++ b/app/src/main/java/net/helcel/beendroid/svg/CSSWrapper.kt @@ -1,20 +1,23 @@ package net.helcel.beendroid.svg +import android.util.TypedValue import net.helcel.beendroid.countries.Visited import net.helcel.beendroid.countries.World class CSSWrapper(private val visited: Visited) { + private val colorPrimary = "#0187FF" + fun get() : String { return listOf(World.WWW.children .filter { visited.visited(it)} - .map { ".${it.code}{fill:blue;}"} + .map { ".${it.code}{fill:$colorPrimary;}"} .fold(""){acc, s-> acc + s}, World.WWW.children .filter { !visited.visited(it) } .map { cg -> cg.children .filter { visited.visited(it) } - .map { ".${it.code}{fill:blue;}"} + .map { ".${it.code}{fill:$colorPrimary;}"} .fold(""){acc, s-> acc + s} }.fold(""){acc,s->acc+s}, ).fold(""){acc,s-> acc+s} diff --git a/app/src/main/java/net/helcel/beendroid/svg/PSVGWrapper.kt b/app/src/main/java/net/helcel/beendroid/svg/PSVGWrapper.kt index 30b5f11..0afbdcd 100644 --- a/app/src/main/java/net/helcel/beendroid/svg/PSVGWrapper.kt +++ b/app/src/main/java/net/helcel/beendroid/svg/PSVGWrapper.kt @@ -1,7 +1,12 @@ package net.helcel.beendroid.svg import android.content.Context +import android.graphics.Color +import android.graphics.drawable.ColorDrawable +import android.util.Log +import android.util.TypedValue 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 @@ -11,8 +16,20 @@ class PSVGWrapper(ctx: Context) { private val cm = HashMap() private var fm = "" + private val colorForeground: String + private val colorBackground: String + init { - Country.values().forEach { + val colorSecondaryTyped = TypedValue() + ctx.theme.resolveAttribute(android.R.attr.textColorTertiary, 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() } build() @@ -31,12 +48,12 @@ class PSVGWrapper(ctx: Context) { }.fold("") { acc, e -> acc + e } } - fun get(): SVG { - return SVG.getFromString("$fm") + fun getFill(): SVG { + return SVG.getFromString("$fm") } - - - + fun getDraw(): SVG { + return SVG.getFromString("$fm") + } } \ No newline at end of file diff --git a/app/src/main/res/drawable/chevron_right_solid.xml b/app/src/main/res/drawable/chevron.xml similarity index 89% rename from app/src/main/res/drawable/chevron_right_solid.xml rename to app/src/main/res/drawable/chevron.xml index a66bef1..6d21775 100644 --- a/app/src/main/res/drawable/chevron_right_solid.xml +++ b/app/src/main/res/drawable/chevron.xml @@ -4,6 +4,6 @@ android:viewportWidth="320" android:viewportHeight="512"> diff --git a/app/src/main/res/drawable/edit.xml b/app/src/main/res/drawable/edit.xml index a4df5f3..5cd1ea2 100644 --- a/app/src/main/res/drawable/edit.xml +++ b/app/src/main/res/drawable/edit.xml @@ -1,11 +1,10 @@ diff --git a/app/src/main/res/drawable/palette.xml b/app/src/main/res/drawable/palette.xml new file mode 100644 index 0000000..e9875e0 --- /dev/null +++ b/app/src/main/res/drawable/palette.xml @@ -0,0 +1,11 @@ + + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 30c760d..bd4166a 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -2,49 +2,9 @@ - - - - - - - - - - - - - + android:theme="@style/Theme.Beendroid" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_list.xml b/app/src/main/res/layout/item_list.xml index 2bbd2bc..b5f2bfa 100644 --- a/app/src/main/res/layout/item_list.xml +++ b/app/src/main/res/layout/item_list.xml @@ -9,49 +9,48 @@ android:layout_width="match_parent" android:layout_height="wrap_content"> - - - + + + app:layout_constraintTop_toBottomOf="@id/checkBox"> + tools:context="net.helcel.beendroid.activity.MainActivity" > + + + - - \ No newline at end of file + diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml new file mode 100644 index 0000000..f5052d1 --- /dev/null +++ b/app/src/main/res/values/arrays.xml @@ -0,0 +1,8 @@ + + + + @string/system + @string/light + @string/dark + + diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..ac343a4 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,13 @@ + + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03AFFF + #FF0187FF + #FFFFDD00 + #FF000000 + #FF555555 + #FFBBBBBB + #FFFFFFFF + diff --git a/app/src/main/res/values/en.xml b/app/src/main/res/values/en.xml index a6fbca8..e75bafd 100644 --- a/app/src/main/res/values/en.xml +++ b/app/src/main/res/values/en.xml @@ -2,7 +2,11 @@ BeenDroid Settings - + Edit Welcome! Change language + App theme + Same as system + Light theme + Dark theme \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 89c86e9..cfa9139 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -1,14 +1,9 @@ - - - - - diff --git a/app/src/main/res/values/en.xml b/app/src/main/res/values/en.xml index e75bafd..e82a8ab 100644 --- a/app/src/main/res/values/en.xml +++ b/app/src/main/res/values/en.xml @@ -1,12 +1,19 @@ BeenDroid + 1.0 Settings Edit Welcome! Change language App theme - Same as system - Light theme - Dark theme + System + Light + Dark + Licenses + About + BeenDroid is free and open source software, licensed under the GNU General Public License (version 3 or later) + Project repository: https://git.helcel.net/helcel/beendroid\n Feel free to report issues or contribute to the project. + Free and open source dependencies and licenses + About the BeenDroid application \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index cfa9139..db354af 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -2,7 +2,7 @@ diff --git a/app/src/main/res/xml/fragment_settings.xml b/app/src/main/res/xml/fragment_settings.xml index 82d5a5c..2f6b780 100644 --- a/app/src/main/res/xml/fragment_settings.xml +++ b/app/src/main/res/xml/fragment_settings.xml @@ -13,5 +13,19 @@ app:entryValues="@array/entries_theme" app:defaultValue="@string/system" /> + + + + \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 34c822e..9377a07 100644 --- a/settings.gradle +++ b/settings.gradle @@ -14,5 +14,5 @@ dependencyResolutionManagement { maven { url 'https://jitpack.io' } } } -rootProject.name = "beendroid" +rootProject.name = "BeenDroid" include ':app' -- 2.47.1 From 84a8a1fe13b5983d9295454f349d5407f72abd94 Mon Sep 17 00:00:00 2001 From: soraefir Date: Sat, 20 Jan 2024 01:19:19 +0100 Subject: [PATCH 4/4] Clean up, parallel compute,... --- app/src/main/AndroidManifest.xml | 1 - .../beendroid/activity/AboutFragment.kt | 1 - .../beendroid/activity/FoldingListAdapter.kt | 43 +++---------------- .../beendroid/activity/LicenseFragment.kt | 4 -- .../helcel/beendroid/activity/MainActivity.kt | 38 +++++++++++++--- .../beendroid/activity/SettingsActivity.kt | 4 -- .../beendroid/activity/SettingsFragment.kt | 2 - .../net/helcel/beendroid/svg/CSSWrapper.kt | 1 - .../net/helcel/beendroid/svg/PSVGWrapper.kt | 4 -- app/src/main/res/layout/item_list.xml | 1 - app/src/main/res/menu/menu_main.xml | 9 +++- app/src/main/res/values/en.xml | 1 + 12 files changed, 48 insertions(+), 61 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 805e8eb..e6296b5 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -27,7 +27,6 @@ android:exported="true" > - diff --git a/app/src/main/java/net/helcel/beendroid/activity/AboutFragment.kt b/app/src/main/java/net/helcel/beendroid/activity/AboutFragment.kt index 1f9bffd..0001d9c 100644 --- a/app/src/main/java/net/helcel/beendroid/activity/AboutFragment.kt +++ b/app/src/main/java/net/helcel/beendroid/activity/AboutFragment.kt @@ -5,7 +5,6 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment -import net.helcel.beendroid.R import net.helcel.beendroid.databinding.FragmentAboutBinding class AboutFragment: Fragment() { diff --git a/app/src/main/java/net/helcel/beendroid/activity/FoldingListAdapter.kt b/app/src/main/java/net/helcel/beendroid/activity/FoldingListAdapter.kt index 44581de..379bbb2 100644 --- a/app/src/main/java/net/helcel/beendroid/activity/FoldingListAdapter.kt +++ b/app/src/main/java/net/helcel/beendroid/activity/FoldingListAdapter.kt @@ -4,17 +4,13 @@ import android.content.Context import android.graphics.Color import android.graphics.Typeface import android.graphics.drawable.ColorDrawable -import android.util.Log import android.util.TypedValue import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.ImageView import android.widget.TextView -import androidx.appcompat.content.res.AppCompatResources.getDrawable import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import com.google.android.material.button.MaterialButton import com.google.android.material.checkbox.MaterialCheckBox import net.helcel.beendroid.R import net.helcel.beendroid.countries.GeoLoc @@ -43,10 +39,7 @@ class FoldingListAdapter( override fun onBindViewHolder(holder: FoldingListViewHolder, position: Int) { val el = cg.toList()[position] - holder.bind(el) { - notifyItemChanged(position) - parentLambda() - } + holder.bind(el) { parentLambda() } holder.addListeners( { if (!el.first.isEnd) { @@ -67,25 +60,16 @@ class FoldingListAdapter( class FoldingListViewHolder(private val ctx: Context, itemView: View, private val visited: Visited, ) : RecyclerView.ViewHolder(itemView) { - private val textView: TextView - //private val expand: MaterialButton - private val checkBox: MaterialCheckBox - private val subItemView: View - private val list: RecyclerView - + private val textView: TextView = itemView.findViewById(R.id.textView) + private val checkBox: MaterialCheckBox = itemView.findViewById(R.id.checkBox) + private val subItemView: View = itemView.findViewById(R.id.sub_item) + private val list: RecyclerView = itemView.findViewById(R.id.list_list) init { - textView = itemView.findViewById(R.id.textView) - //expand = itemView.findViewById(R.id.expand) - checkBox = itemView.findViewById(R.id.checkBox) - subItemView = itemView.findViewById(R.id.sub_item) - list = itemView.findViewById(R.id.list_list) list.layoutManager = LinearLayoutManager(ctx, RecyclerView.VERTICAL, false) } fun bind(el: Pair, parentLambda: () -> Unit) { - //expand.rotation = if(el.second) 90f else 0f subItemView.visibility = if (el.second) View.VISIBLE else View.GONE - //expand.visibility = if(!el.first.isEnd) View.VISIBLE else View.INVISIBLE textView.text = el.first.fullName if (el.first.type == LocType.GROUP) { @@ -95,15 +79,9 @@ class FoldingListAdapter( 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()) - checkBox.visibility = View.INVISIBLE + list.adapter = FoldingListAdapter(ctx, el.first.children,visited, parentLambda) + textView.parent.parent.requestChildFocus(textView,textView) - el.first.children.apply { - val nbCountries = this.size - val nbVisited = this.map { if (visited.visited(it)) 1 else 0 }.reduce{ a, b -> (a + b) } - val ratio = nbVisited.toFloat() / nbCountries.toFloat() - val percentage = (ratio * 100).toInt() - textView.text = "${textView.text as String} (${percentage}%)" - } } else { val colorBackgroundTyped = TypedValue() ctx.theme.resolveAttribute(android.R.attr.colorBackground, colorBackgroundTyped, true) @@ -114,7 +92,6 @@ class FoldingListAdapter( val layoutParam = checkBox.layoutParams layoutParam.width = 125 checkBox.layoutParams = layoutParam - checkBox.visibility = View.VISIBLE } checkBox.checkedState = @@ -122,19 +99,13 @@ class FoldingListAdapter( else if (el.first.children.any { visited.visited(it) }) MaterialCheckBox.STATE_INDETERMINATE else MaterialCheckBox.STATE_UNCHECKED - textView.parent.parent.requestChildFocus(textView,textView) - list.adapter = FoldingListAdapter(ctx, el.first.children,visited, parentLambda) } fun addListeners(expandLambda: ()->Boolean, visitedLambda: (Boolean)->Unit) { - textView.setOnClickListener { expandLambda() } checkBox.addOnCheckedStateChangedListener { _, e -> visitedLambda(e == MaterialCheckBox.STATE_CHECKED) } - - //textView.setOnLongClickListener{ checkBox.toggle(); true } - //expand.setOnClickListener { expandLambda() } } } diff --git a/app/src/main/java/net/helcel/beendroid/activity/LicenseFragment.kt b/app/src/main/java/net/helcel/beendroid/activity/LicenseFragment.kt index b1ad05f..ee964e9 100644 --- a/app/src/main/java/net/helcel/beendroid/activity/LicenseFragment.kt +++ b/app/src/main/java/net/helcel/beendroid/activity/LicenseFragment.kt @@ -2,13 +2,9 @@ package net.helcel.beendroid.activity import android.os.Bundle import android.view.LayoutInflater -import android.view.MenuItem import android.view.View import android.view.ViewGroup -import androidx.appcompat.app.ActionBar -import androidx.appcompat.widget.Toolbar import androidx.fragment.app.Fragment -import com.mikepenz.aboutlibraries.Libs import net.helcel.beendroid.R import net.helcel.beendroid.databinding.FragmentLicenseBinding import com.mikepenz.aboutlibraries.LibsBuilder diff --git a/app/src/main/java/net/helcel/beendroid/activity/MainActivity.kt b/app/src/main/java/net/helcel/beendroid/activity/MainActivity.kt index 853cea5..5bb5699 100644 --- a/app/src/main/java/net/helcel/beendroid/activity/MainActivity.kt +++ b/app/src/main/java/net/helcel/beendroid/activity/MainActivity.kt @@ -1,13 +1,12 @@ package net.helcel.beendroid.activity +import kotlinx.coroutines.* import android.content.Intent import android.content.SharedPreferences import android.graphics.Bitmap import android.graphics.Canvas -import android.graphics.Color import android.graphics.drawable.ColorDrawable import android.os.Bundle -import android.util.Log import android.util.TypedValue import android.view.Menu import android.view.MenuInflater @@ -37,6 +36,8 @@ class MainActivity : AppCompatActivity() { private lateinit var psvg : PSVGWrapper private lateinit var css : CSSWrapper + private var processor: ImageProcessor = ImageProcessor({ refreshMapCompute() },{ refreshMapDisplay(it) }) + private val bitmap: Bitmap = Bitmap.createBitmap(1200,900, Bitmap.Config.ARGB_8888) private val canvas = Canvas(bitmap) @@ -64,6 +65,10 @@ class MainActivity : AppCompatActivity() { // TODO: Enable editing selected countries true } + R.id.action_stats -> { + // TODO: Write stats activity + true + } R.id.action_settings -> { // Open settings startActivity(Intent(this@MainActivity, SettingsActivity::class.java)) @@ -89,24 +94,45 @@ class MainActivity : AppCompatActivity() { setContentView(R.layout.activity_main) map = findViewById(R.id.map) map.setImageBitmap(bitmap) - refreshMap() + refreshMapDisplay(refreshMapCompute()) // Populate list below the map list = findViewById(R.id.list) list.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false) - list.adapter = FoldingListAdapter(this, World.WWW.children, visited) { refreshMap() } + list.adapter = FoldingListAdapter(this, World.WWW.children, visited) { processor.process() } } - private fun refreshMap(){ + private fun refreshMapDisplay(css_value: String){ // Set or reset background (replaces canvas.drawColor(0, 0, 0)) val colorBackgroundTyped = TypedValue() theme.resolveAttribute(android.R.attr.colorBackground, colorBackgroundTyped, true) canvas.drawColor(colorBackgroundTyped.data) // Render all countries and visited ones - psvg.getFill().renderToCanvas(canvas, RenderOptions.create().css(css.get())) + psvg.getFill().renderToCanvas(canvas, RenderOptions.create().css(css_value)) // Render all contours in the same color as the background to make them much clearer psvg.getDraw().renderToCanvas(canvas) } + + private fun refreshMapCompute() : String { + return css.get() + } + + + + class ImageProcessor(private val refreshMapCompute: ()->String, private val refreshMapDisplay: (String)->Unit) { + + private var currentJob : Job? = null + fun process() { + currentJob?.cancel() + currentJob = CoroutineScope(Dispatchers.Main).launch { + try { + refreshMapDisplay(refreshMapCompute()) + } catch (_: CancellationException) { + } + } + } + } + } \ No newline at end of file diff --git a/app/src/main/java/net/helcel/beendroid/activity/SettingsActivity.kt b/app/src/main/java/net/helcel/beendroid/activity/SettingsActivity.kt index 693f6ab..e06fba4 100644 --- a/app/src/main/java/net/helcel/beendroid/activity/SettingsActivity.kt +++ b/app/src/main/java/net/helcel/beendroid/activity/SettingsActivity.kt @@ -1,14 +1,10 @@ package net.helcel.beendroid.activity import android.graphics.drawable.ColorDrawable -import android.content.Intent import android.os.Bundle -import android.os.PersistableBundle import android.util.TypedValue import android.view.MenuItem -import androidx.activity.addCallback import androidx.appcompat.app.AppCompatActivity -import androidx.navigation.findNavController import net.helcel.beendroid.R class SettingsActivity: AppCompatActivity() { diff --git a/app/src/main/java/net/helcel/beendroid/activity/SettingsFragment.kt b/app/src/main/java/net/helcel/beendroid/activity/SettingsFragment.kt index 7746282..6378e15 100644 --- a/app/src/main/java/net/helcel/beendroid/activity/SettingsFragment.kt +++ b/app/src/main/java/net/helcel/beendroid/activity/SettingsFragment.kt @@ -1,9 +1,7 @@ package net.helcel.beendroid.activity import android.content.Context -import android.graphics.drawable.ColorDrawable import android.os.Bundle -import android.util.TypedValue import androidx.appcompat.app.AppCompatDelegate import androidx.preference.ListPreference import androidx.preference.Preference diff --git a/app/src/main/java/net/helcel/beendroid/svg/CSSWrapper.kt b/app/src/main/java/net/helcel/beendroid/svg/CSSWrapper.kt index e95e26e..1ad9312 100644 --- a/app/src/main/java/net/helcel/beendroid/svg/CSSWrapper.kt +++ b/app/src/main/java/net/helcel/beendroid/svg/CSSWrapper.kt @@ -1,6 +1,5 @@ package net.helcel.beendroid.svg -import android.util.TypedValue import net.helcel.beendroid.countries.Visited import net.helcel.beendroid.countries.World diff --git a/app/src/main/java/net/helcel/beendroid/svg/PSVGWrapper.kt b/app/src/main/java/net/helcel/beendroid/svg/PSVGWrapper.kt index 8471add..46bc8ee 100644 --- a/app/src/main/java/net/helcel/beendroid/svg/PSVGWrapper.kt +++ b/app/src/main/java/net/helcel/beendroid/svg/PSVGWrapper.kt @@ -1,12 +1,8 @@ package net.helcel.beendroid.svg import android.content.Context -import android.graphics.Color -import android.graphics.drawable.ColorDrawable -import android.util.Log import android.util.TypedValue 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 diff --git a/app/src/main/res/layout/item_list.xml b/app/src/main/res/layout/item_list.xml index b5f2bfa..c370cae 100644 --- a/app/src/main/res/layout/item_list.xml +++ b/app/src/main/res/layout/item_list.xml @@ -1,7 +1,6 @@ diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml index 1bdac49..a4d5745 100644 --- a/app/src/main/res/menu/menu_main.xml +++ b/app/src/main/res/menu/menu_main.xml @@ -10,10 +10,17 @@ android:visible="false" android:title="@string/action_edit" app:showAsAction="ifRoom" /> - + + \ No newline at end of file diff --git a/app/src/main/res/values/en.xml b/app/src/main/res/values/en.xml index e82a8ab..3dc5f7d 100644 --- a/app/src/main/res/values/en.xml +++ b/app/src/main/res/values/en.xml @@ -3,6 +3,7 @@ BeenDroid 1.0 Settings + Stats Edit Welcome! Change language -- 2.47.1