Merge pull request #2670 from Philoul/wear/new_custom_watchface

Custom Watchface Improve code
This commit is contained in:
Milos Kozak 2023-08-16 19:15:11 +02:00 committed by GitHub
commit e8058ecc2b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 229 additions and 220 deletions

70
_docs/icons/ic_arrows.svg Normal file
View file

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve">
<g id="ic_invalid">
<g>
<g>
<circle fill="#36FF00" cx="17.991" cy="20.275" r="1.285"/>
<path fill="#36FF00" d="M17.936,17.188c-0.514,0-0.93-0.416-0.93-0.93c0-3.343,1.558-4.509,2.81-5.446
c1.049-0.786,1.808-1.354,1.808-3.191c0-2.534-2.433-3.321-3.32-3.321c-1.91,0-3.452,1.145-4.231,3.14
c-0.187,0.479-0.728,0.716-1.204,0.528c-0.479-0.187-0.714-0.726-0.528-1.204c1.057-2.707,3.286-4.322,5.963-4.322
c2.088,0,5.18,1.646,5.18,5.18c0,2.768-1.416,3.828-2.553,4.679c-1.154,0.864-2.065,1.546-2.065,3.958
C18.866,16.771,18.45,17.188,17.936,17.188z"/>
</g>
<g>
<circle fill="#36FF00" cx="6.228" cy="20.275" r="1.285"/>
<path fill="#36FF00" d="M6.173,17.188c-0.514,0-0.93-0.416-0.93-0.93c0-3.343,1.558-4.509,2.81-5.446
c1.049-0.786,1.808-1.354,1.808-3.191c0-2.534-2.433-3.321-3.32-3.321c-1.91,0-3.452,1.145-4.231,3.14
C2.124,7.918,1.583,8.155,1.107,7.967C0.628,7.78,0.392,7.241,0.579,6.763C1.636,4.056,3.865,2.44,6.542,2.44
c2.088,0,5.18,1.646,5.18,5.18c0,2.768-1.416,3.828-2.553,4.679c-1.154,0.864-2.065,1.546-2.065,3.958
C7.103,16.771,6.687,17.188,6.173,17.188z"/>
</g>
</g>
</g>
<g id="ic_flat">
<path fill="#36FF00" d="M17.17,18.413c2.186-2.357,4.922-5.167,6.828-6.413H24c0,0-0.001-0.001-0.001-0.001
c0,0,0.001-0.001,0.001-0.001h-0.003c-1.906-1.246-4.642-4.056-6.828-6.413l-2.199,1.6c0,0,1.7,1.905,3.294,3.543H0l0,2.54h18.264
c-1.593,1.638-3.294,3.543-3.294,3.543L17.17,18.413z"/>
</g>
<g id="ic_simpleup">
<path fill="#36FF00" d="M18.16,6.83c-2.357-2.186-5.167-4.922-6.413-6.828V0c0,0-0.001,0.001-0.001,0.001
c0,0-0.001-0.001-0.001-0.001l0,0.002C10.5,1.908,7.69,4.644,5.333,6.83l1.6,2.199c0,0,1.905-1.7,3.543-3.294V24h2.54V5.736
C14.655,7.329,16.56,9.03,16.56,9.03L18.16,6.83z"/>
</g>
<g id="ic_doubleup">
<g>
<path fill="#36FF00" d="M0.772,6.83c2.357-2.186,5.167-4.922,6.413-6.828V0c0,0,0.001,0.001,0.001,0.001
c0,0,0.001-0.001,0.001-0.001v0.003c1.246,1.906,4.056,4.642,6.413,6.828l-1.6,2.199c0,0-1.905-1.7-3.543-3.294V24h-2.54V5.736
C4.278,7.329,2.373,9.03,2.373,9.03L0.772,6.83z"/>
<path fill="#36FF00" d="M10.401,6.83c2.357-2.186,5.167-4.922,6.413-6.828V0c0,0,0.001,0.001,0.001,0.001
c0,0,0.001-0.001,0.001-0.001v0.003c1.246,1.906,4.056,4.642,6.413,6.828l-1.6,2.199c0,0-1.905-1.7-3.543-3.294V24h-2.54V5.736
c-1.638,1.593-3.543,3.294-3.543,3.294L10.401,6.83z"/>
</g>
</g>
<g id="ic_simpledown">
<path fill="#36FF00" d="M5.587,17.17c2.357,2.186,5.167,4.922,6.413,6.828V24c0,0,0.001-0.001,0.001-0.001
c0,0,0.001,0.001,0.001,0.001v-0.003c1.246-1.906,4.056-4.642,6.413-6.828l-1.6-2.199c0,0-1.905,1.7-3.543,3.294V0l-2.54,0v18.264
c-1.638-1.593-3.543-3.294-3.543-3.294L5.587,17.17z"/>
</g>
<g id="ic_doubledown">
<g>
<path fill="#36FF00" d="M0.772,17.17c2.357,2.186,5.167,4.922,6.413,6.828V24c0,0,0.001-0.001,0.001-0.001
c0,0,0.001,0.001,0.001,0.001v-0.003c1.246-1.906,4.056-4.642,6.413-6.828l-1.6-2.199c0,0-1.905,1.7-3.543,3.294V0l-2.54,0v18.264
c-1.638-1.593-3.543-3.294-3.543-3.294L0.772,17.17z"/>
<path fill="#36FF00" d="M10.401,17.17c2.357,2.186,5.167,4.922,6.413,6.828V24c0,0,0.001-0.001,0.001-0.001
c0,0,0.001,0.001,0.001,0.001v-0.003c1.246-1.906,4.056-4.642,6.413-6.828l-1.6-2.199c0,0-1.905,1.7-3.543,3.294V0l-2.54,0v18.264
c-1.638-1.593-3.543-3.294-3.543-3.294L10.401,17.17z"/>
</g>
</g>
<g id="ic_fortyfivedown">
<path fill="#36FF00" d="M11.121,20.191c3.212-0.121,7.134-0.173,9.362,0.294l0.002,0.002l0-0.002l0.002,0l-0.002-0.002
c-0.466-2.229-0.414-6.15-0.294-9.362l-2.687-0.424c0,0-0.145,2.55-0.176,4.834L4.413,2.617L2.617,4.413l12.915,12.915
c-2.285,0.031-4.834,0.176-4.834,0.176L11.121,20.191z"/>
</g>
<g id="ic_fortyfiveup">
<path fill="#36FF00" d="M20.191,12.879c-0.121-3.212-0.173-7.134,0.294-9.362l0.002-0.002l-0.002,0l0-0.002l-0.002,0.002
c-2.229,0.466-6.15,0.414-9.362,0.294l-0.424,2.687c0,0,2.55,0.145,4.834,0.176L2.617,19.587l1.796,1.796L17.328,8.469
c0.031,2.285,0.176,4.834,0.176,4.834L20.191,12.879z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.2 KiB

