diff --git a/README.md b/README.md index f3d31b2..055da1c 100644 --- a/README.md +++ b/README.md @@ -118,7 +118,7 @@ If this validation fails, an `IllegalArgumentException` will be thrown. # Addons -Krate, by default, supports the types that `SharedPreferences` supports. These are `Boolean`, `Float`, `Int`, `Long`, `String` and `Set`. You may of course want to store additional types in Krate. +Krate, by default, supports the types that `SharedPreferences` supports. These are `Boolean`, `Float`, `Int`, `Long`, `String` and `Set`. Additionally, Krate supports `Double`. You may of course want to store additional types in Krate. If you don't find support for the library or type you're looking for, implementing your own delegate in your own project based on the code of existing delegates should be quite simple, this is very much a supported use case. If you think your type might be commonly used, you can also open an issue to ask for an addon library for that type. diff --git a/app/src/main/java/hu/autsoft/krateexample/ExampleActivity.kt b/app/src/main/java/hu/autsoft/krateexample/ExampleActivity.kt index ca9bd79..56c049c 100644 --- a/app/src/main/java/hu/autsoft/krateexample/ExampleActivity.kt +++ b/app/src/main/java/hu/autsoft/krateexample/ExampleActivity.kt @@ -38,6 +38,7 @@ class ExampleActivity : AppCompatActivity() { super.onResume() booleanPreference.isChecked = exampleSettings.exampleBoolean + doublePreferenceInput.setText(exampleSettings.exampleDouble.toString()) floatPreferenceInput.setText(exampleSettings.exampleFloat.toString()) intPreferenceInput.setText(exampleSettings.exampleInt.toString()) longPreferenceInput.setText(exampleSettings.exampleLong.toString()) @@ -49,6 +50,7 @@ class ExampleActivity : AppCompatActivity() { super.onPause() exampleSettings.exampleBoolean = booleanPreference.isChecked + exampleSettings.exampleDouble = doublePreferenceInput.text.toString().toDouble() exampleSettings.exampleFloat = floatPreferenceInput.text.toString().toFloat() exampleSettings.exampleInt = intPreferenceInput.text.toString().toInt() exampleSettings.exampleLong = longPreferenceInput.text.toString().toLong() diff --git a/app/src/main/java/hu/autsoft/krateexample/krates/ExampleCustomKrate.kt b/app/src/main/java/hu/autsoft/krateexample/krates/ExampleCustomKrate.kt index ab43afa..615d40b 100644 --- a/app/src/main/java/hu/autsoft/krateexample/krates/ExampleCustomKrate.kt +++ b/app/src/main/java/hu/autsoft/krateexample/krates/ExampleCustomKrate.kt @@ -6,6 +6,7 @@ import android.content.Context import android.content.SharedPreferences import hu.autsoft.krate.Krate import hu.autsoft.krate.booleanPref +import hu.autsoft.krate.doublePref import hu.autsoft.krate.floatPref import hu.autsoft.krate.intPref import hu.autsoft.krate.longPref @@ -21,6 +22,7 @@ class ExampleCustomKrate(context: Context) : Krate, ExampleSettings { } override var exampleBoolean by booleanPref("exampleBoolean", false) + override var exampleDouble by doublePref("exampleDouble", 0.0) override var exampleFloat by floatPref("exampleFloat", 0f) override var exampleInt by intPref("exampleInt", 0) override var exampleLong by longPref("exampleLong", 0L) diff --git a/app/src/main/java/hu/autsoft/krateexample/krates/ExampleSettings.kt b/app/src/main/java/hu/autsoft/krateexample/krates/ExampleSettings.kt index 1252ce7..46d15a6 100644 --- a/app/src/main/java/hu/autsoft/krateexample/krates/ExampleSettings.kt +++ b/app/src/main/java/hu/autsoft/krateexample/krates/ExampleSettings.kt @@ -2,6 +2,7 @@ package hu.autsoft.krateexample.krates interface ExampleSettings { var exampleBoolean: Boolean + var exampleDouble: Double var exampleFloat: Float var exampleInt: Int var exampleLong: Long diff --git a/app/src/main/java/hu/autsoft/krateexample/krates/ExampleSimpleKrate.kt b/app/src/main/java/hu/autsoft/krateexample/krates/ExampleSimpleKrate.kt index 62e9def..7288525 100644 --- a/app/src/main/java/hu/autsoft/krateexample/krates/ExampleSimpleKrate.kt +++ b/app/src/main/java/hu/autsoft/krateexample/krates/ExampleSimpleKrate.kt @@ -3,6 +3,7 @@ package hu.autsoft.krateexample.krates import android.content.Context import hu.autsoft.krate.SimpleKrate import hu.autsoft.krate.booleanPref +import hu.autsoft.krate.doublePref import hu.autsoft.krate.floatPref import hu.autsoft.krate.intPref import hu.autsoft.krate.longPref @@ -16,6 +17,7 @@ class ExampleSimpleKrate(context: Context) : SimpleKrate(context, NAME), Example } override var exampleBoolean by booleanPref("exampleBoolean", false) + override var exampleDouble by doublePref("exampleDouble", 0.0) override var exampleFloat by floatPref("exampleFloat", 0f) override var exampleInt by intPref("exampleInt", 0) override var exampleLong by longPref("exampleLong", 0L) diff --git a/app/src/main/res/layout/activity_example.xml b/app/src/main/res/layout/activity_example.xml index c0bf635..2960dd0 100644 --- a/app/src/main/res/layout/activity_example.xml +++ b/app/src/main/res/layout/activity_example.xml @@ -22,7 +22,7 @@ app:layout_constraintTop_toTopOf="parent" /> + + + + + + { return BooleanDelegate(key) } +/** + * Creates an option preference of type Double with the given [key] in this [Krate] instance. + */ +public fun Krate.doublePref(key: String): ReadWriteProperty { + return DoubleDelegate(key) +} + /** * Creates an optional preference of type [Float] with the given [key] in this [Krate] instance. */ @@ -66,6 +75,13 @@ public fun Krate.booleanPref(key: String, defaultValue: Boolean): ReadWritePrope return BooleanDelegateWithDefault(key, defaultValue) } +/** + * Creates a non-option preference of type Double with the given [key] and [defaultValue] in this [Krate] instance. + */ +public fun Krate.doublePref(key: String, defaultValue: Double): ReadWriteProperty { + return DoubleDelegateWithDefault(key, defaultValue) +} + /** * Creates a non-optional preference of type [Float] with the given [key] and [defaultValue] in this [Krate] instance. */ diff --git a/krate/src/main/kotlin/hu/autsoft/krate/default/DoubleDelegateWithDefault.kt b/krate/src/main/kotlin/hu/autsoft/krate/default/DoubleDelegateWithDefault.kt new file mode 100644 index 0000000..4eb9dc1 --- /dev/null +++ b/krate/src/main/kotlin/hu/autsoft/krate/default/DoubleDelegateWithDefault.kt @@ -0,0 +1,26 @@ +package hu.autsoft.krate.default + +import hu.autsoft.krate.Krate +import hu.autsoft.krate.util.edit +import hu.autsoft.krate.util.getDouble +import hu.autsoft.krate.util.putDouble +import kotlin.properties.ReadWriteProperty +import kotlin.reflect.KProperty + +internal class DoubleDelegateWithDefault( + private val key: String, + private val default: Double +) : ReadWriteProperty { + + override operator fun getValue(thisRef: Krate, property: KProperty<*>): Double { + return if (thisRef.sharedPreferences.contains(key)) { + thisRef.sharedPreferences.getDouble(key, default) + } else { + default + } + } + + override operator fun setValue(thisRef: Krate, property: KProperty<*>, value: Double) { + thisRef.sharedPreferences.edit { putDouble(key, value) } + } +} \ No newline at end of file diff --git a/krate/src/main/kotlin/hu/autsoft/krate/optional/DoubleDelegate.kt b/krate/src/main/kotlin/hu/autsoft/krate/optional/DoubleDelegate.kt new file mode 100644 index 0000000..7d56008 --- /dev/null +++ b/krate/src/main/kotlin/hu/autsoft/krate/optional/DoubleDelegate.kt @@ -0,0 +1,31 @@ +package hu.autsoft.krate.optional + +import hu.autsoft.krate.Krate +import hu.autsoft.krate.util.edit +import hu.autsoft.krate.util.getDouble +import hu.autsoft.krate.util.putDouble +import kotlin.properties.ReadWriteProperty +import kotlin.reflect.KProperty + +internal class DoubleDelegate( + private val key: String +) : ReadWriteProperty { + + override operator fun getValue(thisRef: Krate, property: KProperty<*>): Double? { + return if (!thisRef.sharedPreferences.contains(key)) { + null + } else { + thisRef.sharedPreferences.getDouble(key, 0.0) + //thisRef.sharedPreferences.getLong(key, 0.0.toRawBits()).toDouble() + } + } + + override fun setValue(thisRef: Krate, property: KProperty<*>, value: Double?) { + if (value == null) { + thisRef.sharedPreferences.edit { remove(key) } + } else { + thisRef.sharedPreferences.edit { putDouble(key, value) } + //thisRef.sharedPreferences.edit { putLong(key, value.toRawBits()) } + } + } +} \ No newline at end of file diff --git a/krate/src/main/kotlin/hu/autsoft/krate/util/SharedPrefExtensions.kt b/krate/src/main/kotlin/hu/autsoft/krate/util/SharedPrefExtensions.kt index 828a45d..3391a50 100644 --- a/krate/src/main/kotlin/hu/autsoft/krate/util/SharedPrefExtensions.kt +++ b/krate/src/main/kotlin/hu/autsoft/krate/util/SharedPrefExtensions.kt @@ -7,3 +7,9 @@ internal inline fun SharedPreferences.edit(edits: SharedPreferences.Editor.() -> editor.edits() editor.apply() } + +internal fun SharedPreferences.Editor.putDouble(key: String, double: Double) = + putLong(key, java.lang.Double.doubleToRawLongBits(double)) + +internal fun SharedPreferences.getDouble(key: String, default: Double) = + java.lang.Double.longBitsToDouble(getLong(key, java.lang.Double.doubleToRawLongBits(default))) \ No newline at end of file diff --git a/krate/src/test/java/hu/autsoft/krate/TestKrate.kt b/krate/src/test/java/hu/autsoft/krate/TestKrate.kt index c138410..775c4a5 100644 --- a/krate/src/test/java/hu/autsoft/krate/TestKrate.kt +++ b/krate/src/test/java/hu/autsoft/krate/TestKrate.kt @@ -10,6 +10,7 @@ internal class TestKrate(context: Context) : SimpleKrate(context) { } var optionalBoolean by booleanPref("optionalBoolean") + var optionDouble by doublePref("optionalDouble") var optionalFloat by floatPref("optionalFloat") var optionalInt by intPref("optionalInt") var optionalLong by longPref("optionalLong") diff --git a/krate/src/test/java/hu/autsoft/krate/test/OptionalTests.kt b/krate/src/test/java/hu/autsoft/krate/test/OptionalTests.kt index 6bcb1f4..e4d963f 100644 --- a/krate/src/test/java/hu/autsoft/krate/test/OptionalTests.kt +++ b/krate/src/test/java/hu/autsoft/krate/test/OptionalTests.kt @@ -33,6 +33,20 @@ internal class OptionalTests { assertEquals(null, testKrate.optionalBoolean) } + @Test + fun testOptionalDoublePref() { + assertEquals(null, testKrate.optionDouble) + + testKrate.optionDouble = -487741.0 + assertEquals(-487741.0, testKrate.optionDouble) + + testKrate.optionDouble = 215125.0 + assertEquals(215125.0, testKrate.optionDouble) + + testKrate.optionDouble = null + assertEquals(null, testKrate.optionDouble) + } + @Test fun testOptionalFloatPref() { assertEquals(null, testKrate.optionalFloat)