DoubleRangeUserStyleCategory.kt
/*
* Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.wear.watchface.style
import android.graphics.drawable.Icon
import androidx.annotation.RestrictTo
import androidx.wear.watchface.style.data.DoubleRangeUserStyleCategoryWireFormat
import androidx.wear.watchface.style.data.DoubleRangeUserStyleCategoryWireFormat.DoubleRangeOptionWireFormat
/**
* A DoubleRangeUserStyleCategory represents a category with a [Double] value in the range
* `[minimumValue .. maximumValue]`.
*/
public class DoubleRangeUserStyleCategory : UserStyleCategory {
internal companion object {
internal fun createOptionsList(
minimumValue: Double,
maximumValue: Double,
defaultValue: Double
): List<DoubleRangeOption> {
require(minimumValue < maximumValue)
require(defaultValue >= minimumValue)
require(defaultValue <= maximumValue)
return if (defaultValue != minimumValue && defaultValue != maximumValue) {
listOf(
DoubleRangeOption(minimumValue),
DoubleRangeOption(defaultValue),
DoubleRangeOption(maximumValue)
)
} else {
listOf(DoubleRangeOption(minimumValue), DoubleRangeOption(maximumValue))
}
}
}
public constructor (
/** Identifier for the element, must be unique. */
id: String,
/** Localized human readable name for the element, used in the userStyle selection UI. */
displayName: CharSequence,
/** Localized description string displayed under the displayName. */
description: CharSequence,
/** Icon for use in the userStyle selection UI. */
icon: Icon?,
/** Minimum value (inclusive). */
minimumValue: Double,
/** Maximum value (inclusive). */
maximumValue: Double,
/** The default value for this DoubleRangeUserStyleCategory. */
defaultValue: Double,
/**
* Used by the style configuration UI. Describes which rendering layers this style affects.
*/
affectsLayers: Collection<Layer>
) : super(
id,
displayName,
description,
icon,
createOptionsList(minimumValue, maximumValue, defaultValue),
// The index of defaultValue can only ever be 0 or 1.
when (defaultValue) {
minimumValue -> 0
else -> 1
},
affectsLayers
)
internal constructor(wireFormat: DoubleRangeUserStyleCategoryWireFormat) : super(wireFormat)
/** @hide */
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
override fun toWireFormat(): DoubleRangeUserStyleCategoryWireFormat =
DoubleRangeUserStyleCategoryWireFormat(
id,
displayName,
description,
icon,
getWireFormatOptionsList(),
defaultOptionIndex,
affectsLayers.map { it.ordinal }
)
/**
* Represents an option as a [Double] in the range [minimumValue .. maximumValue].
*/
public class DoubleRangeOption : Option {
/* The value for this option. Must be within the range [minimumValue .. maximumValue]. */
public val value: Double
public constructor(value: Double) : super(value.toString()) {
this.value = value
}
internal companion object {
internal const val KEY_DOUBLE_VALUE = "KEY_DOUBLE_VALUE"
}
internal constructor(
wireFormat: DoubleRangeUserStyleCategoryWireFormat.DoubleRangeOptionWireFormat
) : super(wireFormat.mId) {
value = wireFormat.mValue
}
/** @hide */
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
override fun toWireFormat(): DoubleRangeOptionWireFormat =
DoubleRangeOptionWireFormat(id, value)
}
/**
* Returns the minimum value.
*/
public fun getMinimumValue(): Double = (options.first() as DoubleRangeOption).value
/**
* Returns the maximum value.
*/
public fun getMaximumValue(): Double = (options.last() as DoubleRangeOption).value
/**
* Returns the default value.
*/
public fun getDefaultValue(): Double = (options[defaultOptionIndex] as DoubleRangeOption).value
/**
* We support all values in the range [min ... max] not just min & max.
*/
override fun getOptionForId(optionId: String): Option =
options.find { it.id == optionId } ?: checkedOptionForId(optionId)
private fun checkedOptionForId(optionId: String): DoubleRangeOption {
return try {
val value = optionId.toDouble()
if (value < getMinimumValue() || value > getMaximumValue()) {
options[defaultOptionIndex] as DoubleRangeOption
} else {
DoubleRangeOption(value)
}
} catch (e: NumberFormatException) {
options[defaultOptionIndex] as DoubleRangeOption
}
}
}