View file

@ -17,7 +17,7 @@ import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
import java.util.zip.ZipOutputStream
val CUSTOM_VERSION = "0.3"
val CUSTOM_VERSION = "0.5"
enum class CustomWatchfaceDrawableDataKey(val key: String, @DrawableRes val icon: Int?, val fileName: String) {
UNKNOWN("unknown", null, "Unknown"),
CUSTOM_WATCHFACE("customWatchface", R.drawable.watchface_custom, "CustomWatchface"),
@ -29,54 +29,23 @@ enum class CustomWatchfaceDrawableDataKey(val key: String, @DrawableRes val icon
SECONDHAND("second_hand", R.drawable.second_hand, "SecondHand");
companion object {
private val keyToEnumMap = HashMap<String, CustomWatchfaceDrawableDataKey>()
private val fileNameToEnumMap = HashMap<String, CustomWatchfaceDrawableDataKey>()
init {
for (value in values()) keyToEnumMap[value.key] = value
for (value in values()) fileNameToEnumMap[value.fileName] = value
}
fun fromKey(key: String): CustomWatchfaceDrawableDataKey =
if (keyToEnumMap.containsKey(key)) {
keyToEnumMap[key] ?: UNKNOWN
} else {
UNKNOWN
}
fun fromFileName(file: String): CustomWatchfaceDrawableDataKey =
if (fileNameToEnumMap.containsKey(file.substringBeforeLast("."))) {
fileNameToEnumMap[file.substringBeforeLast(".")] ?: UNKNOWN
} else {
UNKNOWN
}
values().firstOrNull { it.key == key } ?: UNKNOWN
fun fromFileName(file: String): CustomWatchfaceDrawableDataKey = values().firstOrNull { it.fileName == file.substringBeforeLast(".") } ?: UNKNOWN
}
}
enum class DrawableFormat(val extension: String) {
UNKNOWN(""),
//XML("xml"),
//SVG("svg"),
JPG("jpg"),
PNG("png");
companion object {
private val extensionToEnumMap = HashMap<String, DrawableFormat>()
init {
for (value in values()) extensionToEnumMap[value.extension] = value
}
fun fromFileName(fileName: String): DrawableFormat =
if (extensionToEnumMap.containsKey(fileName.substringAfterLast("."))) {
extensionToEnumMap[fileName.substringAfterLast(".")] ?: UNKNOWN
} else {
UNKNOWN
}
values().firstOrNull { it.extension == fileName.substringAfterLast(".") } ?: UNKNOWN
}
}
@ -123,25 +92,14 @@ enum class CustomWatchfaceMetadataKey(val key: String, @StringRes val label: Int
CWF_FILENAME("filename", R.string.metadata_wear_import_filename),
CWF_AUTHOR("author", R.string.metadata_label_watchface_author),
CWF_CREATED_AT("created_at", R.string.metadata_label_watchface_created_at),
CWF_VERSION("cwf_version", R.string.metadata_label_watchface_version);
CWF_VERSION("cwf_version", R.string.metadata_label_plugin_version),
CWF_AUTHOR_VERSION("author_version", R.string.metadata_label_watchface_name_version),
CWF_COMMENT("comment", R.string.metadata_label_watchface_comment); // label not planed to be used for CWF_COMMENT
companion object {
private val keyToEnumMap = HashMap<String, CustomWatchfaceMetadataKey>()
init {
for (value in values()) keyToEnumMap[value.key] = value
}
fun fromKey(key: String): CustomWatchfaceMetadataKey? =
if (keyToEnumMap.containsKey(key)) {
keyToEnumMap[key]
} else {
null
}
values().firstOrNull { it.key == key }
}
}
class ZipWatchfaceFormat {

View file

@ -44,7 +44,10 @@
<string name="metadata_label_watchface_author">Author: %1$s</string>
<string name="metadata_label_watchface_name">Name: %1$s</string>
<string name="metadata_wear_import_filename">File name: %1$s</string>
<string name="metadata_label_watchface_version">Watchface version: %1$s</string>
<string name="metadata_label_plugin_version">Plugin version: %1$s</string>
<string name="metadata_label_watchface_name_version">Name: %1$s (%2$s)</string>
<string name="metadata_label_watchface_comment" translatable="false">%1$s</string>
<string name="default_custom_watchface_comment">Default watchface, you can click on EXPORT WATCHFACE button to generate a template</string>
<string name="wear_default_watchface">Default Watchface</string>
</resources>

View file

@ -92,6 +92,10 @@ class CustomWatchfaceImportListActivity: TranslatedDaggerAppCompatActivity() {
filelistName.tag = customWatchfaceFile
customWatchface.setImageDrawable(drawable)
customName.text = rh.gs(CWF_NAME.label, metadata[CWF_NAME])
metadata[CWF_AUTHOR_VERSION]?.let { author_version ->
customName.text = rh.gs(CWF_AUTHOR_VERSION.label, metadata[CWF_NAME], author_version)
}
author.text = rh.gs(CWF_AUTHOR.label, metadata[CWF_AUTHOR] ?:"")
createdAt.text = rh.gs(CWF_CREATED_AT.label, metadata[CWF_CREATED_AT] ?:"")
cwfVersion.text = rh.gs(CWF_VERSION.label, metadata[CWF_VERSION] ?:"")

View file

@ -20,6 +20,7 @@ import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.TextView
import androidx.annotation.DrawableRes
import androidx.annotation.FontRes
import androidx.annotation.IdRes
import androidx.annotation.StringRes
import androidx.core.content.ContextCompat
@ -29,6 +30,7 @@ import androidx.viewbinding.ViewBinding
import info.nightscout.androidaps.R
import info.nightscout.androidaps.databinding.ActivityCustomBinding
import info.nightscout.androidaps.watchfaces.utils.BaseWatchFace
import info.nightscout.rx.logging.LTag
import info.nightscout.rx.weardata.CUSTOM_VERSION
import info.nightscout.rx.weardata.CustomWatchfaceData
import info.nightscout.rx.weardata.CustomWatchfaceDrawableDataKey
@ -56,6 +58,10 @@ class CustomWatchface : BaseWatchFace() {
private var lowBatColor = Color.RED
private var bgColor = Color.WHITE
override fun onCreate() {
super.onCreate()
FontMap.init(context)
}
@Suppress("DEPRECATION")
override fun inflateLayout(inflater: LayoutInflater): ViewBinding {
@ -77,13 +83,18 @@ class CustomWatchface : BaseWatchFace() {
override fun setDataFields() {
super.setDataFields()
binding.direction2.setImageDrawable(resources.getDrawable(TrendArrow.fromSymbol(singleBg.slopeArrow).icon))
binding.direction2.setImageDrawable(resources.getDrawable(TrendArrow.icon(singleBg.slopeArrow)))
// rotate the second hand.
binding.secondHand.rotation = TimeOfDay().secondOfMinute * 6f
// rotate the minute hand.
binding.minuteHand.rotation = TimeOfDay().minuteOfHour * 6f
// rotate the hour hand.
binding.hourHand.rotation = TimeOfDay().hourOfDay * 30f + TimeOfDay().minuteOfHour * 0.5f
}
override fun setColorDark() {
setWatchfaceStyle()
binding.mainLayout.setBackgroundColor(ContextCompat.getColor(this, R.color.dark_background))
binding.sgv.setTextColor(bgColor)
binding.direction.setTextColor(bgColor)
binding.direction2.colorFilter = changeDrawableColor(bgColor)
if (ageLevel != 1)
@ -96,16 +107,6 @@ class CustomWatchface : BaseWatchFace() {
else -> binding.loop.setBackgroundResource(R.drawable.loop_red_25)
}
basalBackgroundColor = ContextCompat.getColor(this, R.color.basal_dark)
basalCenterColor = ContextCompat.getColor(this, R.color.basal_light)
// rotate the second hand.
binding.secondHand.rotation = TimeOfDay().secondOfMinute * 6f
// rotate the minute hand.
binding.minuteHand.rotation = TimeOfDay().minuteOfHour * 6f
// rotate the hour hand.
binding.hourHand.rotation = TimeOfDay().hourOfDay * 30f + TimeOfDay().minuteOfHour * 0.5f
setupCharts()
}
@ -143,7 +144,9 @@ class CustomWatchface : BaseWatchFace() {
lowColor = if (json.has("lowColor")) Color.parseColor(json.getString("lowColor")) else ContextCompat.getColor(this, R.color.low)
lowBatColor = if (json.has("lowBatColor")) Color.parseColor(json.getString("lowBatColor")) else ContextCompat.getColor(this, R.color.dark_uploaderBatteryEmpty)
carbColor = if (json.has("carbColor")) Color.parseColor(json.getString("carbColor")) else ContextCompat.getColor(this, R.color.carbs)
gridColor = if (json.has("gridColor")) Color.parseColor(json.getString("gridColor")) else ContextCompat.getColor(this, R.color.carbs)
basalBackgroundColor = if (json.has("basalBackgroundColor")) Color.parseColor(json.getString("basalBackgroundColor")) else ContextCompat.getColor(this, R.color.basal_dark)
basalCenterColor = if (json.has("basalCenterColor")) Color.parseColor(json.getString("basalCenterColor")) else ContextCompat.getColor(this, R.color.basal_light)
gridColor = if (json.has("gridColor")) Color.parseColor(json.getString("gridColor")) else Color.WHITE
pointSize = if (json.has("pointSize")) json.getInt("pointSize") else 2
bgColor = when (singleBg.sgvLevel) {
1L -> highColor
@ -167,10 +170,10 @@ class CustomWatchface : BaseWatchFace() {
if (view is TextView) {
view.rotation = if (viewjson.has("rotation")) viewjson.getInt("rotation").toFloat() else 0F
view.setTextSize(TypedValue.COMPLEX_UNIT_PX, ((if (viewjson.has("textsize")) viewjson.getInt("textsize") else 22) * zoomFactor).toFloat())
view.gravity = setGravity(if (viewjson.has("gravity")) viewjson.getString("gravity") else "center")
view.gravity = GravityMap.gravity(if (viewjson.has("gravity")) viewjson.getString("gravity") else GravityMap.CENTER.key)
view.setTypeface(
setFont(if (viewjson.has("font")) viewjson.getString("font") else "sans-serif"),
setStyle(if (viewjson.has("fontStyle")) viewjson.getString("fontStyle") else "normal")
FontMap.font(if (viewjson.has("font")) viewjson.getString("font") else FontMap.DEFAULT.key),
StyleMap.style(if (viewjson.has("fontStyle")) viewjson.getString("fontStyle") else StyleMap.NORMAL.key)
)
if (viewjson.has("fontColor"))
view.setTextColor(getColor(viewjson.getString("fontColor")))
@ -203,8 +206,10 @@ class CustomWatchface : BaseWatchFace() {
}
}
}
binding.background.visibility = View.VISIBLE
updateSecondVisibility()
} catch (e:Exception) {
} catch (e: Exception) {
aapsLogger.debug(LTag.WEAR, "Crash during Custom watch load")
persistence.store(defaultWatchface(), false) // relaod correct values to avoid crash of watchface
}
}
@ -216,7 +221,9 @@ class CustomWatchface : BaseWatchFace() {
.put(CustomWatchfaceMetadataKey.CWF_FILENAME.key, getString(info.nightscout.shared.R.string.wear_default_watchface))
.put(CustomWatchfaceMetadataKey.CWF_AUTHOR.key, "Philoul")
.put(CustomWatchfaceMetadataKey.CWF_CREATED_AT.key, dateUtil.dateString(dateUtil.now()))
.put(CustomWatchfaceMetadataKey.CWF_AUTHOR_VERSION.key, CUSTOM_VERSION)
.put(CustomWatchfaceMetadataKey.CWF_VERSION.key, CUSTOM_VERSION)
.put(CustomWatchfaceMetadataKey.CWF_COMMENT.key, getString(info.nightscout.shared.R.string.default_custom_watchface_comment))
val json = JSONObject()
.put("metadata", metadata)
.put("highColor", String.format("#%06X", 0xFFFFFF and highColor))
@ -224,8 +231,10 @@ class CustomWatchface : BaseWatchFace() {
.put("lowColor", String.format("#%06X", 0xFFFFFF and lowColor))
.put("lowBatColor", String.format("#%06X", 0xFFFFFF and lowBatColor))
.put("carbColor", String.format("#%06X", 0xFFFFFF and carbColor))
.put("basalBackgroundColor", String.format("#%06X", 0xFFFFFF and basalBackgroundColor))
.put("basalCenterColor", String.format("#%06X", 0xFFFFFF and basalCenterColor))
.put("gridColor", String.format("#%06X", 0xFFFFFF and Color.WHITE))
.put("pointSize",2)
.put("pointSize", 2)
.put("enableSecond", true)
binding.mainLayout.forEach { view ->
@ -242,14 +251,13 @@ class CustomWatchface : BaseWatchFace() {
.put("rotation", view.rotation.toInt())
.put("visibility", getVisibility(view.visibility))
.put("textsize", view.textSize.toInt())
.put("gravity", getGravity(view.gravity))
.put("font", getFont(view.typeface))
.put("fontStyle", getStyle(view.typeface.style))
.put("gravity", GravityMap.key(view.gravity))
.put("font", FontMap.key())
.put("fontStyle", StyleMap.key(view.typeface.style))
.put("fontColor", String.format("#%06X", 0xFFFFFF and view.currentTextColor))
)
}
if (view is ImageView) {
//view.backgroundTintList =
json.put(
it.key,
JSONObject()
@ -276,7 +284,7 @@ class CustomWatchface : BaseWatchFace() {
val metadataMap = ZipWatchfaceFormat.loadMetadata(json)
val drawableDataMap: CustomWatchfaceDrawableDataMap = mutableMapOf()
getResourceByteArray(info.nightscout.shared.R.drawable.watchface_custom)?.let {
val drawableData = DrawableData(it,DrawableFormat.PNG)
val drawableData = DrawableData(it, DrawableFormat.PNG)
drawableDataMap[CustomWatchfaceDrawableDataKey.CUSTOM_WATCHFACE] = drawableData
}
return EventData.ActionSetCustomWatchface(CustomWatchfaceData(json.toString(4), metadataMap, drawableDataMap))
@ -287,6 +295,8 @@ class CustomWatchface : BaseWatchFace() {
midColor = Color.parseColor("#00FF00")
lowColor = Color.parseColor("#FF0000")
carbColor = ContextCompat.getColor(this, R.color.carbs)
basalBackgroundColor = ContextCompat.getColor(this, R.color.basal_dark)
basalCenterColor = ContextCompat.getColor(this, R.color.basal_light)
lowBatColor = ContextCompat.getColor(this, R.color.dark_uploaderBatteryEmpty)
gridColor = Color.WHITE
}
@ -305,62 +315,6 @@ class CustomWatchface : BaseWatchFace() {
else -> "gone"
}
private fun setGravity(gravity: String): Int = when (gravity) {
"center" -> Gravity.CENTER
"left" -> Gravity.LEFT
"right" -> Gravity.RIGHT
else -> Gravity.CENTER
}
private fun getGravity(gravity: Int): String = when (gravity) {
Gravity.CENTER -> "center"
Gravity.LEFT -> "left"
Gravity.RIGHT -> "right"
else -> "center"
}
private fun setFont(font: String): Typeface = when (font) {
"sans-serif" -> Typeface.SANS_SERIF
"default" -> Typeface.DEFAULT
"default-bold" -> Typeface.DEFAULT_BOLD
"monospace" -> Typeface.MONOSPACE
"serif" -> Typeface.SERIF
"roboto-condensed-bold" -> ResourcesCompat.getFont(context, R.font.roboto_condensed_bold)!!
"roboto-condensed-light" -> ResourcesCompat.getFont(context, R.font.roboto_condensed_light)!!
"roboto-condensed-regular" -> ResourcesCompat.getFont(context, R.font.roboto_condensed_regular)!!
"roboto-slab-light" -> ResourcesCompat.getFont(context, R.font.roboto_slab_light)!!
else -> Typeface.DEFAULT
}
private fun getFont(font: Typeface): String = when (font) {
Typeface.SANS_SERIF -> "sans-serif"
Typeface.DEFAULT -> "default"
Typeface.DEFAULT_BOLD -> "default-bold"
Typeface.MONOSPACE -> "monospace"
Typeface.SERIF -> "serif"
ResourcesCompat.getFont(context, R.font.roboto_condensed_bold)!! -> "roboto-condensed-bold"
ResourcesCompat.getFont(context, R.font.roboto_condensed_light)!! -> "roboto-condensed-light"
ResourcesCompat.getFont(context, R.font.roboto_condensed_regular)!! -> "roboto-condensed-regular"
ResourcesCompat.getFont(context, R.font.roboto_slab_light)!! -> "roboto-slab-light"
else -> "default"
}
private fun setStyle(style: String): Int = when (style) {
"normal" -> Typeface.NORMAL
"bold" -> Typeface.BOLD
"bold-italic" -> Typeface.BOLD_ITALIC
"italic" -> Typeface.ITALIC
else -> Typeface.NORMAL
}
private fun getStyle(style: Int): String = when (style) {
Typeface.NORMAL -> "normal"
Typeface.BOLD -> "bold"
Typeface.BOLD_ITALIC -> "bold-italic"
Typeface.ITALIC -> "italic"
else -> "normal"
}
fun getResourceByteArray(resourceId: Int): ByteArray? {
val inputStream = resources.openRawResource(resourceId)
val byteArrayOutputStream = ByteArrayOutputStream()
@ -408,7 +362,7 @@ class CustomWatchface : BaseWatchFace() {
}
}
enum class CustomViews(val key: String, @IdRes val id: Int, @StringRes val pref: Int?) {
private enum class CustomViews(val key: String, @IdRes val id: Int, @StringRes val pref: Int?) {
BACKGROUND(CustomWatchfaceDrawableDataKey.BACKGROUND.key, R.id.background, null),
CHART("chart", R.id.chart, null),
@ -434,8 +388,7 @@ class CustomWatchface : BaseWatchFace() {
DAY("day", R.id.day, null),
MONTH("month", R.id.month, null),
LOOP("loop", R.id.loop, R.string.key_show_external_status),
DIRECTION("direction", R.id.direction, R.string.key_show_direction),
DIRECTION2("direction2", R.id.direction2, R.string.key_show_direction),
DIRECTION("direction", R.id.direction2, R.string.key_show_direction),
TIMESTAMP("timestamp", R.id.timestamp, R.string.key_show_ago),
SGV("sgv", R.id.sgv, R.string.key_show_bg),
COVER_PLATE(CustomWatchfaceDrawableDataKey.COVERPLATE.key, R.id.cover_plate, null),
@ -445,50 +398,74 @@ class CustomWatchface : BaseWatchFace() {
companion object {
private val keyToEnumMap = HashMap<String, CustomViews>()
private val idToEnumMap = HashMap<Int, CustomViews>()
init {
for (value in values()) keyToEnumMap[value.key] = value
for (value in values()) idToEnumMap[value.id] = value
}
fun fromKey(key: String): CustomViews? =
if (keyToEnumMap.containsKey(key)) {
keyToEnumMap[key]
} else {
null
}
fun fromId(id: Int): CustomViews? =
if (idToEnumMap.containsKey(id)) {
idToEnumMap[id]
} else {
null
}
fun fromKey(key: String): CustomViews? = values().firstOrNull { it.key == key }
fun fromId(id: Int): CustomViews? = values().firstOrNull { it.id == id }
}
fun visibility(sp: SP): Boolean = this.pref?.let { sp.getBoolean(it, true) }
?: true
}
enum class TrendArrow(val text: String, val symbol: String,@DrawableRes val icon: Int) {
private enum class TrendArrow(val text: String, val symbol: String, @DrawableRes val icon: Int) {
NONE("NONE", "??", R.drawable.ic_invalid),
TRIPLE_UP("TripleUp", "X", R.drawable.ic_invalid),
TRIPLE_UP("TripleUp", "X", R.drawable.ic_doubleup),
DOUBLE_UP("DoubleUp", "\u21c8", R.drawable.ic_doubleup),
SINGLE_UP("SingleUp", "\u2191", R.drawable.ic_singleup),
FORTY_FIVE_UP("FortyFiveUp", "\u2197", R.drawable.ic_fortyfiveup),
FLAT("Flat", "\u2192", R.drawable.ic_flat),
FORTY_FIVE_DOWN("FortyFiveDown", "\u2198",R.drawable.ic_fortyfivedown),
FORTY_FIVE_DOWN("FortyFiveDown", "\u2198", R.drawable.ic_fortyfivedown),
SINGLE_DOWN("SingleDown", "\u2193", R.drawable.ic_singledown),
DOUBLE_DOWN("DoubleDown", "\u21ca", R.drawable.ic_doubledown),
TRIPLE_DOWN("TripleDown", "X",R.drawable.ic_invalid)
TRIPLE_DOWN("TripleDown", "X", R.drawable.ic_doubledown)
;
companion object {
fun fromSymbol(direction: String?) =
values().firstOrNull { it.symbol == direction } ?: NONE
fun icon(direction: String?) = values().firstOrNull { it.symbol == direction }?.icon ?: NONE.icon
}
}
private enum class GravityMap(val key: String, val gravity: Int) {
CENTER("center", Gravity.CENTER),
LEFT("left", Gravity.LEFT),
RIGHT("right", Gravity.RIGHT);
companion object {
fun gravity(key: String?) = values().firstOrNull { it.key == key }?.gravity ?: CENTER.gravity
fun key(gravity: Int) = values().firstOrNull { it.gravity == gravity }?.key ?: CENTER.key
}
}
private enum class FontMap(val key: String, var font: Typeface, @FontRes val fontRessources: Int?) {
SANS_SERIF("sans-serif", Typeface.SANS_SERIF, null),
DEFAULT("default", Typeface.DEFAULT, null),
DEFAULT_BOLD("default-bold", Typeface.DEFAULT_BOLD, null),
MONOSPACE("monospace", Typeface.MONOSPACE, null),
SERIF("serif", Typeface.SERIF, null),
ROBOTO_CONDENSED_BOLD("roboto-condensed-bold", Typeface.DEFAULT, R.font.roboto_condensed_bold),
ROBOTO_CONDENSED_LIGHT("roboto-condensed-light", Typeface.DEFAULT, R.font.roboto_condensed_light),
ROBOTO_CONDENSED_REGULAR("roboto-condensed-regular", Typeface.DEFAULT, R.font.roboto_condensed_regular),
ROBOTO_SLAB_LIGHT("roboto-slab-light", Typeface.DEFAULT, R.font.roboto_slab_light);
companion object {
fun init(context: Context) = values().forEach { it.font = it.fontRessources?.let { font -> ResourcesCompat.getFont(context, font) } ?: it.font }
fun font(key: String) = values().firstOrNull { it.key == key }?.font ?: DEFAULT.font
fun key() = DEFAULT.key
}
}
private enum class StyleMap(val key: String, val style: Int) {
NORMAL("normal", Typeface.NORMAL),
BOLD("bold", Typeface.BOLD),
BOLD_ITALIC("bold-italic", Typeface.BOLD_ITALIC),
ITALIC("italic", Typeface.ITALIC);
companion object {
fun style(key: String?) = values().firstOrNull { it.key == key }?.style ?: NORMAL.style
fun key(style: Int) = values().firstOrNull { it.style == style }?.key ?: NORMAL.key
}
}

View file

@ -47,7 +47,7 @@ class WatchfaceViewAdapter(
// Optional attributes
val sgv = aL?.sgv ?: a2?.sgv ?: aa?.sgv ?: bC?.sgv ?: bC?.sgv ?: cp?.sgv ?: ds?.sgv ?: nC?.sgv ?: cU?.sgv
val direction = aL?.direction ?: a2?.direction ?: aa?.direction ?: cp?.direction ?: ds?.direction ?: cU?.direction
val direction = aL?.direction ?: a2?.direction ?: aa?.direction ?: cp?.direction ?: ds?.direction
val loop = a2?.loop ?: cp?.loop ?: sP?.loop ?: cU?.loop
val delta = aL?.delta ?: a2?.delta ?: aa?.delta ?: bC?.delta ?: bC?.delta ?: cp?.delta ?: ds?.delta ?: nC?.delta ?: cU?.delta
val avgDelta = a2?.avgDelta ?: bC?.avgDelta ?: bC?.avgDelta ?: cp?.avgDelta ?: ds?.avgDelta ?: nC?.avgDelta ?: cU?.avgDelta

View file

@ -3,10 +3,11 @@
android:height="48dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M2.702,16.281c1.952,1.81 4.279,4.076 5.31,5.654v0.002c0,0 0.001,-0.001 0.001,-0.001c0,0 0.001,0.001 0.001,0.001v-0.002c1.032,-1.578 3.359,-3.844 5.31,-5.654l-1.325,-1.821c0,0 -1.578,1.408 -2.934,2.728V2.063H6.961l0,15.125c-1.356,-1.319 -2.934,-2.728 -2.934,-2.728L2.702,16.281z"
android:fillColor="@color/white"/>
<path
android:pathData="M10.676,16.281c1.952,1.81 4.279,4.076 5.31,5.654v0.002c0,0 0.001,-0.001 0.001,-0.001c0,0 0.001,0.001 0.001,0.001v-0.002c1.032,-1.578 3.359,-3.844 5.31,-5.654l-1.325,-1.821c0,0 -1.578,1.408 -2.934,2.728V2.063h-2.104v15.125c-1.356,-1.319 -2.934,-2.728 -2.934,-2.728L10.676,16.281z"
android:fillColor="@color/white"/>
<path
android:fillColor="@color/white"
android:pathData="M0.772,17.17c2.357,2.186 5.167,4.922 6.413,6.828V24c0,0 0.001,-0.001 0.001,-0.001c0,0 0.001,0.001 0.001,0.001v-0.003c1.246,-1.906 4.056,-4.642 6.413,-6.828l-1.6,-2.199c0,0 -1.905,1.7 -3.543,3.294V0l-2.54,0v18.264c-1.638,-1.593 -3.543,-3.294 -3.543,-3.294L0.772,17.17z" />
<path
android:fillColor="@color/white"
android:pathData="M10.401,17.17c2.357,2.186 5.167,4.922 6.413,6.828V24c0,0 0.001,-0.001 0.001,-0.001c0,0 0.001,0.001 0.001,0.001v-0.003c1.246,-1.906 4.056,-4.642 6.413,-6.828l-1.6,-2.199c0,0 -1.905,1.7 -3.543,3.294V0l-2.54,0v18.264c-1.638,-1.593 -3.543,-3.294 -3.543,-3.294L10.401,17.17z" />
</vector>

View file

@ -3,10 +3,11 @@
android:height="48dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M2.702,7.719c1.952,-1.81 4.279,-4.076 5.31,-5.654V2.063c0,0 0.001,0.001 0.001,0.001c0,0 0.001,-0.001 0.001,-0.001v0.002c1.032,1.578 3.359,3.844 5.31,5.654L11.999,9.54c0,0 -1.578,-1.408 -2.934,-2.728v15.125H6.961l0,-15.125C5.605,8.132 4.027,9.54 4.027,9.54L2.702,7.719z"
android:fillColor="@color/white"/>
<path
android:pathData="M10.676,7.719c1.952,-1.81 4.279,-4.076 5.31,-5.654V2.063c0,0 0.001,0.001 0.001,0.001c0,0 0.001,-0.001 0.001,-0.001v0.002c1.032,1.578 3.359,3.844 5.31,5.654L19.973,9.54c0,0 -1.578,-1.408 -2.934,-2.728v15.125h-2.104V6.813c-1.356,1.319 -2.934,2.728 -2.934,2.728L10.676,7.719z"
android:fillColor="@color/white"/>
<path
android:fillColor="@color/white"
android:pathData="M0.772,6.83c2.357,-2.186 5.167,-4.922 6.413,-6.828V0c0,0 0.001,0.001 0.001,0.001c0,0 0.001,-0.001 0.001,-0.001v0.003c1.246,1.906 4.056,4.642 6.413,6.828l-1.6,2.199c0,0 -1.905,-1.7 -3.543,-3.294V24h-2.54V5.736C4.278,7.329 2.373,9.03 2.373,9.03L0.772,6.83z" />
<path
android:fillColor="@color/white"
android:pathData="M10.401,6.83c2.357,-2.186 5.167,-4.922 6.413,-6.828V0c0,0 0.001,0.001 0.001,0.001c0,0 0.001,-0.001 0.001,-0.001v0.003c1.246,1.906 4.056,4.642 6.413,6.828l-1.6,2.199c0,0 -1.905,-1.7 -3.543,-3.294V24h-2.54V5.736c-1.638,1.593 -3.543,3.294 -3.543,3.294L10.401,6.83z" />
</vector>

View file

@ -3,7 +3,9 @@
android:height="48dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M16.281,17.311c1.81,-1.952 4.076,-4.279 5.654,-5.31h0.002c0,0 -0.001,-0.001 -0.001,-0.001c0,0 0.001,-0.001 0.001,-0.001h-0.002c-1.578,-1.032 -3.844,-3.359 -5.654,-5.31L14.46,8.014c0,0 1.408,1.578 2.728,2.934H2.063v2.104h15.125c-1.319,1.356 -2.728,2.934 -2.728,2.934L16.281,17.311z"
android:fillColor="@color/white"/>
<path
android:fillColor="@color/white"
android:pathData="M17.17,18.413c2.186,-2.357 4.922,-5.167 6.828,-6.413H24c0,0 -0.001,-0.001 -0.001,-0.001c0,0 0.001,-0.001 0.001,-0.001h-0.003c-1.906,-1.246 -4.642,-4.056 -6.828,-6.413l-2.199,1.6c0,0 1.7,1.905 3.294,3.543H0l0,2.54h18.264c-1.593,1.638 -3.294,3.543 -3.294,3.543L17.17,18.413z" />
</vector>

View file

@ -3,7 +3,9 @@
android:height="48dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M11.272,18.783c2.66,-0.1 5.908,-0.143 7.753,0.243l0.001,0.001c0,0 0,-0.001 0,-0.001c0,0 0.001,0 0.001,0l-0.001,-0.001c-0.386,-1.845 -0.343,-5.093 -0.243,-7.753l-2.225,-0.351c0,0 -0.12,2.111 -0.146,4.003L5.717,4.229L4.229,5.717l10.695,10.695c-1.892,0.026 -4.003,0.146 -4.003,0.146L11.272,18.783z"
android:fillColor="@color/white"/>
<path
android:fillColor="@color/white"
android:pathData="M11.121,20.191c3.212,-0.121 7.134,-0.173 9.362,0.294l0.002,0.002l0,-0.002l0.002,0l-0.002,-0.002c-0.466,-2.229 -0.414,-6.15 -0.294,-9.362l-2.687,-0.424c0,0 -0.145,2.55 -0.176,4.834L4.413,2.617L2.617,4.413l12.915,12.915c-2.285,0.031 -4.834,0.176 -4.834,0.176L11.121,20.191z" />
</vector>

View file

@ -3,7 +3,7 @@
android:height="48dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M18.783,12.728c-0.1,-2.66 -0.143,-5.908 0.243,-7.753l0.001,-0.001c0,0 -0.001,0 -0.001,0c0,0 0,-0.001 0,-0.001l-0.001,0.001c-1.845,0.386 -5.093,0.343 -7.753,0.243l-0.351,2.225c0,0 2.111,0.12 4.003,0.146L4.229,18.283l1.488,1.488L16.412,9.076c0.026,1.892 0.146,4.003 0.146,4.003L18.783,12.728z"
android:fillColor="@color/white"/>
<path
android:fillColor="@color/white"
android:pathData="M20.191,12.879c-0.121,-3.212 -0.173,-7.134 0.294,-9.362l0.002,-0.002l-0.002,0l0,-0.002l-0.002,0.002c-2.229,0.466 -6.15,0.414 -9.362,0.294l-0.424,2.687c0,0 2.55,0.145 4.834,0.176L2.617,19.587l1.796,1.796L17.328,8.469c0.031,2.285 0.176,4.834 0.176,4.834L20.191,12.879z" />
</vector>

View file

@ -3,16 +3,19 @@
android:height="48dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M17.35,19.561m-1.147,0a1.147,1.147 0,1 1,2.294 0a1.147,1.147 0,1 1,-2.294 0"
android:fillColor="@color/white"/>
<path
android:pathData="M17.301,16.804c-0.459,0 -0.83,-0.372 -0.83,-0.831c0,-2.985 1.391,-4.027 2.51,-4.864c0.937,-0.702 1.614,-1.209 1.614,-2.849c0,-2.262 -2.173,-2.965 -2.964,-2.965c-1.705,0 -3.083,1.022 -3.778,2.804c-0.167,0.427 -0.65,0.64 -1.075,0.471c-0.427,-0.167 -0.638,-0.648 -0.471,-1.075c0.944,-2.417 2.935,-3.86 5.325,-3.86c1.865,0 4.626,1.47 4.626,4.626c0,2.472 -1.264,3.418 -2.28,4.178c-1.031,0.772 -1.844,1.38 -1.844,3.535C18.131,16.432 17.76,16.804 17.301,16.804z"
android:fillColor="@color/white"/>
<path
android:pathData="M6.846,19.561m-1.147,0a1.147,1.147 0,1 1,2.294 0a1.147,1.147 0,1 1,-2.294 0"
android:fillColor="@color/white"/>
<path
android:pathData="M6.797,16.804c-0.459,0 -0.83,-0.372 -0.83,-0.831c0,-2.985 1.391,-4.027 2.51,-4.864c0.937,-0.702 1.614,-1.209 1.614,-2.849c0,-2.262 -2.173,-2.965 -2.964,-2.965c-1.705,0 -3.083,1.022 -3.778,2.804c-0.167,0.427 -0.65,0.64 -1.075,0.471C1.845,8.403 1.635,7.922 1.801,7.495c0.944,-2.417 2.935,-3.86 5.325,-3.86c1.865,0 4.626,1.47 4.626,4.626c0,2.472 -1.264,3.418 -2.28,4.178c-1.031,0.772 -1.844,1.38 -1.844,3.535C7.627,16.432 7.256,16.804 6.797,16.804z"
android:fillColor="@color/white"/>
<path
android:fillColor="@color/white"
android:pathData="M17.991,20.275m-1.285,0a1.285,1.285 0,1 1,2.57 0a1.285,1.285 0,1 1,-2.57 0" />
<path
android:fillColor="@color/white"
android:pathData="M17.936,17.188c-0.514,0 -0.93,-0.416 -0.93,-0.93c0,-3.343 1.558,-4.509 2.81,-5.446c1.049,-0.786 1.808,-1.354 1.808,-3.191c0,-2.534 -2.433,-3.321 -3.32,-3.321c-1.91,0 -3.452,1.145 -4.231,3.14c-0.187,0.479 -0.728,0.716 -1.204,0.528c-0.479,-0.187 -0.714,-0.726 -0.528,-1.204c1.057,-2.707 3.286,-4.322 5.963,-4.322c2.088,0 5.18,1.646 5.18,5.18c0,2.768 -1.416,3.828 -2.553,4.679c-1.154,0.864 -2.065,1.546 -2.065,3.958C18.866,16.771 18.45,17.188 17.936,17.188z" />
<path
android:fillColor="@color/white"
android:pathData="M6.228,20.275m-1.285,0a1.285,1.285 0,1 1,2.57 0a1.285,1.285 0,1 1,-2.57 0" />
<path
android:fillColor="@color/white"
android:pathData="M6.173,17.188c-0.514,0 -0.93,-0.416 -0.93,-0.93c0,-3.343 1.558,-4.509 2.81,-5.446c1.049,-0.786 1.808,-1.354 1.808,-3.191c0,-2.534 -2.433,-3.321 -3.32,-3.321c-1.91,0 -3.452,1.145 -4.231,3.14C2.124,7.918 1.583,8.155 1.107,7.967C0.628,7.78 0.392,7.241 0.579,6.763C1.636,4.056 3.865,2.44 6.542,2.44c2.088,0 5.18,1.646 5.18,5.18c0,2.768 -1.416,3.828 -2.553,4.679c-1.154,0.864 -2.065,1.546 -2.065,3.958C7.103,16.771 6.687,17.188 6.173,17.188z" />
</vector>

View file

@ -3,7 +3,8 @@
android:height="48dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M6.689,16.281c1.952,1.81 4.279,4.076 5.31,5.654v0.002c0,0 0.001,-0.001 0.001,-0.001c0,0 0.001,0.001 0.001,0.001v-0.002c1.032,-1.578 3.359,-3.844 5.31,-5.654l-1.325,-1.821c0,0 -1.578,1.408 -2.934,2.728V2.063h-2.104v15.125c-1.356,-1.319 -2.934,-2.728 -2.934,-2.728L6.689,16.281z"
android:fillColor="@color/white"/>
<path
android:fillColor="@color/white"
android:pathData="M5.587,17.17c2.357,2.186 5.167,4.922 6.413,6.828V24c0,0 0.001,-0.001 0.001,-0.001c0,0 0.001,0.001 0.001,0.001v-0.003c1.246,-1.906 4.056,-4.642 6.413,-6.828l-1.6,-2.199c0,0 -1.905,1.7 -3.543,3.294V0l-2.54,0v18.264c-1.638,-1.593 -3.543,-3.294 -3.543,-3.294L5.587,17.17z" />
</vector>

View file

@ -3,7 +3,7 @@
android:height="48dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M17.102,7.719c-1.952,-1.81 -4.279,-4.076 -5.31,-5.654V2.063c0,0 -0.001,0.001 -0.001,0.001c0,0 -0.001,-0.001 -0.001,-0.001v0.002c-1.032,1.578 -3.359,3.844 -5.31,5.654L7.805,9.54c0,0 1.578,-1.408 2.934,-2.728v15.125h2.104V6.813c1.356,1.319 2.934,2.728 2.934,2.728L17.102,7.719z"
android:fillColor="@color/white"/>
<path
android:fillColor="@color/white"
android:pathData="M18.16,6.83c-2.357,-2.186 -5.167,-4.922 -6.413,-6.828V0c0,0 -0.001,0.001 -0.001,0.001c0,0 -0.001,-0.001 -0.001,-0.001l0,0.002C10.5,1.908 7.69,4.644 5.333,6.83l1.6,2.199c0,0 1.905,-1.7 3.543,-3.294V24h2.54V5.736C14.655,7.329 16.56,9.03 16.56,9.03L18.16,6.83z" />
</vector>

View file

@ -300,27 +300,14 @@
android:textColor="@color/light_grey"
tools:text="--'" />
<TextView
android:id="@+id/direction"
android:layout_width="52px"
android:layout_height="52px"
android:layout_marginTop="26px"
android:layout_marginLeft="291px"
android:visibility="gone"
android:gravity="left"
android:textSize="39px"
android:textStyle="bold"
android:textColor="@color/light_grey"
tools:text="--" />
<ImageView
android:id="@+id/direction2"
android:layout_width="52px"
android:layout_height="52px"
android:layout_marginTop="26px"
android:layout_width="40px"
android:layout_height="40px"
android:layout_marginTop="36px"
android:layout_marginLeft="291px"
android:visibility="visible"
android:src="@drawable/ic_flat"
android:src="@drawable/ic_invalid"
android:orientation="vertical" />
<TextView