Wear: Watchfaces -> kt

This commit is contained in:
Milos Kozak 2022-04-24 17:20:29 +02:00
parent ec5a09bdb0
commit 9a78a4cf9f
53 changed files with 2733 additions and 3211 deletions

View file

@ -53,7 +53,6 @@ import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.exceptions.UndeliverableException
import io.reactivex.rxjava3.kotlin.plusAssign
import io.reactivex.rxjava3.plugins.RxJavaPlugins
import net.danlew.android.joda.JodaTimeAndroid
import java.io.IOException
import java.net.SocketException
import java.util.concurrent.TimeUnit
@ -102,7 +101,6 @@ class MainApp : DaggerApplication() {
}
disposable += compatDBHelper.dbChangeDisposable()
registerActivityLifecycleCallbacks(activityMonitor)
JodaTimeAndroid.init(this)
profileSwitchPlugin.setThemeMode()
aapsLogger.debug("Version: " + BuildConfig.VERSION_NAME)
aapsLogger.debug("BuildVersion: " + BuildConfig.BUILDVERSION)

View file

@ -19,12 +19,13 @@ buildscript {
material_version = '1.4.0'
constraintlayout_version = '2.1.0'
preferencektx_version = '1.2.0'
commonslang3_version = '3.11'
commonslang3_version = '3.12.0'
commonscodec_version = '1.15'
jodatime_version = '2.10.14'
work_version = '2.5.0'
tink_version = '1.5.0'
json_version = '20220320'
joga_version = '2.10.14'
junit_version = '4.13.2'
mockito_version = '4.4.0'

View file

@ -75,7 +75,6 @@ dependencies {
api "com.squareup.retrofit2:converter-gson:$retrofit2_version"
api "com.joanzapata.iconify:android-iconify-fontawesome:2.2.2"
api 'net.danlew:android.joda:2.10.6'
api "androidx.fragment:fragment-ktx:$fragmentktx_version"
api "androidx.constraintlayout:constraintlayout:$constraintlayout_version"

View file

@ -18,7 +18,7 @@ android {
dependencies {
api "androidx.preference:preference-ktx:$preferencektx_version"
api 'net.danlew:android.joda:2.10.6'
api "net.danlew:android.joda:$joga_version"
// for old fashioned support-app version (wear)
api "com.google.dagger:dagger:$dagger_version"

View file

@ -136,6 +136,7 @@ class DateUtil @Inject constructor(private val context: Context) {
return DateTime(mills).toString(DateTimeFormat.forPattern(format))
}
fun timeString(): String = timeString(now())
fun timeString(mills: Long): String {
var format = "hh:mma"
if (android.text.format.DateFormat.is24HourFormat(context)) {
@ -144,6 +145,11 @@ class DateUtil @Inject constructor(private val context: Context) {
return DateTime(mills).toString(DateTimeFormat.forPattern(format))
}
fun minuteString(): String = minuteString(now())
fun minuteString(mills: Long): String =
DateTime(mills).toString(DateTimeFormat.forPattern("mm"))
fun hourString(): String = hourString(now())
fun hourString(mills: Long): String {
var format = "hha"
if (android.text.format.DateFormat.is24HourFormat(context)) {
@ -152,6 +158,22 @@ class DateUtil @Inject constructor(private val context: Context) {
return DateTime(mills).toString(DateTimeFormat.forPattern(format))
}
fun dayNameString(): String = minuteString(now())
fun dayNameString(mills: Long): String =
DateTime(mills).toString(DateTimeFormat.forPattern("E"))
fun dayString(): String = minuteString(now())
fun dayString(mills: Long): String =
DateTime(mills).toString(DateTimeFormat.forPattern("dd"))
fun monthString(): String = monthString(now())
fun monthString(mills: Long): String =
DateTime(mills).toString(DateTimeFormat.forPattern("MMM"))
fun weekString(): String = weekString(now())
fun weekString(mills: Long): String =
DateTime(mills).toString(DateTimeFormat.forPattern("ww"))
fun timeStringWithSeconds(mills: Long): String {
var format = "hh:mm:ssa"
if (android.text.format.DateFormat.is24HourFormat(context)) {

View file

@ -27,9 +27,9 @@
android:value="@integer/google_play_services_version" />
<service
android:name=".watchfaces.BIGChart"
android:name=".watchfaces.BigChartWatchface"
android:allowEmbedded="true"
android:label="@string/label_xdrip_big_chart"
android:label="@string/label_watchface_big_chart"
android:permission="android.permission.BIND_WALLPAPER"
android:exported="false">
<meta-data
@ -49,9 +49,9 @@
</service>
<service
android:name=".watchfaces.NOChart"
android:name=".watchfaces.NoChartWatchface"
android:allowEmbedded="true"
android:label="@string/label_xdrip_no_chart"
android:label="@string/label_watchface_no_chart"
android:permission="android.permission.BIND_WALLPAPER"
android:exported="false">
<meta-data
@ -71,9 +71,9 @@
</service>
<service
android:name=".watchfaces.Home"
android:name=".watchfaces.AapsWatchface"
android:allowEmbedded="true"
android:label="@string/label_xdrip"
android:label="@string/label_watchface"
android:permission="android.permission.BIND_WALLPAPER"
android:exported="false">
<meta-data
@ -96,9 +96,9 @@
</service>
<service
android:name=".watchfaces.Home2"
android:name=".watchfaces.AapsV2Watchface"
android:allowEmbedded="true"
android:label="@string/label_xdrip_v2"
android:label="@string/label_watchface_v2"
android:permission="android.permission.BIND_WALLPAPER"
android:exported="false">
<meta-data
@ -121,9 +121,9 @@
</service>
<service
android:name=".watchfaces.Cockpit"
android:name=".watchfaces.CockpitWatchface"
android:allowEmbedded="true"
android:label="@string/label_xdrip_cockpit"
android:label="@string/label_watchface_cockpit"
android:permission="android.permission.BIND_WALLPAPER"
android:exported="false">
<meta-data
@ -148,7 +148,7 @@
<service
android:name=".watchfaces.SteampunkWatchface"
android:allowEmbedded="true"
android:label="@string/label_xdrip_steampunk"
android:label="@string/label_watchface_steampunk"
android:permission="android.permission.BIND_WALLPAPER"
android:exported="false">
<meta-data
@ -171,9 +171,9 @@
</service>
<service
android:name=".watchfaces.LargeHome"
android:name=".watchfaces.AapsLargeWatchface"
android:allowEmbedded="true"
android:label="@string/label_xdrip_large"
android:label="@string/label_watchface_large"
android:permission="android.permission.BIND_WALLPAPER"
android:exported="false">
<meta-data
@ -197,7 +197,7 @@
<service
android:name=".watchfaces.CircleWatchface"
android:allowEmbedded="true"
android:label="@string/label_xdrip_circle"
android:label="@string/label_watchface_circle"
android:permission="android.permission.BIND_WALLPAPER"
android:exported="false">
<meta-data
@ -217,9 +217,9 @@
</service>
<service
android:name=".watchfaces.DigitalStyle"
android:name=".watchfaces.DigitalStyleWatchface"
android:allowEmbedded="true"
android:label="@string/label_digitalstyle"
android:label="@string/label_watchface_digital_style"
android:permission="android.permission.BIND_WALLPAPER"
android:exported="false">
<meta-data

View file

@ -28,15 +28,15 @@ abstract class WearServicesModule {
@ContributesAndroidInjector abstract fun contributesWallpaperComplication(): WallpaperComplication
@ContributesAndroidInjector abstract fun contributesBaseWatchFace(): BaseWatchFace
@ContributesAndroidInjector abstract fun contributesHome(): Home
@ContributesAndroidInjector abstract fun contributesHome2(): Home2
@ContributesAndroidInjector abstract fun contributesLargeHome(): LargeHome
@ContributesAndroidInjector abstract fun contributesAapsWatchface(): AapsWatchface
@ContributesAndroidInjector abstract fun contributesAapsV2Watchface(): AapsV2Watchface
@ContributesAndroidInjector abstract fun contributesAapsLargeWatchface(): AapsLargeWatchface
@ContributesAndroidInjector abstract fun contributesSteampunk(): SteampunkWatchface
@ContributesAndroidInjector abstract fun contributesDigitalStyle(): DigitalStyle
@ContributesAndroidInjector abstract fun contributesCockpit(): Cockpit
@ContributesAndroidInjector abstract fun contributesDigitalStyleWatchface(): DigitalStyleWatchface
@ContributesAndroidInjector abstract fun contributesCockpitWatchface(): CockpitWatchface
@ContributesAndroidInjector abstract fun contributesBIGChart(): BIGChart
@ContributesAndroidInjector abstract fun contributesNOChart(): NOChart
@ContributesAndroidInjector abstract fun contributesBIGChart(): BigChartWatchface
@ContributesAndroidInjector abstract fun contributesNOChart(): NoChartWatchface
@ContributesAndroidInjector abstract fun contributesCircleWatchface(): CircleWatchface
@ContributesAndroidInjector abstract fun contributesTileBase(): TileBase

View file

@ -42,9 +42,9 @@ class AcceptActivity : ViewSelectorActivity() {
return
}
setAdapter(MyGridViewPagerAdapter())
val v = getSystemService(VIBRATOR_SERVICE) as Vibrator
val vibrator = getSystemService(VIBRATOR_SERVICE) as Vibrator
val vibratePattern = longArrayOf(0, 100, 50, 100, 50)
v.vibrate(vibratePattern, -1)
vibrator.vibrate(vibratePattern, -1)
}
override fun onPause() {

View file

@ -8,6 +8,7 @@ import javax.inject.Inject;
import javax.inject.Singleton;
import info.nightscout.androidaps.BuildConfig;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.shared.logging.AAPSLogger;
import info.nightscout.shared.logging.LTag;
@ -25,6 +26,7 @@ public class Inevitable {
@Inject WearUtil wearUtil;
@Inject AAPSLogger aapsLogger;
@Inject DateUtil dateUtil;
@Inject Inevitable() {}
@ -43,14 +45,15 @@ public class Inevitable {
task.extendTime(idle_for);
if (debug)
aapsLogger.debug(LTag.WEAR, "Extending time for: " + id + " to " + wearUtil.dateTimeText(task.when));
aapsLogger.debug(LTag.WEAR, "Extending time for: " + id + " to " + dateUtil.dateAndTimeAndSecondsString(task.when));
} else {
// otherwise create new task
if (runnable == null) return; // extension only if already exists
tasks.put(id, new Task(id, idle_for, runnable));
if (debug) {
aapsLogger.debug(LTag.WEAR, "Creating task: " + id + " due: " + wearUtil.dateTimeText(tasks.get(id).when));
aapsLogger.debug(LTag.WEAR,
"Creating task: " + id + " due: " + dateUtil.dateAndTimeAndSecondsString(tasks.get(id).when));
}
// create a thread to wait and execute in background
@ -73,25 +76,10 @@ public class Inevitable {
}
}
public void stackableTask(String id, long idle_for, Runnable runnable) {
int stack = 0;
while (tasks.get(id = id + "-" + stack) != null) {
stack++;
}
if (stack > 0) {
aapsLogger.debug(LTag.WEAR, "Task stacked to: " + id);
}
task(id, idle_for, runnable);
}
public void kill(final String id) {
tasks.remove(id);
}
public boolean waiting(final String id) {
return tasks.containsKey(id);
}
private class Task {
private long when;
private final Runnable what;

View file

@ -38,11 +38,6 @@ public class WearUtil {
// Time related util methods
//==============================================================================================
public String dateTimeText(long timeInMs) {
Date d = new Date(timeInMs);
return "" + d.getDay() + "." + d.getMonth() + "." + d.getYear() + " " + d.getHours() + ":" + d.getMinutes() + ":" + d.getSeconds();
}
public long timestamp() {
return System.currentTimeMillis();
}

View file

@ -0,0 +1,148 @@
@file:Suppress("DEPRECATION")
package info.nightscout.androidaps.watchfaces
import android.annotation.SuppressLint
import android.content.Intent
import android.graphics.Color
import android.support.wearable.watchface.WatchFaceStyle
import android.view.LayoutInflater
import androidx.core.content.ContextCompat
import com.ustwo.clockwise.common.WatchMode
import info.nightscout.androidaps.R
import info.nightscout.androidaps.interaction.menus.MainMenuActivity
class AapsLargeWatchface : BaseWatchFace() {
private var sgvTapTime: Long = 0
@SuppressLint("InflateParams")
override fun onCreate() {
super.onCreate()
val inflater = getSystemService(LAYOUT_INFLATER_SERVICE) as LayoutInflater
layoutView = inflater.inflate(R.layout.activity_home_large, null)
performViewSetup()
}
override fun onTapCommand(tapType: Int, x: Int, y: Int, eventTime: Long) {
mSgv?.let { mSgv ->
val extra = (mSgv.right - mSgv.left) / 2
if (tapType == TAP_TYPE_TAP && x + extra >= mSgv.left && x - extra <= mSgv.right && y >= mSgv.top && y <= mSgv.bottom) {
if (eventTime - sgvTapTime < 800) {
val intent = Intent(this, MainMenuActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
}
sgvTapTime = eventTime
}
}
}
override fun getWatchFaceStyle(): WatchFaceStyle {
return WatchFaceStyle.Builder(this).setAcceptsTapEvents(true).build()
}
override fun setColorDark() {
mLinearLayout?.setBackgroundColor(ContextCompat.getColor(this, if (dividerMatchesBg) R.color.dark_background else R.color.dark_mLinearLayout))
mTime?.setTextColor(ContextCompat.getColor(this, R.color.dark_mTime))
mRelativeLayout?.setBackgroundColor(ContextCompat.getColor(this, R.color.dark_background))
when (singleBg.sgvLevel) {
1L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor))
mDelta?.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor))
mDirection?.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor))
}
0L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mDelta?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mDirection?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
}
-1L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor))
mDelta?.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor))
mDirection?.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor))
}
}
if (ageLevel == 1) mTimestamp?.setTextColor(ContextCompat.getColor(this, if (dividerMatchesBg) R.color.dark_midColor else R.color.dark_mTimestamp1_home))
else mTimestamp?.setTextColor(ContextCompat.getColor(this, R.color.dark_TimestampOld))
if (status.batteryLevel == 1) mUploaderBattery?.setTextColor(ContextCompat.getColor(this, if (dividerMatchesBg) R.color.dark_midColor else R.color.dark_uploaderBattery))
else mUploaderBattery?.setTextColor(ContextCompat.getColor(this, R.color.dark_uploaderBatteryEmpty))
mStatus?.setTextColor(ContextCompat.getColor(this, if (dividerMatchesBg) R.color.dark_midColor else R.color.dark_mStatus_home))
}
override fun setColorBright() {
if (currentWatchMode == WatchMode.INTERACTIVE) {
mLinearLayout?.setBackgroundColor(ContextCompat.getColor(this, if (dividerMatchesBg) R.color.light_background else R.color.light_stripe_background))
mRelativeLayout?.setBackgroundColor(ContextCompat.getColor(this, R.color.light_background))
when (singleBg.sgvLevel) {
1L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.light_highColor))
mDelta?.setTextColor(ContextCompat.getColor(this, R.color.light_highColor))
mDirection?.setTextColor(ContextCompat.getColor(this, R.color.light_highColor))
}
0L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.light_midColor))
mDelta?.setTextColor(ContextCompat.getColor(this, R.color.light_midColor))
mDirection?.setTextColor(ContextCompat.getColor(this, R.color.light_midColor))
}
-1L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.light_lowColor))
mDelta?.setTextColor(ContextCompat.getColor(this, R.color.light_lowColor))
mDirection?.setTextColor(ContextCompat.getColor(this, R.color.light_lowColor))
}
}
if (ageLevel == 1) mTimestamp?.setTextColor(if (dividerMatchesBg) Color.BLACK else Color.WHITE)
else mTimestamp?.setTextColor(Color.RED)
if (status.batteryLevel == 1) mUploaderBattery?.setTextColor(if (dividerMatchesBg) Color.BLACK else Color.WHITE)
else mUploaderBattery?.setTextColor(Color.RED)
mStatus?.setTextColor(if (dividerMatchesBg) Color.BLACK else Color.WHITE)
mTime?.setTextColor(Color.BLACK)
} else {
mRelativeLayout?.setBackgroundColor(Color.BLACK)
mLinearLayout?.setBackgroundColor(if (dividerMatchesBg) Color.BLACK else Color.LTGRAY)
when (singleBg.sgvLevel) {
1L -> {
mSgv?.setTextColor(Color.YELLOW)
mDirection?.setTextColor(Color.YELLOW)
mDelta?.setTextColor(Color.YELLOW)
}
0L -> {
mSgv?.setTextColor(Color.WHITE)
mDirection?.setTextColor(Color.WHITE)
mDelta?.setTextColor(Color.WHITE)
}
-1L -> {
mSgv?.setTextColor(Color.RED)
mDirection?.setTextColor(Color.RED)
mDelta?.setTextColor(Color.RED)
}
}
mUploaderBattery?.setTextColor(if (dividerMatchesBg) Color.WHITE else Color.BLACK)
mTimestamp?.setTextColor(if (dividerMatchesBg) Color.WHITE else Color.BLACK)
mStatus?.setTextColor(if (dividerMatchesBg) Color.WHITE else Color.BLACK)
mTime?.setTextColor(Color.WHITE)
}
}
override fun setColorLowRes() {
mLinearLayout?.setBackgroundColor(ContextCompat.getColor(this, if (dividerMatchesBg) R.color.dark_background else R.color.dark_mLinearLayout))
mTime?.setTextColor(ContextCompat.getColor(this, R.color.dark_mTime))
mRelativeLayout?.setBackgroundColor(ContextCompat.getColor(this, R.color.dark_background))
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mDelta?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mDirection?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mTimestamp?.setTextColor(ContextCompat.getColor(this, if (dividerMatchesBg) R.color.dark_midColor else R.color.dark_mTimestamp1_home))
mUploaderBattery?.setTextColor(ContextCompat.getColor(this, if (dividerMatchesBg) R.color.dark_midColor else R.color.dark_uploaderBattery))
mStatus?.setTextColor(ContextCompat.getColor(this, if (dividerMatchesBg) R.color.dark_midColor else R.color.dark_mStatus_home))
}
}

View file

@ -0,0 +1,235 @@
@file:Suppress("DEPRECATION")
package info.nightscout.androidaps.watchfaces
import android.annotation.SuppressLint
import android.content.Intent
import android.graphics.Color
import android.support.wearable.watchface.WatchFaceStyle
import android.view.LayoutInflater
import androidx.annotation.ColorInt
import androidx.core.content.ContextCompat
import com.ustwo.clockwise.common.WatchMode
import info.nightscout.androidaps.R
import info.nightscout.androidaps.interaction.menus.MainMenuActivity
class AapsV2Watchface : BaseWatchFace() {
private var chartTapTime: Long = 0
private var sgvTapTime: Long = 0
@SuppressLint("InflateParams")
override fun onCreate() {
super.onCreate()
val inflater = getSystemService(LAYOUT_INFLATER_SERVICE) as LayoutInflater
layoutView = inflater.inflate(R.layout.activity_home_2, null)
performViewSetup()
}
override fun onTapCommand(tapType: Int, x: Int, y: Int, eventTime: Long) {
chart?.let { chart ->
if (tapType == TAP_TYPE_TAP && x >= chart.left && x <= chart.right && y >= chart.top && y <= chart.bottom) {
if (eventTime - chartTapTime < 800) {
changeChartTimeframe()
}
chartTapTime = eventTime
return
}
}
mSgv?.let { mSgv ->
val extra = (mSgv.right - mSgv.left) / 2
if (tapType == TAP_TYPE_TAP && x + extra >= mSgv.left && x - extra <= mSgv.right && y >= mSgv.top && y <= mSgv.bottom) {
if (eventTime - sgvTapTime < 800) {
val intent = Intent(this, MainMenuActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
}
sgvTapTime = eventTime
}
}
}
private fun changeChartTimeframe() {
var timeframe = sp.getInt(R.string.key_chart_time_frame, 3)
timeframe = timeframe % 5 + 1
sp.putInt(R.string.key_chart_time_frame, timeframe)
}
override fun getWatchFaceStyle(): WatchFaceStyle {
return WatchFaceStyle.Builder(this).setAcceptsTapEvents(true).build()
}
override fun setColorDark() {
@ColorInt val dividerTxtColor = if (dividerMatchesBg) ContextCompat.getColor(this, R.color.dark_midColor) else Color.BLACK
@ColorInt val dividerBatteryOkColor = ContextCompat.getColor(this, if (dividerMatchesBg) R.color.dark_midColor else R.color.dark_uploaderBattery)
@ColorInt val dividerBgColor = ContextCompat.getColor(this, if (dividerMatchesBg) R.color.dark_background else R.color.dark_statusView)
mLinearLayout?.setBackgroundColor(dividerBgColor)
mLinearLayout2?.setBackgroundColor(ContextCompat.getColor(this, R.color.dark_background))
mRelativeLayout?.setBackgroundColor(ContextCompat.getColor(this, R.color.dark_background))
mTime?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mIOB1?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mIOB2?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mCOB1?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mCOB2?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mDay?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mMonth?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mLoop?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
setTextSizes()
when (singleBg.sgvLevel) {
1L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor))
mDirection?.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor))
}
0L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mDirection?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
}
-1L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor))
mDirection?.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor))
}
}
if (ageLevel == 1) mTimestamp?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
else mTimestamp?.setTextColor(ContextCompat.getColor(this, R.color.dark_TimestampOld))
if (status.batteryLevel == 1) mUploaderBattery?.setTextColor(dividerBatteryOkColor)
else mUploaderBattery?.setTextColor(ContextCompat.getColor(this, R.color.dark_uploaderBatteryEmpty))
mRigBattery?.setTextColor(dividerTxtColor)
mDelta?.setTextColor(dividerTxtColor)
mAvgDelta?.setTextColor(dividerTxtColor)
mBasalRate?.setTextColor(dividerTxtColor)
mBgi?.setTextColor(dividerTxtColor)
when (loopLevel) {
-1 -> mLoop?.setBackgroundResource(R.drawable.loop_grey_25)
1 -> mLoop?.setBackgroundResource(R.drawable.loop_green_25)
else -> mLoop?.setBackgroundResource(R.drawable.loop_red_25)
}
if (chart != null) {
highColor = ContextCompat.getColor(this, R.color.dark_highColor)
lowColor = ContextCompat.getColor(this, R.color.dark_lowColor)
midColor = ContextCompat.getColor(this, R.color.dark_midColor)
gridColor = ContextCompat.getColor(this, R.color.dark_gridColor)
basalBackgroundColor = ContextCompat.getColor(this, R.color.basal_dark)
basalCenterColor = ContextCompat.getColor(this, R.color.basal_light)
pointSize = 2
setupCharts()
}
}
override fun setColorLowRes() {
@ColorInt val dividerTxtColor = if (dividerMatchesBg) ContextCompat.getColor(this, R.color.dark_midColor) else Color.BLACK
@ColorInt val dividerBgColor = ContextCompat.getColor(this, if (dividerMatchesBg) R.color.dark_background else R.color.dark_statusView)
mLinearLayout?.setBackgroundColor(dividerBgColor)
mLinearLayout2?.setBackgroundColor(ContextCompat.getColor(this, R.color.dark_background))
mRelativeLayout?.setBackgroundColor(ContextCompat.getColor(this, R.color.dark_background))
mLoop?.setBackgroundResource(R.drawable.loop_grey_25)
mLoop?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mDirection?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mTimestamp?.setTextColor(ContextCompat.getColor(this, R.color.dark_Timestamp))
mDelta?.setTextColor(dividerTxtColor)
mAvgDelta?.setTextColor(dividerTxtColor)
mRigBattery?.setTextColor(dividerTxtColor)
mUploaderBattery?.setTextColor(dividerTxtColor)
mBasalRate?.setTextColor(dividerTxtColor)
mBgi?.setTextColor(dividerTxtColor)
mIOB1?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mIOB2?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mCOB1?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mCOB2?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mDay?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mMonth?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mTime?.setTextColor(ContextCompat.getColor(this, R.color.dark_mTime))
if (chart != null) {
highColor = ContextCompat.getColor(this, R.color.dark_midColor)
lowColor = ContextCompat.getColor(this, R.color.dark_midColor)
midColor = ContextCompat.getColor(this, R.color.dark_midColor)
gridColor = ContextCompat.getColor(this, R.color.dark_gridColor)
basalBackgroundColor = ContextCompat.getColor(this, R.color.basal_dark_lowres)
basalCenterColor = ContextCompat.getColor(this, R.color.basal_light_lowres)
pointSize = 2
setupCharts()
}
setTextSizes()
}
override fun setColorBright() {
if (currentWatchMode == WatchMode.INTERACTIVE) {
@ColorInt val dividerTxtColor = if (dividerMatchesBg) Color.BLACK else ContextCompat.getColor(this, R.color.dark_midColor)
@ColorInt val dividerBgColor = ContextCompat.getColor(this, if (dividerMatchesBg) R.color.light_background else R.color.light_stripe_background)
mLinearLayout?.setBackgroundColor(dividerBgColor)
mLinearLayout2?.setBackgroundColor(ContextCompat.getColor(this, R.color.light_background))
mRelativeLayout?.setBackgroundColor(ContextCompat.getColor(this, R.color.light_background))
mTime?.setTextColor(Color.BLACK)
mIOB1?.setTextColor(Color.BLACK)
mIOB2?.setTextColor(Color.BLACK)
mCOB1?.setTextColor(Color.BLACK)
mCOB2?.setTextColor(Color.BLACK)
mDay?.setTextColor(Color.BLACK)
mMonth?.setTextColor(Color.BLACK)
mLoop?.setTextColor(Color.BLACK)
setTextSizes()
when (singleBg.sgvLevel) {
1L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.light_highColor))
mDirection?.setTextColor(ContextCompat.getColor(this, R.color.light_highColor))
}
0L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.light_midColor))
mDirection?.setTextColor(ContextCompat.getColor(this, R.color.light_midColor))
}
-1L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.light_lowColor))
mDirection?.setTextColor(ContextCompat.getColor(this, R.color.light_lowColor))
}
}
if (ageLevel == 1) {
mTimestamp?.setTextColor(Color.BLACK)
} else {
mTimestamp?.setTextColor(Color.RED)
}
if (status.batteryLevel == 1) {
mUploaderBattery?.setTextColor(dividerTxtColor)
} else {
mUploaderBattery?.setTextColor(Color.RED)
}
mRigBattery?.setTextColor(dividerTxtColor)
mDelta?.setTextColor(dividerTxtColor)
mAvgDelta?.setTextColor(dividerTxtColor)
mBasalRate?.setTextColor(dividerTxtColor)
mBgi?.setTextColor(dividerTxtColor)
when (loopLevel) {
-1 -> mLoop?.setBackgroundResource(R.drawable.loop_grey_25)
1 -> mLoop?.setBackgroundResource(R.drawable.loop_green_25)
else -> mLoop?.setBackgroundResource(R.drawable.loop_red_25)
}
if (chart != null) {
highColor = ContextCompat.getColor(this, R.color.light_highColor)
lowColor = ContextCompat.getColor(this, R.color.light_lowColor)
midColor = ContextCompat.getColor(this, R.color.light_midColor)
gridColor = ContextCompat.getColor(this, R.color.light_gridColor)
basalBackgroundColor = ContextCompat.getColor(this, R.color.basal_light)
basalCenterColor = ContextCompat.getColor(this, R.color.basal_dark)
pointSize = 2
setupCharts()
}
} else {
setColorDark()
}
}
private fun setTextSizes() {
if (status.detailedIob) {
mIOB1?.textSize = 14f
mIOB2?.textSize = 10f
} else {
mIOB1?.textSize = 10f
mIOB2?.textSize = 14f
}
}
}

View file

@ -0,0 +1,174 @@
@file:Suppress("DEPRECATION")
package info.nightscout.androidaps.watchfaces
import android.annotation.SuppressLint
import android.content.Intent
import android.graphics.Color
import android.support.wearable.watchface.WatchFaceStyle
import android.view.LayoutInflater
import androidx.core.content.ContextCompat
import com.ustwo.clockwise.common.WatchMode
import info.nightscout.androidaps.R
import info.nightscout.androidaps.interaction.menus.MainMenuActivity
class AapsWatchface : BaseWatchFace() {
private var chartTapTime: Long = 0
private var sgvTapTime: Long = 0
@SuppressLint("InflateParams")
override fun onCreate() {
super.onCreate()
val inflater = getSystemService(LAYOUT_INFLATER_SERVICE) as LayoutInflater
layoutView = inflater.inflate(R.layout.activity_home, null)
performViewSetup()
}
override fun onTapCommand(tapType: Int, x: Int, y: Int, eventTime: Long) {
chart?.let { chart ->
if (tapType == TAP_TYPE_TAP && x >= chart.left && x <= chart.right && y >= chart.top && y <= chart.bottom) {
if (eventTime - chartTapTime < 800) {
changeChartTimeframe()
}
chartTapTime = eventTime
return
}
}
mSgv?.let { mSgv ->
val extra = (mSgv.right - mSgv.left) / 2
if (tapType == TAP_TYPE_TAP && x + extra >= mSgv.left && x - extra <= mSgv.right && y >= mSgv.top && y <= mSgv.bottom) {
if (eventTime - sgvTapTime < 800) {
val intent = Intent(this, MainMenuActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
}
sgvTapTime = eventTime
}
}
}
private fun changeChartTimeframe() {
var timeframe = sp.getInt(R.string.key_chart_time_frame, 3)
timeframe = timeframe % 5 + 1
sp.putInt(R.string.key_chart_time_frame, timeframe)
}
override fun getWatchFaceStyle(): WatchFaceStyle {
return WatchFaceStyle.Builder(this).setAcceptsTapEvents(true).build()
}
override fun setColorDark() {
mLinearLayout?.setBackgroundColor(ContextCompat.getColor(this, if (dividerMatchesBg) R.color.dark_background else R.color.dark_statusView))
mTime?.setTextColor(ContextCompat.getColor(this, R.color.dark_mTime))
mRelativeLayout?.setBackgroundColor(ContextCompat.getColor(this, R.color.dark_background))
when (singleBg.sgvLevel) {
1L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor))
mDelta?.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor))
mDirection?.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor))
}
0L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mDelta?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mDirection?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
}
-1L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor))
mDelta?.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor))
mDirection?.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor))
}
}
if (ageLevel == 1) {
mTimestamp?.setTextColor(ContextCompat.getColor(this, if (dividerMatchesBg) R.color.dark_midColor else R.color.dark_mTimestamp1_home))
} else {
mTimestamp?.setTextColor(ContextCompat.getColor(this, R.color.dark_TimestampOld))
}
if (status.batteryLevel == 1) {
mUploaderBattery?.setTextColor(ContextCompat.getColor(this, if (dividerMatchesBg) R.color.dark_midColor else R.color.dark_uploaderBattery))
} else {
mUploaderBattery?.setTextColor(ContextCompat.getColor(this, R.color.dark_uploaderBatteryEmpty))
}
mStatus?.setTextColor(ContextCompat.getColor(this, if (dividerMatchesBg) R.color.dark_midColor else R.color.dark_mStatus_home))
if (chart != null) {
highColor = ContextCompat.getColor(this, R.color.dark_highColor)
lowColor = ContextCompat.getColor(this, R.color.dark_lowColor)
midColor = ContextCompat.getColor(this, R.color.dark_midColor)
gridColor = ContextCompat.getColor(this, R.color.dark_gridColor)
basalBackgroundColor = ContextCompat.getColor(this, R.color.basal_dark)
basalCenterColor = ContextCompat.getColor(this, R.color.basal_light)
pointSize = 2
setupCharts()
}
}
override fun setColorLowRes() {
mTime?.setTextColor(ContextCompat.getColor(this, R.color.dark_mTime))
mRelativeLayout?.setBackgroundColor(ContextCompat.getColor(this, R.color.dark_background))
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mDelta?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mTimestamp?.setTextColor(ContextCompat.getColor(this, R.color.dark_Timestamp))
if (chart != null) {
highColor = ContextCompat.getColor(this, R.color.dark_midColor)
lowColor = ContextCompat.getColor(this, R.color.dark_midColor)
midColor = ContextCompat.getColor(this, R.color.dark_midColor)
gridColor = ContextCompat.getColor(this, R.color.dark_gridColor)
basalBackgroundColor = ContextCompat.getColor(this, R.color.basal_dark_lowres)
basalCenterColor = ContextCompat.getColor(this, R.color.basal_light_lowres)
pointSize = 2
setupCharts()
}
}
override fun setColorBright() {
if (currentWatchMode == WatchMode.INTERACTIVE) {
mLinearLayout?.setBackgroundColor(ContextCompat.getColor(this, if (dividerMatchesBg) R.color.light_background else R.color.light_stripe_background))
mRelativeLayout?.setBackgroundColor(ContextCompat.getColor(this, R.color.light_background))
when (singleBg.sgvLevel) {
1L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.light_highColor))
mDelta?.setTextColor(ContextCompat.getColor(this, R.color.light_highColor))
mDirection?.setTextColor(ContextCompat.getColor(this, R.color.light_highColor))
}
0L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.light_midColor))
mDelta?.setTextColor(ContextCompat.getColor(this, R.color.light_midColor))
mDirection?.setTextColor(ContextCompat.getColor(this, R.color.light_midColor))
}
-1L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.light_lowColor))
mDelta?.setTextColor(ContextCompat.getColor(this, R.color.light_lowColor))
mDirection?.setTextColor(ContextCompat.getColor(this, R.color.light_lowColor))
}
}
if (ageLevel == 1) {
mTimestamp?.setTextColor(if (dividerMatchesBg) Color.BLACK else Color.WHITE)
} else {
mTimestamp?.setTextColor(Color.RED)
}
if (status.batteryLevel == 1) {
mUploaderBattery?.setTextColor(if (dividerMatchesBg) Color.BLACK else Color.WHITE)
} else {
mUploaderBattery?.setTextColor(Color.RED)
}
mStatus?.setTextColor(if (dividerMatchesBg) Color.BLACK else Color.WHITE)
mTime?.setTextColor(Color.BLACK)
if (chart != null) {
highColor = ContextCompat.getColor(this, R.color.light_highColor)
lowColor = ContextCompat.getColor(this, R.color.light_lowColor)
midColor = ContextCompat.getColor(this, R.color.light_midColor)
gridColor = ContextCompat.getColor(this, R.color.light_gridColor)
basalBackgroundColor = ContextCompat.getColor(this, R.color.basal_light)
basalCenterColor = ContextCompat.getColor(this, R.color.basal_dark)
pointSize = 2
setupCharts()
}
} else {
setColorDark()
}
}
}

View file

@ -1,491 +0,0 @@
package info.nightscout.androidaps.watchfaces;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.PowerManager;
import android.support.wearable.watchface.WatchFaceStyle;
import android.text.format.DateFormat;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.core.content.ContextCompat;
import com.ustwo.clockwise.common.WatchFaceTime;
import com.ustwo.clockwise.common.WatchMode;
import com.ustwo.clockwise.common.WatchShape;
import com.ustwo.clockwise.wearable.WatchFace;
import java.util.ArrayList;
import javax.inject.Inject;
import dagger.android.AndroidInjection;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.events.EventWearToMobile;
import info.nightscout.androidaps.interaction.menus.MainMenuActivity;
import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.rx.AapsSchedulers;
import info.nightscout.shared.logging.AAPSLogger;
import info.nightscout.shared.logging.LTag;
import info.nightscout.shared.sharedPreferences.SP;
import info.nightscout.shared.weardata.EventData;
import io.reactivex.rxjava3.disposables.CompositeDisposable;
import lecho.lib.hellocharts.view.LineChartView;
/**
* Created by adrianLxM.
*/
@SuppressWarnings("deprecation")
public class BIGChart extends WatchFace {
@Inject RxBus rxBus;
@Inject AapsSchedulers aapsSchedulers;
@Inject AAPSLogger aapsLogger;
@Inject SP sp;
@Inject DateUtil dateUtil;
CompositeDisposable disposable = new CompositeDisposable();
private EventData.SingleBg singleBg;
private EventData.Status status;
private EventData.TreatmentData treatmentData;
private EventData.GraphData graphData;
private static final int SCREEN_SIZE_SMALL = 280;
private TextView mTime, mSgv, mTimestamp, mDelta, mAvgDelta;
private RelativeLayout mRelativeLayout;
public int ageLevel = 1;
public int highColor = Color.YELLOW;
public int lowColor = Color.RED;
public int midColor = Color.WHITE;
public int gridColour = Color.WHITE;
public int basalBackgroundColor = Color.BLUE;
public int basalCenterColor = Color.BLUE;
public int bolusColor = Color.MAGENTA;
public int carbsColor = Color.GREEN;
public int pointSize = 2;
public boolean lowResMode = false;
public boolean layoutSet = false;
public BgGraphBuilder bgGraphBuilder;
public LineChartView chart;
public ArrayList<EventData.SingleBg> bgDataList = new ArrayList<>();
public PowerManager.WakeLock wakeLock;
public View layoutView;
private final Point displaySize = new Point();
private int specW, specH;
private TextView statusView;
private long chartTapTime = 0L;
private long sgvTapTime = 0L;
@SuppressLint("InflateParams")
@Override
public void onCreate() {
AndroidInjection.inject(this);
super.onCreate();
Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay();
display.getSize(displaySize);
wakeLock = ((PowerManager) getSystemService(Context.POWER_SERVICE)).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidAPS:BIGChart");
specW = View.MeasureSpec.makeMeasureSpec(displaySize.x,
View.MeasureSpec.EXACTLY);
specH = View.MeasureSpec.makeMeasureSpec(displaySize.y,
View.MeasureSpec.EXACTLY);
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
DisplayMetrics metrics = getResources().getDisplayMetrics();
if (metrics.widthPixels < SCREEN_SIZE_SMALL || metrics.heightPixels < SCREEN_SIZE_SMALL) {
layoutView = inflater.inflate(R.layout.activity_bigchart_small, null);
} else {
layoutView = inflater.inflate(R.layout.activity_bigchart, null);
}
performViewSetup();
disposable.add(rxBus
.toObservable(EventData.SingleBg.class)
.observeOn(aapsSchedulers.getMain())
.subscribe(event -> {
aapsLogger.debug(LTag.WEAR, "SingleBg received");
singleBg = event;
mSgv.setText(singleBg.getSgvString());
if (ageLevel() <= 0)
mSgv.setPaintFlags(mSgv.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
else mSgv.setPaintFlags(mSgv.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
final java.text.DateFormat timeFormat = DateFormat.getTimeFormat(BIGChart.this);
mTime.setText(timeFormat.format(System.currentTimeMillis()));
mDelta.setText(singleBg.getDelta());
mAvgDelta.setText(singleBg.getAvgDelta());
})
);
disposable.add(rxBus
.toObservable(EventData.TreatmentData.class)
.observeOn(aapsSchedulers.getMain())
.subscribe(event -> treatmentData = event)
);
disposable.add(rxBus
.toObservable(EventData.GraphData.class)
.observeOn(aapsSchedulers.getMain())
.subscribe(event -> graphData = event)
);
disposable.add(rxBus
.toObservable(EventData.Status.class)
.observeOn(aapsSchedulers.getMain())
.subscribe(event -> {
// this event is received as last batch of data
aapsLogger.debug(LTag.WEAR, "Status received");
status = event;
showAgeAndStatus();
addToWatchSet();
mRelativeLayout.measure(specW, specH);
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
mRelativeLayout.getMeasuredHeight());
invalidate();
setColor();
})
);
disposable.add(rxBus
.toObservable(EventData.Preferences.class)
.observeOn(aapsSchedulers.getMain())
.subscribe(event -> {
setColor();
if (layoutSet) {
showAgeAndStatus();
mRelativeLayout.measure(specW, specH);
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
mRelativeLayout.getMeasuredHeight());
}
invalidate();
})
);
}
@Override
protected void onLayout(WatchShape shape, Rect screenBounds, WindowInsets screenInsets) {
super.onLayout(shape, screenBounds, screenInsets);
layoutView.onApplyWindowInsets(screenInsets);
}
public void performViewSetup() {
mTime = layoutView.findViewById(R.id.watch_time);
mSgv = layoutView.findViewById(R.id.sgv);
mTimestamp = layoutView.findViewById(R.id.timestamp);
mDelta = layoutView.findViewById(R.id.delta);
mAvgDelta = layoutView.findViewById(R.id.avgdelta);
mRelativeLayout = layoutView.findViewById(R.id.main_layout);
chart = layoutView.findViewById(R.id.chart);
statusView = layoutView.findViewById(R.id.aps_status);
layoutSet = true;
showAgeAndStatus();
mRelativeLayout.measure(specW, specH);
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(), mRelativeLayout.getMeasuredHeight());
rxBus.send(new EventWearToMobile(new EventData.ActionResendData("BIGChart:performViewSetup")));
wakeLock.acquire(50);
}
@Override
protected void onTapCommand(int tapType, int x, int y, long eventTime) {
int extra = mSgv != null ? (mSgv.getRight() - mSgv.getLeft()) / 2 : 0;
if (tapType == TAP_TYPE_TAP &&
x >= chart.getLeft() &&
x <= chart.getRight() &&
y >= chart.getTop() &&
y <= chart.getBottom()) {
if (eventTime - chartTapTime < 800) {
changeChartTimeframe();
}
chartTapTime = eventTime;
} else if (tapType == TAP_TYPE_TAP &&
x + extra >= mSgv.getLeft() &&
x - extra <= mSgv.getRight() &&
y >= mSgv.getTop() &&
y <= mSgv.getBottom()) {
if (eventTime - sgvTapTime < 800) {
Intent intent = new Intent(this, MainMenuActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
sgvTapTime = eventTime;
}
}
private void changeChartTimeframe() {
int timeframe = sp.getInt("chart_timeframe", 3);
timeframe = (timeframe % 5) + 1;
sp.putInt("chart_timeframe", timeframe);
}
protected void onWatchModeChanged(WatchMode watchMode) {
if (lowResMode ^ isLowRes(watchMode)) { //if there was a change in lowResMode
lowResMode = isLowRes(watchMode);
setColor();
} else if (!sp.getBoolean("dark", true)) {
//in bright mode: different colours if active:
setColor();
}
}
private boolean isLowRes(WatchMode watchMode) {
return (watchMode == WatchMode.LOW_BIT) || (watchMode == WatchMode.LOW_BIT_BURN_IN);
}
@SuppressWarnings("deprecation")
@Override
protected WatchFaceStyle getWatchFaceStyle() {
return new WatchFaceStyle.Builder(this).setAcceptsTapEvents(true).build();
}
public int ageLevel() {
if (timeSince() <= (1000 * 60 * 12)) {
return 1;
} else {
return 0;
}
}
public double timeSince() {
return System.currentTimeMillis() - singleBg.getTimeStamp();
}
public String readingAge(boolean shortString) {
if (singleBg == null || singleBg.getTimeStamp() == 0) {
return shortString ? "--'" : "-- Minute ago";
}
int minutesAgo = (int) Math.floor(timeSince() / (1000 * 60));
if (minutesAgo == 1) {
return minutesAgo + (shortString ? "'" : " Minute ago");
}
return minutesAgo + (shortString ? "'" : " Minutes ago");
}
@Override
public void onDestroy() {
disposable.clear();
super.onDestroy();
}
@Override
protected void onDraw(Canvas canvas) {
if (layoutSet) {
this.mRelativeLayout.draw(canvas);
}
}
@Override
protected void onTimeChanged(WatchFaceTime oldTime, WatchFaceTime newTime) {
if (layoutSet && (newTime.hasHourChanged(oldTime) || newTime.hasMinuteChanged(oldTime))) {
wakeLock.acquire(50);
final java.text.DateFormat timeFormat = DateFormat.getTimeFormat(BIGChart.this);
mTime.setText(timeFormat.format(System.currentTimeMillis()));
showAgeAndStatus();
if (ageLevel() <= 0) {
mSgv.setPaintFlags(mSgv.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
} else {
mSgv.setPaintFlags(mSgv.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
}
missedReadingAlert();
mRelativeLayout.measure(specW, specH);
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
mRelativeLayout.getMeasuredHeight());
}
}
private void showAgeAndStatus() {
if (mTimestamp != null) {
mTimestamp.setText(readingAge(true));
}
boolean showStatus = sp.getBoolean("showExternalStatus", true);
boolean showAvgDelta = sp.getBoolean("showAvgDelta", true);
if (showAvgDelta) {
mAvgDelta.setVisibility(View.VISIBLE);
} else {
mAvgDelta.setVisibility(View.GONE);
}
if (showStatus && status != null) {
String status = this.status.getExternalStatus();
if (sp.getBoolean("show_cob", true)) {
status += " " + this.status.getCob();
}
statusView.setText(status);
statusView.setVisibility(View.VISIBLE);
} else {
statusView.setVisibility(View.GONE);
}
}
public void setColor() {
if (lowResMode) {
setColorLowRes();
} else if (sp.getBoolean("dark", true)) {
setColorDark();
} else {
setColorBright();
}
}
protected void setColorLowRes() {
mTime.setTextColor(ContextCompat.getColor(this, R.color.dark_mTime));
statusView.setTextColor(ContextCompat.getColor(this, R.color.dark_statusView));
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(this, R.color.dark_background));
mSgv.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mDelta.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mAvgDelta.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mTimestamp.setTextColor(ContextCompat.getColor(this, R.color.dark_Timestamp));
if (chart != null) {
highColor = ContextCompat.getColor(this, R.color.dark_midColor);
lowColor = ContextCompat.getColor(this, R.color.dark_midColor);
midColor = ContextCompat.getColor(this, R.color.dark_midColor);
gridColour = ContextCompat.getColor(this, R.color.dark_gridColor);
basalBackgroundColor = ContextCompat.getColor(this, R.color.basal_dark_lowres);
basalCenterColor = ContextCompat.getColor(this, R.color.basal_light_lowres);
pointSize = 2;
setupCharts();
}
}
protected void setColorDark() {
if (singleBg != null) {
mTime.setTextColor(ContextCompat.getColor(this, R.color.dark_mTime));
statusView.setTextColor(ContextCompat.getColor(this, R.color.dark_statusView));
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(this, R.color.dark_background));
if (singleBg.getSgvLevel() == 1) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor));
mDelta.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor));
mAvgDelta.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor));
} else if (singleBg.getSgvLevel() == 0) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mDelta.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mAvgDelta.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
} else if (singleBg.getSgvLevel() == -1) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor));
mDelta.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor));
mAvgDelta.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor));
}
if (ageLevel == 1) {
mTimestamp.setTextColor(ContextCompat.getColor(this, R.color.dark_Timestamp));
} else {
mTimestamp.setTextColor(ContextCompat.getColor(this, R.color.dark_TimestampOld));
}
if (chart != null) {
highColor = ContextCompat.getColor(this, R.color.dark_highColor);
lowColor = ContextCompat.getColor(this, R.color.dark_lowColor);
midColor = ContextCompat.getColor(this, R.color.dark_midColor);
gridColour = ContextCompat.getColor(this, R.color.dark_gridColor);
basalBackgroundColor = ContextCompat.getColor(this, R.color.basal_dark);
basalCenterColor = ContextCompat.getColor(this, R.color.basal_light);
pointSize = 2;
setupCharts();
}
}
}
protected void setColorBright() {
if (getCurrentWatchMode() == WatchMode.INTERACTIVE) {
mTime.setTextColor(ContextCompat.getColor(this, R.color.light_bigchart_time));
statusView.setTextColor(ContextCompat.getColor(this, R.color.light_bigchart_status));
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(this, R.color.light_background));
if (singleBg.getSgvLevel() == 1) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.light_highColor));
mDelta.setTextColor(ContextCompat.getColor(this, R.color.light_highColor));
mAvgDelta.setTextColor(ContextCompat.getColor(this, R.color.light_highColor));
} else if (singleBg.getSgvLevel() == 0) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.light_midColor));
mDelta.setTextColor(ContextCompat.getColor(this, R.color.light_midColor));
mAvgDelta.setTextColor(ContextCompat.getColor(this, R.color.light_midColor));
} else if (singleBg.getSgvLevel() == -1) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.light_lowColor));
mDelta.setTextColor(ContextCompat.getColor(this, R.color.light_lowColor));
mAvgDelta.setTextColor(ContextCompat.getColor(this, R.color.light_lowColor));
}
if (ageLevel == 1) {
mTimestamp.setTextColor(ContextCompat.getColor(this, R.color.light_mTimestamp1));
} else {
mTimestamp.setTextColor(ContextCompat.getColor(this, R.color.light_mTimestamp));
}
if (chart != null) {
highColor = ContextCompat.getColor(this, R.color.light_highColor);
lowColor = ContextCompat.getColor(this, R.color.light_lowColor);
midColor = ContextCompat.getColor(this, R.color.light_midColor);
gridColour = ContextCompat.getColor(this, R.color.light_gridColor);
basalBackgroundColor = ContextCompat.getColor(this, R.color.basal_light);
basalCenterColor = ContextCompat.getColor(this, R.color.basal_dark);
pointSize = 2;
setupCharts();
}
} else {
setColorDark();
}
}
public void missedReadingAlert() {
int minutes_since = (int) Math.floor(timeSince() / (1000 * 60));
if (minutes_since >= 16 && ((minutes_since - 16) % 5) == 0) {
// attempt endTime recover missing data
rxBus.send(new EventWearToMobile(new EventData.ActionResendData("BIGChart:missedReadingAlert")));
}
}
public void addToWatchSet() {
if (graphData != null) {
bgDataList = graphData.getEntries();
} else {
final int size = bgDataList.size();
if (size > 0 && bgDataList.get(size - 1).getTimeStamp() == singleBg.getTimeStamp())
return; // Ignore duplicates.
bgDataList.add(singleBg);
}
}
public void setupCharts() {
if (bgDataList.size() > 0) {
int timeframe = sp.getInt("chart_timeframe", 3);
if (lowResMode) {
bgGraphBuilder = new BgGraphBuilder(sp, dateUtil, bgDataList,
treatmentData.getPredictions(), treatmentData.getTemps(), treatmentData.getBasals(), treatmentData.getBoluses(), pointSize, midColor, gridColour, basalBackgroundColor, basalCenterColor, bolusColor, carbsColor, timeframe);
} else {
bgGraphBuilder = new BgGraphBuilder(sp, dateUtil, bgDataList,
treatmentData.getPredictions(), treatmentData.getTemps(), treatmentData.getBasals(), treatmentData.getBoluses(), pointSize, highColor, lowColor, midColor, gridColour, basalBackgroundColor, basalCenterColor, bolusColor, carbsColor, timeframe);
}
chart.setLineChartData(bgGraphBuilder.lineData());
chart.setViewportCalculationEnabled(true);
chart.setMaximumViewport(chart.getMaximumViewport());
} else {
rxBus.send(new EventWearToMobile(new EventData.ActionResendData("BIGChart:setupCharts")));
}
}
}

View file

@ -1,744 +0,0 @@
package info.nightscout.androidaps.watchfaces;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.os.BatteryManager;
import android.os.PowerManager;
import android.os.Vibrator;
import android.support.wearable.view.WatchViewStub;
import android.text.format.DateFormat;
import android.view.Display;
import android.view.View;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.core.content.ContextCompat;
import com.ustwo.clockwise.common.WatchFaceTime;
import com.ustwo.clockwise.common.WatchMode;
import com.ustwo.clockwise.common.WatchShape;
import com.ustwo.clockwise.wearable.WatchFace;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Locale;
import javax.inject.Inject;
import dagger.android.AndroidInjection;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.events.EventWearPreferenceChange;
import info.nightscout.androidaps.events.EventWearToMobile;
import info.nightscout.androidaps.interaction.utils.Persistence;
import info.nightscout.androidaps.interaction.utils.WearUtil;
import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.rx.AapsSchedulers;
import info.nightscout.shared.logging.AAPSLogger;
import info.nightscout.shared.logging.LTag;
import info.nightscout.shared.sharedPreferences.SP;
import info.nightscout.shared.weardata.EventData;
import io.reactivex.rxjava3.disposables.CompositeDisposable;
import lecho.lib.hellocharts.view.LineChartView;
/**
* Created by emmablack on 12/29/14.
* Updated by andrew-warrington on 02-Jan-2018.
* Refactored by dlvoy on 2019-11-2019
*/
public abstract class BaseWatchFace extends WatchFace {
@Inject WearUtil wearUtil;
@Inject Persistence persistence;
@Inject AAPSLogger aapsLogger;
@Inject RxBus rxBus;
@Inject AapsSchedulers aapsSchedulers;
@Inject SP sp;
@Inject DateUtil dateUtil;
CompositeDisposable disposable = new CompositeDisposable();
protected EventData.SingleBg singleBg = new EventData.SingleBg(0, "---", "-", "--", "--", "--", 0, 0.0, 0.0, 0.0, 0);
protected EventData.Status status = new EventData.Status("no status", "IOB", "-.--", false, "--g", "-.--U/h", "--", "--", -1, "--", false, 1);
protected EventData.TreatmentData treatmentData = new EventData.TreatmentData(new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>());
protected EventData.GraphData graphData = new EventData.GraphData(new ArrayList<>());
static IntentFilter iFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
public final Point displaySize = new Point();
public TextView mTime, mHour, mMinute, mTimePeriod, mSgv, mDirection, mTimestamp, mUploaderBattery, mRigBattery, mDelta, mAvgDelta, mStatus, mBasalRate, mIOB1, mIOB2, mCOB1, mCOB2, mBgi, mLoop, mDay, mDayName, mMonth, isAAPSv2, mHighLight, mLowLight;
public ImageView mGlucoseDial, mDeltaGauge, mHourHand, mMinuteHand;
public RelativeLayout mRelativeLayout;
public LinearLayout mLinearLayout, mLinearLayout2, mDate, mChartTap, mMainMenuTap;
public int ageLevel = 1;
public int loopLevel = -1;
public int highColor = Color.YELLOW;
public int lowColor = Color.RED;
public int midColor = Color.WHITE;
public int gridColor = Color.WHITE;
public int basalBackgroundColor = Color.BLUE;
public int basalCenterColor = Color.BLUE;
public int bolusColor = Color.MAGENTA;
public boolean lowResMode = false;
public boolean layoutSet = false;
public boolean bIsRound = false;
public boolean dividerMatchesBg = false;
public int pointSize = 2;
public BgGraphBuilder bgGraphBuilder;
public LineChartView chart;
public PowerManager.WakeLock wakeLock;
// related endTime manual layout
public View layoutView;
public int specW, specH;
public boolean forceSquareCanvas = false; // Set to true by the Steampunk watch face.
public String sMinute = "0";
public String sHour = "0";
private BroadcastReceiver batteryReceiver;
private int colorDarkHigh, colorDarkMid, colorDarkLow;
private java.text.DateFormat timeFormat;
private SimpleDateFormat sdfDay, sdfMonth, sdfHour, sdfPeriod, sdfDayName, sdfMinute;
private Paint mBackgroundPaint, mTimePaint, mSvgPaint, mDirectionPaint;
private Date mDateTime;
private String mLastSvg = "", mLastDirection = "";
private float mYOffset = 0;
@Override
public void onCreate() {
// Not derived from DaggerService, do injection here
AndroidInjection.inject(this);
super.onCreate();
colorDarkHigh = ContextCompat.getColor(this, R.color.dark_highColor);
colorDarkMid = ContextCompat.getColor(this, R.color.dark_midColor);
colorDarkLow = ContextCompat.getColor(this, R.color.dark_lowColor);
Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
display.getSize(displaySize);
wakeLock = ((PowerManager) getSystemService(Context.POWER_SERVICE)).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidAPS:BaseWatchFace");
specW = View.MeasureSpec.makeMeasureSpec(displaySize.x, View.MeasureSpec.EXACTLY);
if (forceSquareCanvas) {
specH = specW;
} else {
specH = View.MeasureSpec.makeMeasureSpec(displaySize.y, View.MeasureSpec.EXACTLY);
}
disposable.add(rxBus
.toObservable(EventWearPreferenceChange.class)
.observeOn(aapsSchedulers.getMain())
.subscribe(event -> {
setupBatteryReceiver();
if (event.getChangedKey() != null && event.getChangedKey().equals("delta_granularity"))
rxBus.send(new EventWearToMobile(new EventData.ActionResendData("BaseWatchFace:onSharedPreferenceChanged")));
if (layoutSet) setDataFields();
invalidate();
})
);
disposable.add(rxBus
.toObservable(EventData.SingleBg.class)
.observeOn(aapsSchedulers.getMain())
.subscribe(event -> singleBg = event)
);
disposable.add(rxBus
.toObservable(EventData.TreatmentData.class)
.observeOn(aapsSchedulers.getMain())
.subscribe(event -> treatmentData = event)
);
disposable.add(rxBus
.toObservable(EventData.GraphData.class)
.observeOn(aapsSchedulers.getMain())
.subscribe(event -> graphData = event)
);
disposable.add(rxBus
.toObservable(EventData.Status.class)
.observeOn(aapsSchedulers.getMain())
.subscribe(event -> {
status = event;
// this event is received as last batch of data
if (!isSimpleUi() || !needUpdate()) {
setupCharts();
setDataFields();
}
invalidate();
})
);
persistence.turnOff();
setupBatteryReceiver();
initFormats();
setupSimpleUi();
}
private void setupBatteryReceiver() {
String setting = sp.getString("simplify_ui", "off");
if ((setting.equals("charging") || setting.equals("ambient_charging")) && batteryReceiver == null) {
IntentFilter intentBatteryFilter = new IntentFilter();
intentBatteryFilter.addAction(BatteryManager.ACTION_CHARGING);
intentBatteryFilter.addAction(BatteryManager.ACTION_DISCHARGING);
batteryReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
setDataFields();
invalidate();
}
};
registerReceiver(batteryReceiver, intentBatteryFilter);
}
}
private void initFormats() {
Locale locale = Locale.getDefault();
timeFormat = DateFormat.getTimeFormat(BaseWatchFace.this);
sdfMinute = new SimpleDateFormat("mm", locale);
sdfHour = DateFormat.is24HourFormat(this) ? new SimpleDateFormat("HH", locale) : new SimpleDateFormat("hh", locale);
sdfPeriod = new SimpleDateFormat("a", locale);
sdfDay = new SimpleDateFormat("dd", locale);
sdfDayName = new SimpleDateFormat("E", locale);
sdfMonth = new SimpleDateFormat("MMM", locale);
}
private void setupSimpleUi() {
mDateTime = new Date();
int black = ContextCompat.getColor(this, R.color.black);
mBackgroundPaint = new Paint();
mBackgroundPaint.setColor(black);
final Typeface NORMAL_TYPEFACE = Typeface.create(Typeface.SANS_SERIF, Typeface.NORMAL);
final Typeface BOLD_TYPEFACE = Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD);
int white = ContextCompat.getColor(this, R.color.white);
Resources resources = this.getResources();
float textSizeSvg = resources.getDimension(R.dimen.simple_ui_svg_text_size);
float textSizeDirection = resources.getDimension(R.dimen.simple_ui_direction_text_size);
float textSizeTime = resources.getDimension(R.dimen.simple_ui_time_text_size);
mYOffset = resources.getDimension(R.dimen.simple_ui_y_offset);
mSvgPaint = createTextPaint(NORMAL_TYPEFACE, white, textSizeSvg);
mDirectionPaint = createTextPaint(BOLD_TYPEFACE, white, textSizeDirection);
mTimePaint = createTextPaint(NORMAL_TYPEFACE, white, textSizeTime);
}
private Paint createTextPaint(Typeface typeface, int colour, float textSize) {
Paint paint = new Paint();
paint.setColor(colour);
paint.setTypeface(typeface);
paint.setAntiAlias(true);
paint.setTextSize(textSize);
return paint;
}
@Override
protected void onLayout(WatchShape shape, Rect screenBounds, WindowInsets screenInsets) {
super.onLayout(shape, screenBounds, screenInsets);
layoutView.onApplyWindowInsets(screenInsets);
bIsRound = screenInsets.isRound();
}
public void performViewSetup() {
mTime = layoutView.findViewById(R.id.watch_time);
mHour = layoutView.findViewById(R.id.hour);
mMinute = layoutView.findViewById(R.id.minute);
mTimePeriod = layoutView.findViewById(R.id.timePeriod);
mDay = layoutView.findViewById(R.id.day);
mDayName = layoutView.findViewById(R.id.dayname);
mMonth = layoutView.findViewById(R.id.month);
mDate = layoutView.findViewById(R.id.date_time);
mLoop = layoutView.findViewById(R.id.loop);
mSgv = layoutView.findViewById(R.id.sgv);
mDirection = layoutView.findViewById(R.id.direction);
mTimestamp = layoutView.findViewById(R.id.timestamp);
mIOB1 = layoutView.findViewById(R.id.iob_text);
mIOB2 = layoutView.findViewById(R.id.iobView);
mCOB1 = layoutView.findViewById(R.id.cob_text);
mCOB2 = layoutView.findViewById(R.id.cobView);
mBgi = layoutView.findViewById(R.id.bgiView);
mStatus = layoutView.findViewById(R.id.externaltstatus);
mBasalRate = layoutView.findViewById(R.id.tmpBasal);
mUploaderBattery = layoutView.findViewById(R.id.uploader_battery);
mRigBattery = layoutView.findViewById(R.id.rig_battery);
mDelta = layoutView.findViewById(R.id.delta);
mAvgDelta = layoutView.findViewById(R.id.avgdelta);
isAAPSv2 = layoutView.findViewById(R.id.AAPSv2);
mHighLight = layoutView.findViewById(R.id.highLight);
mLowLight = layoutView.findViewById(R.id.lowLight);
mRelativeLayout = layoutView.findViewById(R.id.main_layout);
mLinearLayout = layoutView.findViewById(R.id.secondary_layout);
mLinearLayout2 = layoutView.findViewById(R.id.tertiary_layout);
mGlucoseDial = layoutView.findViewById(R.id.glucose_dial);
mDeltaGauge = layoutView.findViewById(R.id.delta_pointer);
mHourHand = layoutView.findViewById(R.id.hour_hand);
mMinuteHand = layoutView.findViewById(R.id.minute_hand);
mChartTap = layoutView.findViewById(R.id.chart_zoom_tap);
mMainMenuTap = layoutView.findViewById(R.id.main_menu_tap);
chart = layoutView.findViewById(R.id.chart);
layoutSet = true;
setupCharts();
setDataFields();
missedReadingAlert();
wakeLock.acquire(50);
}
public int ageLevel() {
if (timeSince() <= (1000 * 60 * 12)) {
return 1;
}
return 0;
}
public double timeSince() {
return System.currentTimeMillis() - singleBg.getTimeStamp();
}
public String readingAge(boolean shortString) {
if (singleBg.getTimeStamp() == 0) {
return shortString ? "--" : "-- Minute ago";
}
int minutesAgo = (int) Math.floor(timeSince() / (1000 * 60));
if (minutesAgo == 1) {
return minutesAgo + (shortString ? "'" : " Minute ago");
}
return minutesAgo + (shortString ? "'" : " Minutes ago");
}
@Override
public void onDestroy() {
disposable.clear();
if (batteryReceiver != null) {
unregisterReceiver(batteryReceiver);
}
super.onDestroy();
}
@Override
protected long getInteractiveModeUpdateRate() {
return 60 * 1000L; // Only call onTimeChanged every 60 seconds
}
@Override
protected void onDraw(Canvas canvas) {
if (isSimpleUi()) {
onDrawSimpleUi(canvas);
} else {
if (layoutSet) {
mRelativeLayout.measure(specW, specH);
int y = forceSquareCanvas ? displaySize.x : displaySize.y; // Square Steampunk
mRelativeLayout.layout(0, 0, displaySize.x, y);
mRelativeLayout.draw(canvas);
}
}
}
protected void onDrawSimpleUi(Canvas canvas) {
canvas.drawRect(0, 0, displaySize.x, displaySize.y, mBackgroundPaint);
float xHalf = displaySize.x / 2f;
float yThird = displaySize.y / 3f;
boolean isOutdated = singleBg.getTimeStamp() > 0 && ageLevel() <= 0;
mSvgPaint.setStrikeThruText(isOutdated);
mSvgPaint.setColor(getBgColour(singleBg.getSgvLevel()));
mDirectionPaint.setColor(getBgColour(singleBg.getSgvLevel()));
String sSvg = singleBg.getSgvString();
float svgWidth = mSvgPaint.measureText(sSvg);
String sDirection = " " + singleBg.getSgvString() + "\uFE0E";
float directionWidth = mDirectionPaint.measureText(sDirection);
float xSvg = xHalf - (svgWidth + directionWidth) / 2;
canvas.drawText(sSvg, xSvg, yThird + mYOffset, mSvgPaint);
float xDirection = xSvg + svgWidth;
canvas.drawText(sDirection, xDirection, yThird + mYOffset, mDirectionPaint);
String sTime = timeFormat.format(mDateTime);
float xTime = xHalf - mTimePaint.measureText(sTime) / 2f;
canvas.drawText(timeFormat.format(mDateTime), xTime, yThird * 2f + mYOffset, mTimePaint);
}
int getBgColour(long level) {
if (level == 1) {
return colorDarkHigh;
}
if (level == 0) {
return colorDarkMid;
}
return colorDarkLow;
}
@Override
protected void onTimeChanged(WatchFaceTime oldTime, WatchFaceTime newTime) {
if (layoutSet && (newTime.hasHourChanged(oldTime) || newTime.hasMinuteChanged(oldTime))) {
long now = System.currentTimeMillis();
mDateTime.setTime(now);
PowerManager.WakeLock wl = wearUtil.getWakeLock("readingPrefs", 50);
missedReadingAlert();
checkVibrateHourly(oldTime, newTime);
if (!isSimpleUi()) {
setDataFields();
}
wearUtil.releaseWakeLock(wl);
}
}
private boolean isCharging() {
Intent mBatteryStatus = this.registerReceiver(null, iFilter);
int status = mBatteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
return status == BatteryManager.BATTERY_STATUS_CHARGING ||
status == BatteryManager.BATTERY_STATUS_FULL;
}
private void checkVibrateHourly(WatchFaceTime oldTime, WatchFaceTime newTime) {
boolean hourlyVibratePref = sp.getBoolean("vibrate_Hourly", false);
if (hourlyVibratePref && layoutSet && newTime.hasHourChanged(oldTime)) {
aapsLogger.info(LTag.WEAR, "hourlyVibratePref", "true --> " + newTime);
Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
long[] vibrationPattern = {0, 150, 125, 100};
vibrator.vibrate(vibrationPattern, -1);
}
}
public void setDataFields() {
setDateAndTime();
if (mSgv != null) {
if (sp.getBoolean("showBG", true)) {
mSgv.setText(singleBg.getSgvString());
mSgv.setVisibility(View.VISIBLE);
} else {
// Leave the textview there but invisible, as a height holder for the empty space above the white line
mSgv.setVisibility(View.INVISIBLE);
mSgv.setText("");
}
}
strikeThroughSgvIfNeeded();
if (mDirection != null) {
if (sp.getBoolean("show_direction", true)) {
mDirection.setText(singleBg.getSgvString() + "\uFE0E");
mDirection.setVisibility(View.VISIBLE);
} else {
mDirection.setVisibility(View.GONE);
}
}
if (mDelta != null) {
if (sp.getBoolean("showDelta", true)) {
mDelta.setText(singleBg.getDelta());
mDelta.setVisibility(View.VISIBLE);
} else {
mDelta.setVisibility(View.GONE);
}
}
if (mAvgDelta != null) {
if (sp.getBoolean("showAvgDelta", true)) {
mAvgDelta.setText(singleBg.getAvgDelta());
mAvgDelta.setVisibility(View.VISIBLE);
} else {
mAvgDelta.setVisibility(View.GONE);
}
}
if (mCOB1 != null && mCOB2 != null) {
mCOB2.setText(status.getCob());
if (sp.getBoolean("show_cob", true)) {
mCOB1.setVisibility(View.VISIBLE);
mCOB2.setVisibility(View.VISIBLE);
} else {
mCOB1.setVisibility(View.GONE);
mCOB2.setVisibility(View.GONE);
}
// Deal with cases where there is only the value shown for COB, and not the label
} else if (mCOB2 != null) {
mCOB2.setText(status.getCob());
if (sp.getBoolean("show_cob", true)) {
mCOB2.setVisibility(View.VISIBLE);
} else {
mCOB2.setVisibility(View.GONE);
}
}
if (mIOB1 != null && mIOB2 != null) {
if (sp.getBoolean("show_iob", true)) {
mIOB1.setVisibility(View.VISIBLE);
mIOB2.setVisibility(View.VISIBLE);
if (status.getDetailedIob()) {
mIOB1.setText(status.getIobSum());
mIOB2.setText(status.getIobDetail());
} else {
mIOB1.setText(getString(R.string.activity_IOB));
mIOB2.setText(status.getIobSum());
}
} else {
mIOB1.setVisibility(View.GONE);
mIOB2.setVisibility(View.GONE);
}
// Deal with cases where there is only the value shown for IOB, and not the label
} else if (mIOB2 != null) {
if (sp.getBoolean("show_iob", true)) {
mIOB2.setVisibility(View.VISIBLE);
if (status.getDetailedIob()) {
mIOB2.setText(status.getIobDetail());
} else {
mIOB2.setText(status.getIobSum());
}
} else {
mIOB2.setText("");
}
}
if (mTimestamp != null) {
if (sp.getBoolean("showAgo", true)) {
if (isAAPSv2 != null) {
mTimestamp.setText(readingAge(true));
} else {
boolean shortString = sp.getBoolean("showExternalStatus", true);
mTimestamp.setText(readingAge(shortString));
}
mTimestamp.setVisibility(View.VISIBLE);
} else {
mTimestamp.setVisibility(View.GONE);
}
}
if (mUploaderBattery != null) {
if (sp.getBoolean("show_uploader_battery", true)) {
if (isAAPSv2 != null) {
mUploaderBattery.setText(status.getBattery() + "%");
mUploaderBattery.setVisibility(View.VISIBLE);
} else {
if (sp.getBoolean("showExternalStatus", true)) {
mUploaderBattery.setText("U: " + status.getBattery() + "%");
} else {
mUploaderBattery.setText("Uploader: " + status.getBattery() + "%");
}
}
} else {
mUploaderBattery.setVisibility(View.GONE);
}
}
if (mRigBattery != null) {
if (sp.getBoolean("show_rig_battery", false)) {
mRigBattery.setText(status.getRigBattery());
mRigBattery.setVisibility(View.VISIBLE);
} else {
mRigBattery.setVisibility(View.GONE);
}
}
if (mBasalRate != null) {
if (sp.getBoolean("show_temp_basal", true)) {
mBasalRate.setText(status.getCurrentBasal());
mBasalRate.setVisibility(View.VISIBLE);
} else {
mBasalRate.setVisibility(View.GONE);
}
}
if (mBgi != null) {
if (status.getShowBgi()) {
mBgi.setText(status.getBgi());
mBgi.setVisibility(View.VISIBLE);
} else {
mBgi.setVisibility(View.GONE);
}
}
if (mStatus != null) {
if (sp.getBoolean("showExternalStatus", true)) {
mStatus.setText(status.getExternalStatus());
mStatus.setVisibility(View.VISIBLE);
} else {
mStatus.setVisibility(View.GONE);
}
}
if (mLoop != null) {
if (sp.getBoolean("showExternalStatus", true)) {
mLoop.setVisibility(View.VISIBLE);
if (status.getOpenApsStatus() != -1) {
int mins = (int) ((System.currentTimeMillis() - status.getOpenApsStatus()) / 1000 / 60);
mLoop.setText(mins + "'");
if (mins > 14) {
loopLevel = 0;
mLoop.setBackgroundResource(R.drawable.loop_red_25);
} else {
loopLevel = 1;
mLoop.setBackgroundResource(R.drawable.loop_green_25);
}
} else {
loopLevel = -1;
mLoop.setText("-");
mLoop.setBackgroundResource(R.drawable.loop_grey_25);
}
} else {
mLoop.setVisibility(View.GONE);
}
}
setColor();
}
@Override
protected void on24HourFormatChanged(boolean is24HourFormat) {
initFormats();
if (!isSimpleUi()) {
setDataFields();
}
invalidate();
}
public void setDateAndTime() {
if (mTime != null) {
mTime.setText(timeFormat.format(mDateTime));
}
sMinute = sdfMinute.format(mDateTime);
sHour = sdfHour.format(mDateTime);
if (mHour != null && mMinute != null) {
mHour.setText(sHour);
mMinute.setText(sMinute);
}
if (mTimePeriod != null) {
if (!DateFormat.is24HourFormat(this)) {
mTimePeriod.setVisibility(View.VISIBLE);
mTimePeriod.setText(sdfPeriod.format(mDateTime).toUpperCase());
} else {
mTimePeriod.setVisibility(View.GONE);
}
}
if (mDate != null && mDay != null && mMonth != null) {
if (sp.getBoolean("show_date", false)) {
if (mDayName != null) {
mDayName.setText(sdfDayName.format(mDateTime));
}
mDay.setText(sdfDay.format(mDateTime));
mMonth.setText(sdfMonth.format(mDateTime));
mDate.setVisibility(View.VISIBLE);
} else {
mDate.setVisibility(View.GONE);
}
}
}
public void setColor() {
dividerMatchesBg = sp.getBoolean("match_divider", false);
if (lowResMode) {
setColorLowRes();
} else if (sp.getBoolean("dark", true)) {
setColorDark();
} else {
setColorBright();
}
}
public void strikeThroughSgvIfNeeded() {
if (mSgv != null) {
if (sp.getBoolean("showBG", true)) {
if (ageLevel() <= 0 && singleBg.getTimeStamp() > 0) {
mSgv.setPaintFlags(mSgv.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
} else {
mSgv.setPaintFlags(mSgv.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
}
}
}
}
protected void onWatchModeChanged(WatchMode watchMode) {
lowResMode = isLowRes(watchMode);
if (isSimpleUi()) {
setSimpleUiAntiAlias();
} else {
setDataFields();
}
invalidate();
}
void setSimpleUiAntiAlias() {
boolean antiAlias = getCurrentWatchMode() == WatchMode.AMBIENT;
mSvgPaint.setAntiAlias(antiAlias);
mDirectionPaint.setAntiAlias(antiAlias);
mTimePaint.setAntiAlias(antiAlias);
}
private boolean isLowRes(WatchMode watchMode) {
return watchMode == WatchMode.LOW_BIT || watchMode == WatchMode.LOW_BIT_BURN_IN;
}
private boolean isSimpleUi() {
String simplify = sp.getString("simplify_ui", "off");
if (simplify.equals("off")) {
return false;
}
if ((simplify.equals("ambient") || simplify.equals("ambient_charging")) && getCurrentWatchMode() == WatchMode.AMBIENT) {
return true;
}
return (simplify.equals("charging") || simplify.equals("ambient_charging")) && isCharging();
}
protected abstract void setColorDark();
protected abstract void setColorBright();
protected abstract void setColorLowRes();
public void missedReadingAlert() {
int minutes_since = (int) Math.floor(timeSince() / (1000 * 60));
if (singleBg.getTimeStamp() == 0 || minutes_since >= 16 && ((minutes_since - 16) % 5) == 0) {
// Attempt endTime recover missing data
rxBus.send(new EventWearToMobile(new EventData.ActionResendData("BaseWatchFace:missedReadingAlert")));
}
}
public void setupCharts() {
if (isSimpleUi()) {
return;
}
if (chart != null && graphData.getEntries().size() > 0) {
int timeframe = sp.getInt("chart_timeframe", 3);
if (lowResMode) {
bgGraphBuilder = new BgGraphBuilder(sp, dateUtil,
graphData.getEntries(), treatmentData.getPredictions(), treatmentData.getTemps(), treatmentData.getBasals(), treatmentData.getBoluses(), pointSize, midColor, gridColor, basalBackgroundColor, basalCenterColor, bolusColor, Color.GREEN, timeframe);
} else {
bgGraphBuilder = new BgGraphBuilder(sp, dateUtil, graphData.getEntries(),
treatmentData.getPredictions(), treatmentData.getTemps(), treatmentData.getBasals(), treatmentData.getBoluses(), pointSize, highColor, lowColor, midColor, gridColor, basalBackgroundColor, basalCenterColor, bolusColor, Color.GREEN, timeframe);
}
chart.setLineChartData(bgGraphBuilder.lineData());
chart.setViewportCalculationEnabled(true);
chart.setMaximumViewport(chart.getMaximumViewport());
}
}
private boolean needUpdate() {
if (mLastSvg.equals(singleBg.getSgvString()) && mLastDirection.equals(singleBg.getSgvString())) {
return false;
}
mLastSvg = singleBg.getSgvString();
mLastDirection = singleBg.getSgvString();
return true;
}
}

View file

@ -0,0 +1,547 @@
package info.nightscout.androidaps.watchfaces
import android.annotation.SuppressLint
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.graphics.*
import android.os.BatteryManager
import android.os.PowerManager
import android.os.Vibrator
import android.view.View
import android.view.WindowInsets
import android.view.WindowManager
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.RelativeLayout
import android.widget.TextView
import androidx.core.content.ContextCompat
import com.ustwo.clockwise.common.WatchFaceTime
import com.ustwo.clockwise.common.WatchMode
import com.ustwo.clockwise.common.WatchShape
import com.ustwo.clockwise.wearable.WatchFace
import dagger.android.AndroidInjection
import info.nightscout.androidaps.R
import info.nightscout.androidaps.events.EventWearPreferenceChange
import info.nightscout.androidaps.events.EventWearToMobile
import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.extensions.toVisibilityKeepSpace
import info.nightscout.androidaps.interaction.utils.Persistence
import info.nightscout.androidaps.interaction.utils.WearUtil
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP
import info.nightscout.shared.weardata.EventData
import info.nightscout.shared.weardata.EventData.ActionResendData
import info.nightscout.shared.weardata.EventData.SingleBg
import info.nightscout.shared.weardata.EventData.TreatmentData
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import lecho.lib.hellocharts.view.LineChartView
import javax.inject.Inject
import kotlin.math.floor
/**
* Created by emmablack on 12/29/14.
* Updated by andrew-warrington on 02-Jan-2018.
* Refactored by dlvoy on 2019-11-2019
*/
abstract class BaseWatchFace : WatchFace() {
@Inject lateinit var wearUtil: WearUtil
@Inject lateinit var persistence: Persistence
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var rxBus: RxBus
@Inject lateinit var aapsSchedulers: AapsSchedulers
@Inject lateinit var sp: SP
@Inject lateinit var dateUtil: DateUtil
private var disposable = CompositeDisposable()
protected var singleBg = SingleBg(0, "---", "-", "--", "--", "--", 0, 0.0, 0.0, 0.0, 0)
protected var status = EventData.Status("no status", "IOB", "-.--", false, "--g", "-.--U/h", "--", "--", -1, "--", false, 1)
protected var treatmentData = TreatmentData(ArrayList(), ArrayList(), ArrayList(), ArrayList())
protected var graphData = EventData.GraphData(ArrayList())
private val displaySize = Point()
var mTime: TextView? = null
var mHour: TextView? = null
var mMinute: TextView? = null
var mSgv: TextView? = null
var mDirection: TextView? = null
var mTimestamp: TextView? = null
var mUploaderBattery: TextView? = null
var mRigBattery: TextView? = null
var mDelta: TextView? = null
var mAvgDelta: TextView? = null
var mStatus: TextView? = null
var mBasalRate: TextView? = null
var mIOB1: TextView? = null
var mIOB2: TextView? = null
var mCOB1: TextView? = null
var mCOB2: TextView? = null
var mBgi: TextView? = null
var mLoop: TextView? = null
var mDay: TextView? = null
var mDayName: TextView? = null
var mMonth: TextView? = null
var isAAPSv2: TextView? = null
var mHighLight: TextView? = null
var mLowLight: TextView? = null
var mGlucoseDial: ImageView? = null
var mDeltaGauge: ImageView? = null
var mHourHand: ImageView? = null
var mMinuteHand: ImageView? = null
var mRelativeLayout: RelativeLayout? = null
var mLinearLayout: LinearLayout? = null
var mLinearLayout2: LinearLayout? = null
var mDate: LinearLayout? = null
var mChartTap: LinearLayout? = null
var mMainMenuTap: LinearLayout? = null
var ageLevel = 1
var loopLevel = -1
var highColor = Color.YELLOW
var lowColor = Color.RED
var midColor = Color.WHITE
var gridColor = Color.WHITE
var basalBackgroundColor = Color.BLUE
var basalCenterColor = Color.BLUE
var bolusColor = Color.MAGENTA
var lowResMode = false
var layoutSet = false
var bIsRound = false
var dividerMatchesBg = false
var pointSize = 2
var chart: LineChartView? = null
var wakeLock: PowerManager.WakeLock? = null
// related endTime manual layout
var layoutView: View? = null
var specW = 0
var specH = 0
var forceSquareCanvas = false // Set to true by the Steampunk watch face.
private var batteryReceiver: BroadcastReceiver? = null
private var colorDarkHigh = 0
private var colorDarkMid = 0
private var colorDarkLow = 0
private var mBackgroundPaint = Paint()
private lateinit var mTimePaint: Paint
private lateinit var mSvgPaint: Paint
private lateinit var mDirectionPaint: Paint
private var mLastSvg = ""
private var mLastDirection = ""
private var mYOffset = 0f
override fun onCreate() {
// Not derived from DaggerService, do injection here
AndroidInjection.inject(this)
super.onCreate()
colorDarkHigh = ContextCompat.getColor(this, R.color.dark_highColor)
colorDarkMid = ContextCompat.getColor(this, R.color.dark_midColor)
colorDarkLow = ContextCompat.getColor(this, R.color.dark_lowColor)
@Suppress("DEPRECATION")
(getSystemService(WINDOW_SERVICE) as WindowManager).defaultDisplay.getSize(displaySize)
wakeLock = (getSystemService(POWER_SERVICE) as PowerManager).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidAPS:BaseWatchFace")
specW = View.MeasureSpec.makeMeasureSpec(displaySize.x, View.MeasureSpec.EXACTLY)
specH = if (forceSquareCanvas) specW else View.MeasureSpec.makeMeasureSpec(displaySize.y, View.MeasureSpec.EXACTLY)
disposable += rxBus
.toObservable(EventWearPreferenceChange::class.java)
.observeOn(aapsSchedulers.main)
.subscribe { event: EventWearPreferenceChange ->
setupBatteryReceiver()
if (event.changedKey != null && event.changedKey == "delta_granularity") rxBus.send(EventWearToMobile(ActionResendData("BaseWatchFace:onSharedPreferenceChanged")))
if (layoutSet) setDataFields()
invalidate()
}
disposable += rxBus
.toObservable(SingleBg::class.java)
.observeOn(aapsSchedulers.main)
.subscribe { event: SingleBg -> singleBg = event }
disposable += rxBus
.toObservable(TreatmentData::class.java)
.observeOn(aapsSchedulers.main)
.subscribe { event: TreatmentData -> treatmentData = event }
disposable += rxBus
.toObservable(EventData.GraphData::class.java)
.observeOn(aapsSchedulers.main)
.subscribe { event: EventData.GraphData -> graphData = event }
disposable += rxBus
.toObservable(EventData.Status::class.java)
.observeOn(aapsSchedulers.main)
.subscribe { event: EventData.Status ->
status = event
// this event is received as last batch of data
if (!isSimpleUi || !needUpdate()) {
setupCharts()
setDataFields()
}
invalidate()
}
persistence.turnOff()
setupBatteryReceiver()
setupSimpleUi()
}
private fun setupBatteryReceiver() {
val setting = sp.getString("simplify_ui", "off")
if ((setting == "charging" || setting == "ambient_charging") && batteryReceiver == null) {
val intentBatteryFilter = IntentFilter()
intentBatteryFilter.addAction(BatteryManager.ACTION_CHARGING)
intentBatteryFilter.addAction(BatteryManager.ACTION_DISCHARGING)
batteryReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
setDataFields()
invalidate()
}
}
registerReceiver(batteryReceiver, intentBatteryFilter)
}
}
private fun setupSimpleUi() {
val black = ContextCompat.getColor(this, R.color.black)
mBackgroundPaint.color = black
val white = ContextCompat.getColor(this, R.color.white)
val resources = this.resources
val textSizeSvg = resources.getDimension(R.dimen.simple_ui_svg_text_size)
val textSizeDirection = resources.getDimension(R.dimen.simple_ui_direction_text_size)
val textSizeTime = resources.getDimension(R.dimen.simple_ui_time_text_size)
mYOffset = resources.getDimension(R.dimen.simple_ui_y_offset)
mSvgPaint = createTextPaint(NORMAL_TYPEFACE, white, textSizeSvg)
mDirectionPaint = createTextPaint(BOLD_TYPEFACE, white, textSizeDirection)
mTimePaint = createTextPaint(NORMAL_TYPEFACE, white, textSizeTime)
}
private fun createTextPaint(typeface: Typeface, colour: Int, textSize: Float): Paint {
val paint = Paint()
paint.color = colour
paint.typeface = typeface
paint.isAntiAlias = true
paint.textSize = textSize
return paint
}
override fun onLayout(shape: WatchShape, screenBounds: Rect, screenInsets: WindowInsets) {
super.onLayout(shape, screenBounds, screenInsets)
layoutView?.onApplyWindowInsets(screenInsets)
bIsRound = screenInsets.isRound
}
fun performViewSetup() {
mTime = layoutView?.findViewById(R.id.watch_time)
mHour = layoutView?.findViewById(R.id.hour)
mMinute = layoutView?.findViewById(R.id.minute)
mDay = layoutView?.findViewById(R.id.day)
mDayName = layoutView?.findViewById(R.id.dayname)
mMonth = layoutView?.findViewById(R.id.month)
mDate = layoutView?.findViewById(R.id.date_time)
mLoop = layoutView?.findViewById(R.id.loop)
mSgv = layoutView?.findViewById(R.id.sgv)
mDirection = layoutView?.findViewById(R.id.direction)
mTimestamp = layoutView?.findViewById(R.id.timestamp)
mIOB1 = layoutView?.findViewById(R.id.iob_text)
mIOB2 = layoutView?.findViewById(R.id.iobView)
mCOB1 = layoutView?.findViewById(R.id.cob_text)
mCOB2 = layoutView?.findViewById(R.id.cobView)
mBgi = layoutView?.findViewById(R.id.bgiView)
mStatus = layoutView?.findViewById(R.id.externaltstatus)
mBasalRate = layoutView?.findViewById(R.id.tmpBasal)
mUploaderBattery = layoutView?.findViewById(R.id.uploader_battery)
mRigBattery = layoutView?.findViewById(R.id.rig_battery)
mDelta = layoutView?.findViewById(R.id.delta)
mAvgDelta = layoutView?.findViewById(R.id.avgdelta)
isAAPSv2 = layoutView?.findViewById(R.id.AAPSv2)
mHighLight = layoutView?.findViewById(R.id.highLight)
mLowLight = layoutView?.findViewById(R.id.lowLight)
mRelativeLayout = layoutView?.findViewById(R.id.main_layout)
mLinearLayout = layoutView?.findViewById(R.id.secondary_layout)
mLinearLayout2 = layoutView?.findViewById(R.id.tertiary_layout)
mGlucoseDial = layoutView?.findViewById(R.id.glucose_dial)
mDeltaGauge = layoutView?.findViewById(R.id.delta_pointer)
mHourHand = layoutView?.findViewById(R.id.hour_hand)
mMinuteHand = layoutView?.findViewById(R.id.minute_hand)
mChartTap = layoutView?.findViewById(R.id.chart_zoom_tap)
mMainMenuTap = layoutView?.findViewById(R.id.main_menu_tap)
chart = layoutView?.findViewById(R.id.chart)
layoutSet = true
setupCharts()
setDataFields()
missedReadingAlert()
wakeLock?.acquire(50)
}
fun ageLevel(): Int {
return if (timeSince() <= 1000 * 60 * 12) {
1
} else 0
}
fun timeSince(): Double {
return (System.currentTimeMillis() - singleBg.timeStamp).toDouble()
}
private fun readingAge(shortString: Boolean): String {
if (singleBg.timeStamp == 0L) {
return if (shortString) "--" else "-- Minute ago"
}
val minutesAgo = floor(timeSince() / (1000 * 60)).toInt()
return if (minutesAgo == 1) {
minutesAgo.toString() + if (shortString) "'" else " Minute ago"
} else minutesAgo.toString() + if (shortString) "'" else " Minutes ago"
}
override fun onDestroy() {
disposable.clear()
if (batteryReceiver != null) {
unregisterReceiver(batteryReceiver)
}
super.onDestroy()
}
override fun getInteractiveModeUpdateRate(): Long {
return 60 * 1000L // Only call onTimeChanged every 60 seconds
}
override fun onDraw(canvas: Canvas) {
if (isSimpleUi) {
onDrawSimpleUi(canvas)
} else {
if (layoutSet) {
mRelativeLayout?.measure(specW, specH)
val y = if (forceSquareCanvas) displaySize.x else displaySize.y // Square Steampunk
mRelativeLayout?.layout(0, 0, displaySize.x, y)
mRelativeLayout?.draw(canvas)
}
}
}
private fun onDrawSimpleUi(canvas: Canvas) {
canvas.drawRect(0f, 0f, displaySize.x.toFloat(), displaySize.y.toFloat(), mBackgroundPaint)
val xHalf = displaySize.x / 2f
val yThird = displaySize.y / 3f
val isOutdated = singleBg.timeStamp > 0 && ageLevel() <= 0
mSvgPaint.isStrikeThruText = isOutdated
mSvgPaint.color = getBgColour(singleBg.sgvLevel)
mDirectionPaint.color = getBgColour(singleBg.sgvLevel)
val sSvg = singleBg.sgvString
val svgWidth = mSvgPaint.measureText(sSvg)
val sDirection = " " + singleBg.sgvString + "\uFE0E"
val directionWidth = mDirectionPaint.measureText(sDirection)
val xSvg = xHalf - (svgWidth + directionWidth) / 2
canvas.drawText(sSvg, xSvg, yThird + mYOffset, mSvgPaint)
val xDirection = xSvg + svgWidth
canvas.drawText(sDirection, xDirection, yThird + mYOffset, mDirectionPaint)
val sTime = dateUtil.timeString()
val xTime = xHalf - mTimePaint.measureText(sTime) / 2f
canvas.drawText(sTime, xTime, yThird * 2f + mYOffset, mTimePaint)
}
private fun getBgColour(level: Long): Int {
if (level == 1L) {
return colorDarkHigh
}
return if (level == 0L) {
colorDarkMid
} else colorDarkLow
}
override fun onTimeChanged(oldTime: WatchFaceTime, newTime: WatchFaceTime) {
if (layoutSet && (newTime.hasHourChanged(oldTime) || newTime.hasMinuteChanged(oldTime))) {
val wl = wearUtil.getWakeLock("readingPrefs", 50)
missedReadingAlert()
checkVibrateHourly(oldTime, newTime)
if (!isSimpleUi) {
setDataFields()
}
wearUtil.releaseWakeLock(wl)
}
}
private val isCharging: Boolean
get() {
val mBatteryStatus = this.registerReceiver(null, iFilter)
val status = mBatteryStatus?.getIntExtra(BatteryManager.EXTRA_STATUS, -1)
return status == BatteryManager.BATTERY_STATUS_CHARGING || status == BatteryManager.BATTERY_STATUS_FULL
}
@Suppress("DEPRECATION")
private fun checkVibrateHourly(oldTime: WatchFaceTime, newTime: WatchFaceTime) {
val hourlyVibratePref = sp.getBoolean("vibrate_Hourly", false)
if (hourlyVibratePref && layoutSet && newTime.hasHourChanged(oldTime)) {
aapsLogger.info(LTag.WEAR, "hourlyVibratePref", "true --> $newTime")
val vibrator = getSystemService(VIBRATOR_SERVICE) as Vibrator
val vibrationPattern = longArrayOf(0, 150, 125, 100)
vibrator.vibrate(vibrationPattern, -1)
}
}
@SuppressLint("SetTextI18n") fun setDataFields() {
setDateAndTime()
mSgv?.text = singleBg.sgvString
mSgv?.visibility = sp.getBoolean(R.string.key_show_bg, true).toVisibilityKeepSpace()
strikeThroughSgvIfNeeded()
mDirection?.text = "${singleBg.sgvString}\uFE0E"
mDirection?.visibility = sp.getBoolean("show_direction", true).toVisibility()
mDelta?.text = singleBg.delta
mDelta?.visibility = sp.getBoolean(R.string.key_show_delta, true).toVisibility()
mAvgDelta?.text = singleBg.avgDelta
mAvgDelta?.visibility = sp.getBoolean(R.string.key_show_avg_delta, true).toVisibility()
mCOB1?.visibility = sp.getBoolean(R.string.key_show_cob, true).toVisibility()
mCOB2?.text = status.cob
mCOB2?.visibility = sp.getBoolean(R.string.key_show_cob, true).toVisibility()
mIOB1?.visibility = sp.getBoolean("show_iob", true).toVisibility()
mIOB2?.visibility = sp.getBoolean("show_iob", true).toVisibility()
mIOB1?.text = if (sp.getBoolean("show_iob", true)) status.iobSum else getString(R.string.activity_IOB)
mIOB2?.text = if (sp.getBoolean("show_iob", true)) status.iobDetail else status.iobSum
mTimestamp?.visibility = sp.getBoolean(R.string.key_show_ago, true).toVisibility()
mTimestamp?.text = readingAge(if (isAAPSv2 != null) true else sp.getBoolean(R.string.key_show_external_status, true))
mUploaderBattery?.visibility = sp.getBoolean("show_uploader_battery", true).toVisibility()
mUploaderBattery?.text =
when {
isAAPSv2 != null -> status.battery + "%"
sp.getBoolean(R.string.key_show_external_status, true) -> "U: ${status.battery}%"
else -> "Uploader: ${status.battery}%"
}
mRigBattery?.visibility = sp.getBoolean("show_rig_battery", false).toVisibility()
mRigBattery?.text = status.rigBattery
mBasalRate?.text = status.currentBasal
mBasalRate?.visibility = sp.getBoolean("show_temp_basal", true).toVisibility()
mBgi?.text = status.bgi
mBgi?.visibility = status.showBgi.toVisibility()
mStatus?.text = status.externalStatus
mStatus?.visibility = sp.getBoolean(R.string.key_show_external_status, true).toVisibility()
mLoop?.visibility = sp.getBoolean(R.string.key_show_external_status, true).toVisibility()
if (status.openApsStatus != -1L) {
val minutes = ((System.currentTimeMillis() - status.openApsStatus) / 1000 / 60).toInt()
mLoop?.text = "$minutes'"
if (minutes > 14) {
loopLevel = 0
mLoop?.setBackgroundResource(R.drawable.loop_red_25)
} else {
loopLevel = 1
mLoop?.setBackgroundResource(R.drawable.loop_green_25)
}
} else {
loopLevel = -1
mLoop?.text = "-"
mLoop?.setBackgroundResource(R.drawable.loop_grey_25)
}
setColor()
}
override fun on24HourFormatChanged(is24HourFormat: Boolean) {
if (!isSimpleUi) {
setDataFields()
}
invalidate()
}
private fun setDateAndTime() {
mTime?.text = dateUtil.timeString()
mHour?.text = dateUtil.hourString()
mMinute?.text = dateUtil.minuteString()
mDate?.visibility = sp.getBoolean(R.string.key_show_date, false).toVisibility()
mDayName?.text = dateUtil.dayNameString()
mDay?.text = dateUtil.dayString()
mMonth?.text = dateUtil.monthString()
}
private fun setColor() {
dividerMatchesBg = sp.getBoolean("match_divider", false)
when {
lowResMode -> setColorLowRes()
sp.getBoolean("dark", true) -> setColorDark()
else -> setColorBright()
}
}
private fun strikeThroughSgvIfNeeded() {
mSgv?.let { mSgv ->
if (ageLevel() <= 0 && singleBg.timeStamp > 0) mSgv.paintFlags = mSgv.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
else mSgv.paintFlags = mSgv.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv()
}
}
override fun onWatchModeChanged(watchMode: WatchMode) {
lowResMode = isLowRes(watchMode)
if (isSimpleUi) {
setSimpleUiAntiAlias()
} else {
setDataFields()
}
invalidate()
}
private fun setSimpleUiAntiAlias() {
val antiAlias = currentWatchMode == WatchMode.AMBIENT
mSvgPaint.isAntiAlias = antiAlias
mDirectionPaint.isAntiAlias = antiAlias
mTimePaint.isAntiAlias = antiAlias
}
private fun isLowRes(watchMode: WatchMode): Boolean {
return watchMode == WatchMode.LOW_BIT || watchMode == WatchMode.LOW_BIT_BURN_IN
}
private val isSimpleUi: Boolean
get() {
val simplify = sp.getString("simplify_ui", "off")
return if (simplify == "off") false
else if ((simplify == "ambient" || simplify == "ambient_charging") && currentWatchMode == WatchMode.AMBIENT) true
else (simplify == "charging" || simplify == "ambient_charging") && isCharging
}
protected abstract fun setColorDark()
protected abstract fun setColorBright()
protected abstract fun setColorLowRes()
private fun missedReadingAlert() {
val minutesSince = floor(timeSince() / (1000 * 60)).toInt()
if (singleBg.timeStamp == 0L || minutesSince >= 16 && (minutesSince - 16) % 5 == 0) {
// Attempt endTime recover missing data
rxBus.send(EventWearToMobile(ActionResendData("BaseWatchFace:missedReadingAlert")))
}
}
fun setupCharts() {
if (isSimpleUi) {
return
}
if (chart != null && graphData.entries.size > 0) {
val timeframe = sp.getInt(R.string.key_chart_time_frame, 3)
val bgGraphBuilder =
if (lowResMode)
BgGraphBuilder(
sp, dateUtil, graphData.entries, treatmentData.predictions, treatmentData.temps, treatmentData.basals, treatmentData.boluses, pointSize,
midColor, gridColor, basalBackgroundColor, basalCenterColor, bolusColor, Color.GREEN, timeframe
)
else
BgGraphBuilder(
sp, dateUtil, graphData.entries, treatmentData.predictions, treatmentData.temps, treatmentData.basals, treatmentData.boluses,
pointSize, highColor, lowColor, midColor, gridColor, basalBackgroundColor, basalCenterColor, bolusColor, Color.GREEN, timeframe
)
chart?.lineChartData = bgGraphBuilder.lineData()
chart?.isViewportCalculationEnabled = true
}
}
private fun needUpdate(): Boolean {
if (mLastSvg == singleBg.sgvString && mLastDirection == singleBg.sgvString) {
return false
}
mLastSvg = singleBg.sgvString
mLastDirection = singleBg.sgvString
return true
}
companion object {
var iFilter = IntentFilter(Intent.ACTION_BATTERY_CHANGED)
val NORMAL_TYPEFACE: Typeface = Typeface.create(Typeface.SANS_SERIF, Typeface.NORMAL)
val BOLD_TYPEFACE: Typeface = Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD)
}
}

View file

@ -0,0 +1,428 @@
@file:Suppress("DEPRECATION")
package info.nightscout.androidaps.watchfaces
import android.annotation.SuppressLint
import android.content.Intent
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Point
import android.graphics.Rect
import android.os.PowerManager
import android.support.wearable.watchface.WatchFaceStyle
import android.text.format.DateFormat
import android.view.LayoutInflater
import android.view.View
import android.view.WindowInsets
import android.view.WindowManager
import android.widget.RelativeLayout
import android.widget.TextView
import androidx.core.content.ContextCompat
import com.ustwo.clockwise.common.WatchFaceTime
import com.ustwo.clockwise.common.WatchMode
import com.ustwo.clockwise.common.WatchShape
import com.ustwo.clockwise.wearable.WatchFace
import dagger.android.AndroidInjection
import info.nightscout.androidaps.R
import info.nightscout.androidaps.events.EventWearToMobile
import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.interaction.menus.MainMenuActivity
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP
import info.nightscout.shared.weardata.EventData
import info.nightscout.shared.weardata.EventData.ActionResendData
import info.nightscout.shared.weardata.EventData.SingleBg
import info.nightscout.shared.weardata.EventData.TreatmentData
import io.reactivex.rxjava3.disposables.CompositeDisposable
import lecho.lib.hellocharts.view.LineChartView
import javax.inject.Inject
import kotlin.math.floor
class BigChartWatchface : WatchFace() {
@Inject lateinit var rxBus: RxBus
@Inject lateinit var aapsSchedulers: AapsSchedulers
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var sp: SP
@Inject lateinit var dateUtil: DateUtil
private var disposable = CompositeDisposable()
private var singleBg = SingleBg(0, "---", "-", "--", "--", "--", 0, 0.0, 0.0, 0.0, 0)
private var status = EventData.Status("no status", "IOB", "-.--", false, "--g", "-.--U/h", "--", "--", -1, "--", false, 1)
private var treatmentData = TreatmentData(java.util.ArrayList(), java.util.ArrayList(), java.util.ArrayList(), java.util.ArrayList())
private var graphData = EventData.GraphData(java.util.ArrayList())
private var mTime: TextView? = null
private var mSgv: TextView? = null
private var mTimestamp: TextView? = null
private var mDelta: TextView? = null
private var mAvgDelta: TextView? = null
private var mRelativeLayout: RelativeLayout? = null
private var ageLevel = 1
private var highColor = Color.YELLOW
private var lowColor = Color.RED
private var midColor = Color.WHITE
private var gridColour = Color.WHITE
private var basalBackgroundColor = Color.BLUE
private var basalCenterColor = Color.BLUE
private var bolusColor = Color.MAGENTA
private var carbsColor = Color.GREEN
private var pointSize = 2
private var lowResMode = false
private var layoutSet = false
var chart: LineChartView? = null
private var bgDataList = ArrayList<SingleBg>()
private var wakeLock: PowerManager.WakeLock? = null
private var layoutView: View? = null
private val displaySize = Point()
private var specW = 0
private var specH = 0
private var statusView: TextView? = null
private var chartTapTime = 0L
private var sgvTapTime = 0L
@SuppressLint("InflateParams")
override fun onCreate() {
AndroidInjection.inject(this)
super.onCreate()
val display = (getSystemService(WINDOW_SERVICE) as WindowManager).defaultDisplay
display.getSize(displaySize)
wakeLock = (getSystemService(POWER_SERVICE) as PowerManager).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidAPS:BIGChart")
specW = View.MeasureSpec.makeMeasureSpec(displaySize.x, View.MeasureSpec.EXACTLY)
specH = View.MeasureSpec.makeMeasureSpec(displaySize.y, View.MeasureSpec.EXACTLY)
val inflater = getSystemService(LAYOUT_INFLATER_SERVICE) as LayoutInflater
val metrics = resources.displayMetrics
layoutView = if (metrics.widthPixels < SCREEN_SIZE_SMALL || metrics.heightPixels < SCREEN_SIZE_SMALL) {
inflater.inflate(R.layout.activity_bigchart_small, null)
} else {
inflater.inflate(R.layout.activity_bigchart, null)
}
performViewSetup()
disposable.add(rxBus
.toObservable(SingleBg::class.java)
.observeOn(aapsSchedulers.main)
.subscribe { event ->
aapsLogger.debug(LTag.WEAR, "SingleBg received")
singleBg = event
mSgv?.text = singleBg.sgvString
mSgv?.let { mSgv ->
if (ageLevel() <= 0) mSgv.paintFlags = mSgv.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
else mSgv.paintFlags = mSgv.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv()
}
mTime?.text = dateUtil.timeString()
mDelta?.text = singleBg.delta
mAvgDelta?.text = singleBg.avgDelta
}
)
disposable.add(rxBus
.toObservable(TreatmentData::class.java)
.observeOn(aapsSchedulers.main)
.subscribe { event -> treatmentData = event }
)
disposable.add(rxBus
.toObservable(EventData.GraphData::class.java)
.observeOn(aapsSchedulers.main)
.subscribe { event -> graphData = event }
)
disposable.add(rxBus
.toObservable(EventData.Status::class.java)
.observeOn(aapsSchedulers.main)
.subscribe { event ->
// this event is received as last batch of data
aapsLogger.debug(LTag.WEAR, "Status received")
status = event
showAgeAndStatus()
addToWatchSet()
mRelativeLayout?.measure(specW, specH)
mRelativeLayout?.layout(0, 0, mRelativeLayout?.measuredWidth ?: 0, mRelativeLayout?.measuredHeight ?: 0)
invalidate()
setColor()
}
)
disposable.add(rxBus
.toObservable(EventData.Preferences::class.java)
.observeOn(aapsSchedulers.main)
.subscribe {
setColor()
if (layoutSet) {
showAgeAndStatus()
mRelativeLayout?.measure(specW, specH)
mRelativeLayout?.layout(0, 0, mRelativeLayout?.measuredWidth ?: 0, mRelativeLayout?.measuredHeight ?: 0)
}
invalidate()
}
)
}
override fun onLayout(shape: WatchShape, screenBounds: Rect, screenInsets: WindowInsets) {
super.onLayout(shape, screenBounds, screenInsets)
layoutView?.onApplyWindowInsets(screenInsets)
}
private fun performViewSetup() {
mTime = layoutView?.findViewById(R.id.watch_time)
mSgv = layoutView?.findViewById(R.id.sgv)
mTimestamp = layoutView?.findViewById(R.id.timestamp)
mDelta = layoutView?.findViewById(R.id.delta)
mAvgDelta = layoutView?.findViewById(R.id.avgdelta)
mRelativeLayout = layoutView?.findViewById(R.id.main_layout)
chart = layoutView?.findViewById(R.id.chart)
statusView = layoutView?.findViewById(R.id.aps_status)
layoutSet = true
showAgeAndStatus()
mRelativeLayout?.measure(specW, specH)
mRelativeLayout?.layout(0, 0, mRelativeLayout?.measuredWidth ?: 0, mRelativeLayout?.measuredHeight ?: 0)
rxBus.send(EventWearToMobile(ActionResendData("BIGChart:performViewSetup")))
wakeLock?.acquire(50)
}
override fun onTapCommand(tapType: Int, x: Int, y: Int, eventTime: Long) {
chart?.let { chart ->
mSgv?.let { mSgv ->
val extra = (mSgv.right - mSgv.left) / 2
if (tapType == TAP_TYPE_TAP && x >= chart.left && x <= chart.right && y >= chart.top && y <= chart.bottom) {
if (eventTime - chartTapTime < 800) {
changeChartTimeframe()
}
chartTapTime = eventTime
} else if (tapType == TAP_TYPE_TAP && x + extra >= mSgv.left && x - extra <= mSgv.right && y >= mSgv.top && y <= mSgv.bottom) {
if (eventTime - sgvTapTime < 800) {
val intent = Intent(this, MainMenuActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
}
sgvTapTime = eventTime
}
}
}
}
private fun changeChartTimeframe() {
var timeframe = sp.getInt(R.string.key_chart_time_frame, 3)
timeframe = timeframe % 5 + 1
sp.putInt(R.string.key_chart_time_frame, timeframe)
}
override fun onWatchModeChanged(watchMode: WatchMode) {
if (lowResMode xor isLowRes(watchMode)) { //if there was a change in lowResMode
lowResMode = isLowRes(watchMode)
setColor()
} else if (!sp.getBoolean("dark", true)) {
//in bright mode: different colours if active:
setColor()
}
}
private fun isLowRes(watchMode: WatchMode): Boolean {
return watchMode == WatchMode.LOW_BIT || watchMode == WatchMode.LOW_BIT_BURN_IN
}
override fun getWatchFaceStyle(): WatchFaceStyle {
return WatchFaceStyle.Builder(this).setAcceptsTapEvents(true).build()
}
private fun ageLevel(): Int {
return if (timeSince() <= 1000 * 60 * 12) {
1
} else {
0
}
}
fun timeSince(): Double {
return (System.currentTimeMillis() - singleBg.timeStamp).toDouble()
}
private fun readingAge(): String {
if (singleBg.timeStamp == 0L) return "--'"
val minutesAgo = floor(timeSince() / (1000 * 60)).toInt()
return if (minutesAgo == 1) "$minutesAgo'"
else "$minutesAgo'"
}
override fun onDestroy() {
disposable.clear()
super.onDestroy()
}
override fun onDraw(canvas: Canvas) {
if (layoutSet) {
mRelativeLayout?.draw(canvas)
}
}
override fun onTimeChanged(oldTime: WatchFaceTime, newTime: WatchFaceTime) {
if (layoutSet && (newTime.hasHourChanged(oldTime) || newTime.hasMinuteChanged(oldTime))) {
wakeLock?.acquire(50)
mTime?.text = dateUtil.timeString()
showAgeAndStatus()
mSgv?.let { mSgv ->
if (ageLevel() <= 0) mSgv.paintFlags = mSgv.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
else mSgv.paintFlags = mSgv.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv()
}
missedReadingAlert()
mRelativeLayout?.measure(specW, specH)
mRelativeLayout?.layout(0, 0, mRelativeLayout?.measuredWidth ?: 0, mRelativeLayout?.measuredHeight ?: 0)
}
}
private fun showAgeAndStatus() {
mTimestamp?.text = readingAge()
mAvgDelta?.visibility = sp.getBoolean(R.string.key_show_external_status, true).toVisibility()
statusView?.visibility = sp.getBoolean(R.string.key_show_external_status, true).toVisibility()
statusView?.text = status.externalStatus + if (sp.getBoolean(R.string.key_show_cob, true)) (" " + this.status.cob) else ""
}
private fun setColor() {
when {
lowResMode -> setColorLowRes()
sp.getBoolean("dark", true) -> setColorDark()
else -> setColorBright()
}
}
private fun setColorLowRes() {
mTime?.setTextColor(ContextCompat.getColor(this, R.color.dark_mTime))
statusView?.setTextColor(ContextCompat.getColor(this, R.color.dark_statusView))
mRelativeLayout?.setBackgroundColor(ContextCompat.getColor(this, R.color.dark_background))
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mDelta?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mAvgDelta?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mTimestamp?.setTextColor(ContextCompat.getColor(this, R.color.dark_Timestamp))
if (chart != null) {
highColor = ContextCompat.getColor(this, R.color.dark_midColor)
lowColor = ContextCompat.getColor(this, R.color.dark_midColor)
midColor = ContextCompat.getColor(this, R.color.dark_midColor)
gridColour = ContextCompat.getColor(this, R.color.dark_gridColor)
basalBackgroundColor = ContextCompat.getColor(this, R.color.basal_dark_lowres)
basalCenterColor = ContextCompat.getColor(this, R.color.basal_light_lowres)
pointSize = 2
setupCharts()
}
}
private fun setColorDark() {
mTime?.setTextColor(ContextCompat.getColor(this, R.color.dark_mTime))
statusView?.setTextColor(ContextCompat.getColor(this, R.color.dark_statusView))
mRelativeLayout?.setBackgroundColor(ContextCompat.getColor(this, R.color.dark_background))
when (singleBg.sgvLevel) {
1L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor))
mDelta?.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor))
mAvgDelta?.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor))
}
0L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mDelta?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mAvgDelta?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
}
-1L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor))
mDelta?.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor))
mAvgDelta?.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor))
}
}
if (ageLevel == 1) {
mTimestamp?.setTextColor(ContextCompat.getColor(this, R.color.dark_Timestamp))
} else {
mTimestamp?.setTextColor(ContextCompat.getColor(this, R.color.dark_TimestampOld))
}
if (chart != null) {
highColor = ContextCompat.getColor(this, R.color.dark_highColor)
lowColor = ContextCompat.getColor(this, R.color.dark_lowColor)
midColor = ContextCompat.getColor(this, R.color.dark_midColor)
gridColour = ContextCompat.getColor(this, R.color.dark_gridColor)
basalBackgroundColor = ContextCompat.getColor(this, R.color.basal_dark)
basalCenterColor = ContextCompat.getColor(this, R.color.basal_light)
pointSize = 2
setupCharts()
}
}
private fun setColorBright() {
if (currentWatchMode == WatchMode.INTERACTIVE) {
mTime?.setTextColor(ContextCompat.getColor(this, R.color.light_bigchart_time))
statusView?.setTextColor(ContextCompat.getColor(this, R.color.light_bigchart_status))
mRelativeLayout?.setBackgroundColor(ContextCompat.getColor(this, R.color.light_background))
when (singleBg.sgvLevel) {
1L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.light_highColor))
mDelta?.setTextColor(ContextCompat.getColor(this, R.color.light_highColor))
mAvgDelta?.setTextColor(ContextCompat.getColor(this, R.color.light_highColor))
}
0L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.light_midColor))
mDelta?.setTextColor(ContextCompat.getColor(this, R.color.light_midColor))
mAvgDelta?.setTextColor(ContextCompat.getColor(this, R.color.light_midColor))
}
-1L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.light_lowColor))
mDelta?.setTextColor(ContextCompat.getColor(this, R.color.light_lowColor))
mAvgDelta?.setTextColor(ContextCompat.getColor(this, R.color.light_lowColor))
}
}
if (ageLevel == 1) mTimestamp?.setTextColor(ContextCompat.getColor(this, R.color.light_mTimestamp1))
else mTimestamp?.setTextColor(ContextCompat.getColor(this, R.color.light_mTimestamp))
if (chart != null) {
highColor = ContextCompat.getColor(this, R.color.light_highColor)
lowColor = ContextCompat.getColor(this, R.color.light_lowColor)
midColor = ContextCompat.getColor(this, R.color.light_midColor)
gridColour = ContextCompat.getColor(this, R.color.light_gridColor)
basalBackgroundColor = ContextCompat.getColor(this, R.color.basal_light)
basalCenterColor = ContextCompat.getColor(this, R.color.basal_dark)
pointSize = 2
setupCharts()
}
} else {
setColorDark()
}
}
private fun missedReadingAlert() {
val minutesSince = floor(timeSince() / (1000 * 60)).toInt()
if (minutesSince >= 16 && (minutesSince - 16) % 5 == 0) {
// attempt endTime recover missing data
rxBus.send(EventWearToMobile(ActionResendData("BIGChart:missedReadingAlert")))
}
}
private fun addToWatchSet() {
bgDataList = graphData.entries
}
private fun setupCharts() {
if (bgDataList.size > 0) {
val timeframe = sp.getInt(R.string.key_chart_time_frame, 3)
val bgGraphBuilder = if (lowResMode) {
BgGraphBuilder(
sp, dateUtil, bgDataList, treatmentData.predictions, treatmentData.temps, treatmentData.basals, treatmentData.boluses, pointSize,
midColor, gridColour, basalBackgroundColor, basalCenterColor, bolusColor, carbsColor, timeframe
)
} else {
BgGraphBuilder(
sp, dateUtil, bgDataList, treatmentData.predictions, treatmentData.temps, treatmentData.basals, treatmentData.boluses, pointSize,
highColor, lowColor, midColor, gridColour, basalBackgroundColor, basalCenterColor, bolusColor, carbsColor, timeframe
)
}
chart?.lineChartData = bgGraphBuilder.lineData()
chart?.isViewportCalculationEnabled = true
} else {
rxBus.send(EventWearToMobile(ActionResendData("BIGChart:setupCharts")))
}
}
companion object {
private const val SCREEN_SIZE_SMALL = 280
}
}

View file

@ -1,534 +0,0 @@
package info.nightscout.androidaps.watchfaces;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.RectF;
import android.os.PowerManager;
import android.support.wearable.watchface.WatchFaceStyle;
import android.util.TypedValue;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;
import com.ustwo.clockwise.common.WatchFaceTime;
import com.ustwo.clockwise.wearable.WatchFace;
import java.util.ArrayList;
import java.util.Calendar;
import javax.inject.Inject;
import dagger.android.AndroidInjection;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.events.EventWearToMobile;
import info.nightscout.androidaps.interaction.menus.MainMenuActivity;
import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.utils.rx.AapsSchedulers;
import info.nightscout.shared.logging.AAPSLogger;
import info.nightscout.shared.logging.LTag;
import info.nightscout.shared.sharedPreferences.SP;
import info.nightscout.shared.weardata.EventData;
import io.reactivex.rxjava3.disposables.CompositeDisposable;
public class CircleWatchface extends WatchFace {
@Inject RxBus rxBus;
@Inject AapsSchedulers aapsSchedulers;
@Inject AAPSLogger aapsLogger;
@Inject SP sp;
CompositeDisposable disposable = new CompositeDisposable();
private EventData.SingleBg singleBg = new EventData.SingleBg(0, "---", "-", "--", "--", "--", 0, 0.0, 0.0, 0.0, 0);
private EventData.GraphData graphData;
private EventData.Status status = new EventData.Status("no status", "IOB", "-.--", false, "--g", "-.--U/h", "--", "--", -1, "--", false, 1);
public final float PADDING = 20f;
public final float CIRCLE_WIDTH = 10f;
public final int BIG_HAND_WIDTH = 16;
public final int SMALL_HAND_WIDTH = 8;
public final int NEAR = 2; //how near do the hands have endTime be endTime activate overlapping mode
public final boolean ALWAYS_HIGHLIGT_SMALL = false;
//variables for time
private float angleBig = 0f;
private float angleSMALL = 0f;
private int color;
private final Paint circlePaint = new Paint();
private final Paint removePaint = new Paint();
private RectF rect, rectDelete;
private boolean overlapping;
public Point displaySize = new Point();
public ArrayList<EventData.SingleBg> bgDataList = new ArrayList<>();
private int specW;
private int specH;
private View myLayout;
private TextView mSgv;
private long sgvTapTime = 0;
@SuppressLint("InflateParams") @Override
public void onCreate() {
AndroidInjection.inject(this);
super.onCreate();
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidAPS:CircleWatchface");
wakeLock.acquire(30000);
Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay();
display.getSize(displaySize);
specW = View.MeasureSpec.makeMeasureSpec(displaySize.x,
View.MeasureSpec.EXACTLY);
specH = View.MeasureSpec.makeMeasureSpec(displaySize.y,
View.MeasureSpec.EXACTLY);
//register Message Receiver
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
myLayout = inflater.inflate(R.layout.activity_circle, null);
prepareLayout();
prepareDrawTime();
disposable.add(rxBus
.toObservable(EventData.SingleBg.class)
.observeOn(aapsSchedulers.getMain())
.subscribe(event -> singleBg = event)
);
disposable.add(rxBus
.toObservable(EventData.GraphData.class)
.observeOn(aapsSchedulers.getMain())
.subscribe(event -> graphData = event)
);
disposable.add(rxBus
.toObservable(EventData.Status.class)
.observeOn(aapsSchedulers.getMain())
.subscribe(event -> {
// this event is received as last batch of data
aapsLogger.debug(LTag.WEAR, "Status received");
status = event;
addToWatchSet();
prepareLayout();
prepareDrawTime();
invalidate();
})
);
disposable.add(rxBus
.toObservable(EventData.Preferences.class)
.observeOn(aapsSchedulers.getMain())
.subscribe(event -> {
prepareDrawTime();
prepareLayout();
invalidate();
})
);
rxBus.send(new EventWearToMobile(new EventData.ActionResendData("CircleWatchFace::onCreate")));
wakeLock.release();
}
@Override
public void onDestroy() {
disposable.clear();
super.onDestroy();
}
@Override
protected synchronized void onDraw(Canvas canvas) {
aapsLogger.debug(LTag.WEAR, "start onDraw");
canvas.drawColor(getBackgroundColor());
drawTime(canvas);
drawOtherStuff(canvas);
myLayout.draw(canvas);
}
private synchronized void prepareLayout() {
aapsLogger.debug(LTag.WEAR, "start startPrepareLayout");
// prepare fields
mSgv = myLayout.findViewById(R.id.sgvString);
if (sp.getBoolean("showBG", true)) {
mSgv.setVisibility(View.VISIBLE);
mSgv.setText(singleBg.getSgvString());
mSgv.setTextColor(getTextColor());
} else {
//Also possible: View.INVISIBLE instead of View.GONE (no layout change)
mSgv.setVisibility(View.INVISIBLE);
}
TextView textView = myLayout.findViewById(R.id.statusString);
if (sp.getBoolean("showExternalStatus", true)) {
textView.setVisibility(View.VISIBLE);
textView.setText(status.getExternalStatus());
textView.setTextColor(getTextColor());
} else {
//Also possible: View.INVISIBLE instead of View.GONE (no layout change)
textView.setVisibility(View.GONE);
}
textView = myLayout.findViewById(R.id.agoString);
if (sp.getBoolean("showAgo", true)) {
textView.setVisibility(View.VISIBLE);
if (sp.getBoolean("showBigNumbers", false)) {
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 26);
} else {
((TextView) myLayout.findViewById(R.id.agoString)).setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
}
textView.setText(getMinutes());
textView.setTextColor(getTextColor());
} else {
//Also possible: View.INVISIBLE instead of View.GONE (no layout change)
textView.setVisibility(View.INVISIBLE);
}
textView = myLayout.findViewById(R.id.deltaString);
if (sp.getBoolean("showDelta", true)) {
textView.setVisibility(View.VISIBLE);
textView.setText(singleBg.getDelta());
textView.setTextColor(getTextColor());
if (sp.getBoolean("showBigNumbers", false)) {
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 25);
} else {
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
}
if (sp.getBoolean("showAvgDelta", true)) {
textView.append(" " + singleBg.getAvgDelta());
}
} else {
//Also possible: View.INVISIBLE instead of View.GONE (no layout change)
textView.setVisibility(View.INVISIBLE);
}
myLayout.measure(specW, specH);
myLayout.layout(0, 0, myLayout.getMeasuredWidth(),
myLayout.getMeasuredHeight());
}
public String getMinutes() {
String minutes = "--'";
if (singleBg.getTimeStamp() != 0) {
minutes = ((int) Math.floor((System.currentTimeMillis() - singleBg.getTimeStamp()) / 60000.0)) + "'";
}
return minutes;
}
private void drawTime(Canvas canvas) {
//draw circle
circlePaint.setColor(color);
circlePaint.setStrokeWidth(CIRCLE_WIDTH);
canvas.drawArc(rect, 0, 360, false, circlePaint);
//"remove" hands from circle
removePaint.setStrokeWidth(CIRCLE_WIDTH * 3);
canvas.drawArc(rectDelete, angleBig, (float) BIG_HAND_WIDTH, false, removePaint);
canvas.drawArc(rectDelete, angleSMALL, (float) SMALL_HAND_WIDTH, false, removePaint);
if (overlapping) {
//add small hand with extra
circlePaint.setStrokeWidth(CIRCLE_WIDTH * 2);
circlePaint.setColor(color);
canvas.drawArc(rect, angleSMALL, (float) SMALL_HAND_WIDTH, false, circlePaint);
//remove inner part of hands
removePaint.setStrokeWidth(CIRCLE_WIDTH);
canvas.drawArc(rect, angleBig, (float) BIG_HAND_WIDTH, false, removePaint);
canvas.drawArc(rect, angleSMALL, (float) SMALL_HAND_WIDTH, false, removePaint);
}
}
private synchronized void prepareDrawTime() {
aapsLogger.debug(LTag.WEAR, "start prepareDrawTime");
int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY) % 12;
int minute = Calendar.getInstance().get(Calendar.MINUTE);
angleBig = (((hour + minute / 60f) / 12f * 360) - 90 - BIG_HAND_WIDTH / 2f + 360) % 360;
angleSMALL = ((minute / 60f * 360) - 90 - SMALL_HAND_WIDTH / 2f + 360) % 360;
color = 0;
switch ((int) singleBg.getSgvLevel()) {
case -1:
color = getLowColor();
break;
case 0:
color = getInRangeColor();
break;
case 1:
color = getHighColor();
break;
}
circlePaint.setShader(null);
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setStrokeWidth(CIRCLE_WIDTH);
circlePaint.setAntiAlias(true);
circlePaint.setColor(color);
removePaint.setStyle(Paint.Style.STROKE);
removePaint.setStrokeWidth(CIRCLE_WIDTH);
removePaint.setAntiAlias(true);
removePaint.setColor(getBackgroundColor());
rect = new RectF(PADDING, PADDING, displaySize.x - PADDING, displaySize.y - PADDING);
rectDelete = new RectF(PADDING - CIRCLE_WIDTH / 2, PADDING - CIRCLE_WIDTH / 2, displaySize.x - PADDING + CIRCLE_WIDTH / 2, displaySize.y - PADDING + CIRCLE_WIDTH / 2);
overlapping = ALWAYS_HIGHLIGT_SMALL || areOverlapping(angleSMALL, angleSMALL + SMALL_HAND_WIDTH + NEAR, angleBig, angleBig + BIG_HAND_WIDTH + NEAR);
aapsLogger.debug(LTag.WEAR, "end prepareDrawTime");
}
private boolean areOverlapping(float aBegin, float aEnd, float bBegin, float bEnd) {
return
aBegin <= bBegin && aEnd >= bBegin ||
aBegin <= bBegin && (bEnd > 360) && bEnd % 360 > aBegin ||
bBegin <= aBegin && bEnd >= aBegin ||
bBegin <= aBegin && aEnd > 360 && aEnd % 360 > bBegin;
}
@Override
protected void onTimeChanged(WatchFaceTime oldTime, WatchFaceTime newTime) {
if (oldTime.hasMinuteChanged(newTime)) {
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidAPS:CircleWatchface_onTimeChanged");
wakeLock.acquire(30000);
/*Preparing the layout just on every minute tick:
* - hopefully better battery life
* - drawback: might update the minutes since last reading up endTime one minute late*/
prepareLayout();
prepareDrawTime();
invalidate(); //redraw the time
wakeLock.release();
}
}
// defining color for dark and bright
public int getLowColor() {
if (sp.getBoolean("dark", true)) {
return Color.argb(255, 255, 120, 120);
} else {
return Color.argb(255, 255, 80, 80);
}
}
public int getInRangeColor() {
if (sp.getBoolean("dark", true)) {
return Color.argb(255, 120, 255, 120);
} else {
return Color.argb(255, 0, 240, 0);
}
}
public int getHighColor() {
if (sp.getBoolean("dark", true)) {
return Color.argb(255, 255, 255, 120);
} else {
return Color.argb(255, 255, 200, 0);
}
}
public int getBackgroundColor() {
if (sp.getBoolean("dark", true)) {
return Color.BLACK;
} else {
return Color.WHITE;
}
}
public int getTextColor() {
if (sp.getBoolean("dark", true)) {
return Color.WHITE;
} else {
return Color.BLACK;
}
}
public void drawOtherStuff(Canvas canvas) {
aapsLogger.debug(LTag.WEAR, "start onDrawOtherStuff. bgDataList.size(): " + bgDataList.size());
if (sp.getBoolean("showRingHistory", false)) {
//Perfect low and High indicators
if (bgDataList.size() > 0) {
addIndicator(canvas, 100, Color.LTGRAY);
addIndicator(canvas, (float) bgDataList.iterator().next().getLow(), getLowColor());
addIndicator(canvas, (float) bgDataList.iterator().next().getHigh(), getHighColor());
if (sp.getBoolean("softRingHistory", true)) {
for (EventData.SingleBg data : bgDataList) {
addReadingSoft(canvas, data);
}
} else {
for (EventData.SingleBg data : bgDataList) {
addReading(canvas, data);
}
}
}
}
}
public synchronized void addToWatchSet() {
bgDataList.clear();
if (!sp.getBoolean("showRingHistory", false)) return;
double threshold = (System.currentTimeMillis() - (1000L * 60 * 30)); // 30 min
for (EventData.SingleBg entry : graphData.getEntries())
if (entry.getTimeStamp() >= threshold) bgDataList.add(entry);
aapsLogger.debug(LTag.WEAR, "addToWatchSet size=" + bgDataList.size());
}
public int darken(int color, double fraction) {
int red = Color.red(color);
int green = Color.green(color);
int blue = Color.blue(color);
red = darkenColor(red, fraction);
green = darkenColor(green, fraction);
blue = darkenColor(blue, fraction);
int alpha = Color.alpha(color);
return Color.argb(alpha, red, green, blue);
}
private int darkenColor(int color, double fraction) {
return (int) Math.max(color - (color * fraction), 0);
}
public void addArch(Canvas canvas, float offset, int color, float size) {
Paint paint = new Paint();
paint.setColor(color);
RectF rectTemp = new RectF(PADDING + offset - CIRCLE_WIDTH / 2, PADDING + offset - CIRCLE_WIDTH / 2, (displaySize.x - PADDING - offset + CIRCLE_WIDTH / 2), (displaySize.y - PADDING - offset + CIRCLE_WIDTH / 2));
canvas.drawArc(rectTemp, 270, size, true, paint);
}
public void addArch(Canvas canvas, float start, float offset, int color, float size) {
Paint paint = new Paint();
paint.setColor(color);
RectF rectTemp = new RectF(PADDING + offset - CIRCLE_WIDTH / 2, PADDING + offset - CIRCLE_WIDTH / 2, (displaySize.x - PADDING - offset + CIRCLE_WIDTH / 2), (displaySize.y - PADDING - offset + CIRCLE_WIDTH / 2));
canvas.drawArc(rectTemp, start + 270, size, true, paint);
}
public void addIndicator(Canvas canvas, float bg, int color) {
float convertedBg;
convertedBg = bgToAngle(bg);
convertedBg += 270;
Paint paint = new Paint();
paint.setColor(color);
float offset = 9;
RectF rectTemp = new RectF(PADDING + offset - CIRCLE_WIDTH / 2, PADDING + offset - CIRCLE_WIDTH / 2, (displaySize.x - PADDING - offset + CIRCLE_WIDTH / 2), (displaySize.y - PADDING - offset + CIRCLE_WIDTH / 2));
canvas.drawArc(rectTemp, convertedBg, 2, true, paint);
}
private float bgToAngle(float bg) {
if (bg > 100) {
return (((bg - 100f) / 300f) * 225f) + 135;
} else {
return ((bg / 100) * 135);
}
}
public void addReadingSoft(Canvas canvas, EventData.SingleBg entry) {
aapsLogger.debug(LTag.WEAR, "addReadingSoft");
double size;
int color = Color.LTGRAY;
if (sp.getBoolean("dark", true)) {
color = Color.DKGRAY;
}
float offsetMultiplier = (((displaySize.x / 2f) - PADDING) / 12f);
float offset = (float) Math.max(1,
Math.ceil((System.currentTimeMillis() - entry.getTimeStamp()) / (1000 * 60 * 5.0)));
size = bgToAngle((float) entry.getSgv());
addArch(canvas, offset * offsetMultiplier + 10, color, (float) size);
addArch(canvas, (float) size, offset * offsetMultiplier + 10, getBackgroundColor(), (float) (360 - size));
addArch(canvas, (offset + .8f) * offsetMultiplier + 10, getBackgroundColor(), 360);
}
public void addReading(Canvas canvas, EventData.SingleBg entry) {
aapsLogger.debug(LTag.WEAR, "addReading");
double size;
int color = Color.LTGRAY;
int indicatorColor = Color.DKGRAY;
if (sp.getBoolean("dark", true)) {
color = Color.DKGRAY;
indicatorColor = Color.LTGRAY;
}
int barColor = Color.GRAY;
if (entry.getSgv() >= entry.getHigh()) {
indicatorColor = getHighColor();
barColor = darken(getHighColor(), .5);
} else if (entry.getSgv() <= entry.getLow()) {
indicatorColor = getLowColor();
barColor = darken(getLowColor(), .5);
}
float offsetMultiplier = (((displaySize.x / 2f) - PADDING) / 12f);
float offset = (float) Math.max(1,
Math.ceil((System.currentTimeMillis() - entry.getTimeStamp()) / (1000 * 60 * 5.0)));
size = bgToAngle((float) entry.getSgv());
addArch(canvas, offset * offsetMultiplier + 11, barColor, (float) size - 2); // Dark Color Bar
addArch(canvas, (float) size - 2, offset * offsetMultiplier + 11, indicatorColor, 2f); // Indicator at end of bar
addArch(canvas, (float) size, offset * offsetMultiplier + 11, color, (float) (360f - size)); // Dark fill
addArch(canvas, (offset + .8f) * offsetMultiplier + 11, getBackgroundColor(), 360);
}
@SuppressWarnings("deprecation")
@Override
protected void onTapCommand(int tapType, int x, int y, long eventTime) {
if (mSgv == null) return;
int extra = (mSgv.getRight() - mSgv.getLeft()) / 2;
if (tapType == TAP_TYPE_TAP &&
x + extra >= mSgv.getLeft() &&
x - extra <= mSgv.getRight() &&
y >= mSgv.getTop() &&
y <= mSgv.getBottom()) {
if (eventTime - sgvTapTime < 800) {
Intent intent = new Intent(this, MainMenuActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
sgvTapTime = eventTime;
}
}
@Override
protected WatchFaceStyle getWatchFaceStyle() {
return new WatchFaceStyle.Builder(this).setAcceptsTapEvents(true).build();
}
}

View file

@ -0,0 +1,445 @@
@file:Suppress("DEPRECATION")
package info.nightscout.androidaps.watchfaces
import android.annotation.SuppressLint
import android.content.Intent
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Point
import android.graphics.RectF
import android.os.PowerManager
import android.support.wearable.watchface.WatchFaceStyle
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
import android.view.WindowManager
import android.widget.TextView
import com.ustwo.clockwise.common.WatchFaceTime
import com.ustwo.clockwise.wearable.WatchFace
import dagger.android.AndroidInjection
import info.nightscout.androidaps.R
import info.nightscout.androidaps.events.EventWearToMobile
import info.nightscout.androidaps.interaction.menus.MainMenuActivity
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP
import info.nightscout.shared.weardata.EventData
import info.nightscout.shared.weardata.EventData.ActionResendData
import info.nightscout.shared.weardata.EventData.SingleBg
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import java.util.*
import javax.inject.Inject
import kotlin.math.ceil
import kotlin.math.floor
import kotlin.math.max
class CircleWatchface : WatchFace() {
@Inject lateinit var rxBus: RxBus
@Inject lateinit var aapsSchedulers: AapsSchedulers
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var sp: SP
private var disposable = CompositeDisposable()
private var singleBg = SingleBg(0, "---", "-", "--", "--", "--", 0, 0.0, 0.0, 0.0, 0)
private var graphData = EventData.GraphData(ArrayList())
private var status = EventData.Status("no status", "IOB", "-.--", false, "--g", "-.--U/h", "--", "--", -1, "--", false, 1)
companion object {
const val PADDING = 20f
const val CIRCLE_WIDTH = 10f
const val BIG_HAND_WIDTH = 16
const val SMALL_HAND_WIDTH = 8
const val NEAR = 2 //how near do the hands have endTime be endTime activate overlapping mode
const val ALWAYS_HIGHLIGHT_SMALL = false
const val fraction = .5
}
//variables for time
private var angleBig = 0f
private var angleSMALL = 0f
private var color = 0
private val circlePaint = Paint()
private val removePaint = Paint()
private lateinit var rect: RectF
private lateinit var rectDelete: RectF
private var overlapping = false
private var displaySize = Point()
private var bgDataList = ArrayList<SingleBg>()
private var specW = 0
private var specH = 0
private var myLayout: View? = null
private var mSgv: TextView? = null
private var sgvTapTime: Long = 0
@SuppressLint("InflateParams")
override fun onCreate() {
AndroidInjection.inject(this)
super.onCreate()
val powerManager = getSystemService(POWER_SERVICE) as PowerManager
val wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidAPS:CircleWatchface")
wakeLock.acquire(30000)
val display = (getSystemService(WINDOW_SERVICE) as WindowManager).defaultDisplay
display.getSize(displaySize)
specW = View.MeasureSpec.makeMeasureSpec(displaySize.x, View.MeasureSpec.EXACTLY)
specH = View.MeasureSpec.makeMeasureSpec(displaySize.y, View.MeasureSpec.EXACTLY)
//register Message Receiver
val inflater = getSystemService(LAYOUT_INFLATER_SERVICE) as LayoutInflater
myLayout = inflater.inflate(R.layout.activity_circle, null)
prepareLayout()
prepareDrawTime()
disposable += rxBus
.toObservable(SingleBg::class.java)
.observeOn(aapsSchedulers.main)
.subscribe { event -> singleBg = event }
disposable += rxBus
.toObservable(EventData.GraphData::class.java)
.observeOn(aapsSchedulers.main)
.subscribe { event -> graphData = event }
disposable += rxBus
.toObservable(EventData.Status::class.java)
.observeOn(aapsSchedulers.main)
.subscribe { event ->
// this event is received as last batch of data
aapsLogger.debug(LTag.WEAR, "Status received")
status = event
addToWatchSet()
prepareLayout()
prepareDrawTime()
invalidate()
}
disposable += rxBus
.toObservable(EventData.Preferences::class.java)
.observeOn(aapsSchedulers.main)
.subscribe {
prepareDrawTime()
prepareLayout()
invalidate()
}
rxBus.send(EventWearToMobile(ActionResendData("CircleWatchFace::onCreate")))
wakeLock.release()
}
override fun onDestroy() {
disposable.clear()
super.onDestroy()
}
@Synchronized override fun onDraw(canvas: Canvas) {
aapsLogger.debug(LTag.WEAR, "start onDraw")
canvas.drawColor(backgroundColor)
drawTime(canvas)
drawOtherStuff(canvas)
myLayout?.draw(canvas)
}
@Synchronized private fun prepareLayout() {
aapsLogger.debug(LTag.WEAR, "start startPrepareLayout")
// prepare fields
mSgv = myLayout?.findViewById(R.id.sgvString)
if (sp.getBoolean(R.string.key_show_bg, true)) {
mSgv?.visibility = View.VISIBLE
mSgv?.text = singleBg.sgvString
mSgv?.setTextColor(textColor)
} else {
//Also possible: View.INVISIBLE instead of View.GONE (no layout change)
mSgv?.visibility = View.INVISIBLE
}
var textView = myLayout?.findViewById<TextView>(R.id.statusString)
if (sp.getBoolean(R.string.key_show_external_status, true)) {
textView?.visibility = View.VISIBLE
textView?.text = status.externalStatus
textView?.setTextColor(textColor)
} else {
//Also possible: View.INVISIBLE instead of View.GONE (no layout change)
textView?.visibility = View.GONE
}
textView = myLayout?.findViewById(R.id.agoString)
if (sp.getBoolean(R.string.key_show_ago, true)) {
textView?.visibility = View.VISIBLE
if (sp.getBoolean(R.string.key_show_big_numbers, false)) {
textView?.setTextSize(TypedValue.COMPLEX_UNIT_SP, 26f)
} else {
(myLayout?.findViewById<View>(R.id.agoString) as TextView).setTextSize(TypedValue.COMPLEX_UNIT_SP, 18f)
}
textView?.text = minutes
textView?.setTextColor(textColor)
} else {
//Also possible: View.INVISIBLE instead of View.GONE (no layout change)
textView?.visibility = View.INVISIBLE
}
textView = myLayout?.findViewById(R.id.deltaString)
if (sp.getBoolean(R.string.key_show_delta, true)) {
textView?.visibility = View.VISIBLE
textView?.text = singleBg.delta
textView?.setTextColor(textColor)
if (sp.getBoolean(R.string.key_show_big_numbers, false)) {
textView?.setTextSize(TypedValue.COMPLEX_UNIT_SP, 25f)
} else {
textView?.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18f)
}
if (sp.getBoolean(R.string.key_show_avg_delta, true)) {
textView?.append(" " + singleBg.avgDelta)
}
} else {
//Also possible: View.INVISIBLE instead of View.GONE (no layout change)
textView?.visibility = View.INVISIBLE
}
myLayout?.measure(specW, specH)
myLayout?.layout(0, 0, myLayout?.measuredWidth ?: 0, myLayout?.measuredHeight ?: 0)
}
val minutes: String
get() {
var minutes = "--'"
if (singleBg.timeStamp != 0L) {
minutes = floor((System.currentTimeMillis() - singleBg.timeStamp) / 60000.0).toInt().toString() + "'"
}
return minutes
}
private fun drawTime(canvas: Canvas) {
//draw circle
circlePaint.color = color
circlePaint.strokeWidth = CIRCLE_WIDTH
canvas.drawArc(rect, 0f, 360f, false, circlePaint)
//"remove" hands from circle
removePaint.strokeWidth = CIRCLE_WIDTH * 3
canvas.drawArc(rectDelete, angleBig, BIG_HAND_WIDTH.toFloat(), false, removePaint)
canvas.drawArc(rectDelete, angleSMALL, SMALL_HAND_WIDTH.toFloat(), false, removePaint)
if (overlapping) {
//add small hand with extra
circlePaint.strokeWidth = CIRCLE_WIDTH * 2
circlePaint.color = color
canvas.drawArc(rect, angleSMALL, SMALL_HAND_WIDTH.toFloat(), false, circlePaint)
//remove inner part of hands
removePaint.strokeWidth = CIRCLE_WIDTH
canvas.drawArc(rect, angleBig, BIG_HAND_WIDTH.toFloat(), false, removePaint)
canvas.drawArc(rect, angleSMALL, SMALL_HAND_WIDTH.toFloat(), false, removePaint)
}
}
@Synchronized private fun prepareDrawTime() {
aapsLogger.debug(LTag.WEAR, "start prepareDrawTime")
val hour = Calendar.getInstance()[Calendar.HOUR_OF_DAY] % 12
val minute = Calendar.getInstance()[Calendar.MINUTE]
angleBig = ((hour + minute / 60f) / 12f * 360 - 90 - BIG_HAND_WIDTH / 2f + 360) % 360
angleSMALL = (minute / 60f * 360 - 90 - SMALL_HAND_WIDTH / 2f + 360) % 360
color = 0
when (singleBg.sgvLevel.toInt()) {
-1 -> color = lowColor
0 -> color = inRangeColor
1 -> color = highColor
}
circlePaint.shader = null
circlePaint.style = Paint.Style.STROKE
circlePaint.strokeWidth = CIRCLE_WIDTH
circlePaint.isAntiAlias = true
circlePaint.color = color
removePaint.style = Paint.Style.STROKE
removePaint.strokeWidth = CIRCLE_WIDTH
removePaint.isAntiAlias = true
removePaint.color = backgroundColor
rect = RectF(PADDING, PADDING, displaySize.x - PADDING, displaySize.y - PADDING)
rectDelete = RectF(PADDING - CIRCLE_WIDTH / 2, PADDING - CIRCLE_WIDTH / 2, displaySize.x - PADDING + CIRCLE_WIDTH / 2, displaySize.y - PADDING + CIRCLE_WIDTH / 2)
overlapping = ALWAYS_HIGHLIGHT_SMALL || areOverlapping(angleSMALL, angleSMALL + SMALL_HAND_WIDTH + NEAR, angleBig, angleBig + BIG_HAND_WIDTH + NEAR)
aapsLogger.debug(LTag.WEAR, "end prepareDrawTime")
}
private fun areOverlapping(aBegin: Float, aEnd: Float, bBegin: Float, bEnd: Float): Boolean {
return bBegin in aBegin..aEnd || aBegin <= bBegin && bEnd > 360 && bEnd % 360 > aBegin || aBegin in bBegin..bEnd || bBegin <= aBegin && aEnd > 360 && aEnd % 360 > bBegin
}
override fun onTimeChanged(oldTime: WatchFaceTime, newTime: WatchFaceTime) {
if (oldTime.hasMinuteChanged(newTime)) {
val powerManager = getSystemService(POWER_SERVICE) as PowerManager
val wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidAPS:CircleWatchface_onTimeChanged")
wakeLock.acquire(30000)
/*Preparing the layout just on every minute tick:
* - hopefully better battery life
* - drawback: might update the minutes since last reading up endTime one minute late*/prepareLayout()
prepareDrawTime()
invalidate() //redraw the time
wakeLock.release()
}
}
// defining color for dark and bright
private val lowColor: Int
get() = if (sp.getBoolean("dark", true)) {
Color.argb(255, 255, 120, 120)
} else {
Color.argb(255, 255, 80, 80)
}
private val inRangeColor: Int
get() = if (sp.getBoolean("dark", true)) {
Color.argb(255, 120, 255, 120)
} else {
Color.argb(255, 0, 240, 0)
}
private val highColor: Int
get() = if (sp.getBoolean("dark", true)) {
Color.argb(255, 255, 255, 120)
} else {
Color.argb(255, 255, 200, 0)
}
private val backgroundColor: Int
get() = if (sp.getBoolean("dark", true)) {
Color.BLACK
} else {
Color.WHITE
}
val textColor: Int
get() = if (sp.getBoolean("dark", true)) {
Color.WHITE
} else {
Color.BLACK
}
private fun drawOtherStuff(canvas: Canvas) {
aapsLogger.debug(LTag.WEAR, "start onDrawOtherStuff. bgDataList.size(): " + bgDataList.size)
if (sp.getBoolean(R.string.key_show_ring_history, false)) {
//Perfect low and High indicators
if (bgDataList.size > 0) {
addIndicator(canvas, 100f, Color.LTGRAY)
addIndicator(canvas, bgDataList.iterator().next().low.toFloat(), lowColor)
addIndicator(canvas, bgDataList.iterator().next().high.toFloat(), highColor)
if (sp.getBoolean("softRingHistory", true)) {
for (data in bgDataList) {
addReadingSoft(canvas, data)
}
} else {
for (data in bgDataList) {
addReading(canvas, data)
}
}
}
}
}
@Synchronized fun addToWatchSet() {
bgDataList.clear()
if (!sp.getBoolean(R.string.key_show_ring_history, false)) return
val threshold = (System.currentTimeMillis() - 1000L * 60 * 30).toDouble() // 30 min
for (entry in graphData.entries) if (entry.timeStamp >= threshold) bgDataList.add(entry)
aapsLogger.debug(LTag.WEAR, "addToWatchSet size=" + bgDataList.size)
}
private fun darken(color: Int): Int {
var red = Color.red(color)
var green = Color.green(color)
var blue = Color.blue(color)
red = darkenColor(red)
green = darkenColor(green)
blue = darkenColor(blue)
val alpha = Color.alpha(color)
return Color.argb(alpha, red, green, blue)
}
private fun darkenColor(color: Int): Int {
return max(color - color * fraction, 0.0).toInt()
}
private fun addArch(canvas: Canvas, offset: Float, color: Int, size: Float) {
val paint = Paint()
paint.color = color
val rectTemp =
RectF(PADDING + offset - CIRCLE_WIDTH / 2, PADDING + offset - CIRCLE_WIDTH / 2, displaySize.x - PADDING - offset + CIRCLE_WIDTH / 2, displaySize.y - PADDING - offset + CIRCLE_WIDTH / 2)
canvas.drawArc(rectTemp, 270f, size, true, paint)
}
private fun addArch(canvas: Canvas, start: Float, offset: Float, color: Int, size: Float) {
val paint = Paint()
paint.color = color
val rectTemp =
RectF(PADDING + offset - CIRCLE_WIDTH / 2, PADDING + offset - CIRCLE_WIDTH / 2, displaySize.x - PADDING - offset + CIRCLE_WIDTH / 2, displaySize.y - PADDING - offset + CIRCLE_WIDTH / 2)
canvas.drawArc(rectTemp, start + 270, size, true, paint)
}
private fun addIndicator(canvas: Canvas, bg: Float, color: Int) {
var convertedBg: Float = bgToAngle(bg)
convertedBg += 270f
val paint = Paint()
paint.color = color
val offset = 9f
val rectTemp =
RectF(PADDING + offset - CIRCLE_WIDTH / 2, PADDING + offset - CIRCLE_WIDTH / 2, displaySize.x - PADDING - offset + CIRCLE_WIDTH / 2, displaySize.y - PADDING - offset + CIRCLE_WIDTH / 2)
canvas.drawArc(rectTemp, convertedBg, 2f, true, paint)
}
private fun bgToAngle(bg: Float): Float {
return if (bg > 100) {
(bg - 100f) / 300f * 225f + 135
} else {
bg / 100 * 135
}
}
private fun addReadingSoft(canvas: Canvas, entry: SingleBg) {
aapsLogger.debug(LTag.WEAR, "addReadingSoft")
var color = Color.LTGRAY
if (sp.getBoolean("dark", true)) {
color = Color.DKGRAY
}
val offsetMultiplier = (displaySize.x / 2f - PADDING) / 12f
val offset = max(1.0, ceil((System.currentTimeMillis() - entry.timeStamp) / (1000 * 60 * 5.0))).toFloat()
val size: Double = bgToAngle(entry.sgv.toFloat()).toDouble()
addArch(canvas, offset * offsetMultiplier + 10, color, size.toFloat())
addArch(canvas, size.toFloat(), offset * offsetMultiplier + 10, backgroundColor, (360 - size).toFloat())
addArch(canvas, (offset + .8f) * offsetMultiplier + 10, backgroundColor, 360f)
}
private fun addReading(canvas: Canvas, entry: SingleBg) {
aapsLogger.debug(LTag.WEAR, "addReading")
var color = Color.LTGRAY
var indicatorColor = Color.DKGRAY
if (sp.getBoolean("dark", true)) {
color = Color.DKGRAY
indicatorColor = Color.LTGRAY
}
var barColor = Color.GRAY
if (entry.sgv >= entry.high) {
indicatorColor = highColor
barColor = darken(highColor)
} else if (entry.sgv <= entry.low) {
indicatorColor = lowColor
barColor = darken(lowColor)
}
val offsetMultiplier = (displaySize.x / 2f - PADDING) / 12f
val offset = max(1.0, ceil((System.currentTimeMillis() - entry.timeStamp) / (1000 * 60 * 5.0))).toFloat()
val size: Double = bgToAngle(entry.sgv.toFloat()).toDouble()
addArch(canvas, offset * offsetMultiplier + 11, barColor, size.toFloat() - 2) // Dark Color Bar
addArch(canvas, size.toFloat() - 2, offset * offsetMultiplier + 11, indicatorColor, 2f) // Indicator at end of bar
addArch(canvas, size.toFloat(), offset * offsetMultiplier + 11, color, (360f - size).toFloat()) // Dark fill
addArch(canvas, (offset + .8f) * offsetMultiplier + 11, backgroundColor, 360f)
}
override fun onTapCommand(tapType: Int, x: Int, y: Int, eventTime: Long) {
mSgv?.let { mSgv ->
val extra = (mSgv.right - mSgv.left) / 2
if (tapType == TAP_TYPE_TAP && x + extra >= mSgv.left && x - extra <= mSgv.right && y >= mSgv.top && y <= mSgv.bottom) {
if (eventTime - sgvTapTime < 800) {
val intent = Intent(this, MainMenuActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
}
sgvTapTime = eventTime
}
}
}
override fun getWatchFaceStyle(): WatchFaceStyle {
return WatchFaceStyle.Builder(this).setAcceptsTapEvents(true).build()
}
}

View file

@ -1,122 +0,0 @@
package info.nightscout.androidaps.watchfaces;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.support.wearable.watchface.WatchFaceStyle;
import android.view.LayoutInflater;
import android.view.View;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interaction.menus.MainMenuActivity;
/**
* Created by andrew-warrington on 18/11/2017.
*/
public class Cockpit extends BaseWatchFace {
private long sgvTapTime = 0;
@SuppressLint("InflateParams") @Override
public void onCreate() {
super.onCreate();
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
layoutView = inflater.inflate(R.layout.activity_cockpit, null);
performViewSetup();
}
@Override
protected void onTapCommand(int tapType, int x, int y, long eventTime) {
if (tapType == TAP_TYPE_TAP ) {
if (eventTime - sgvTapTime < 800) {
Intent intent = new Intent(this, MainMenuActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
sgvTapTime = eventTime;
}
}
@SuppressWarnings("deprecation")
@Override
protected WatchFaceStyle getWatchFaceStyle() {
return new WatchFaceStyle.Builder(this).setAcceptsTapEvents(true).build();
}
protected void setColorDark() {
mRelativeLayout.setBackgroundResource(R.drawable.airplane_cockpit_outside_clouds);
setTextSizes();
if (mHighLight != null && mLowLight != null) {
if (singleBg.getSgvLevel() == 1) {
mHighLight.setBackgroundResource(R.drawable.airplane_led_yellow_lit);
mLowLight.setBackgroundResource(R.drawable.airplane_led_grey_unlit);
} else if (singleBg.getSgvLevel() == 0) {
mHighLight.setBackgroundResource(R.drawable.airplane_led_grey_unlit);
mLowLight.setBackgroundResource(R.drawable.airplane_led_grey_unlit);
} else if (singleBg.getSgvLevel() == -1) {
mHighLight.setBackgroundResource(R.drawable.airplane_led_grey_unlit);
mLowLight.setBackgroundResource(R.drawable.airplane_led_red_lit);
}
}
if (loopLevel == -1) {
mLoop.setBackgroundResource(R.drawable.loop_grey_25);
} else if (loopLevel == 1) {
mLoop.setBackgroundResource(R.drawable.loop_green_25);
} else {
mLoop.setBackgroundResource(R.drawable.loop_red_25);
}
invalidate();
}
protected void setColorLowRes() {
mRelativeLayout.setBackgroundResource(R.drawable.airplane_cockpit_outside_clouds_lowres);
}
protected void setColorBright() {
setColorDark();
}
protected void setTextSizes() {
if (mIOB2 != null) {
if (status.getDetailedIob()) {
if (bIsRound) {
mIOB2.setTextSize(10);
} else {
mIOB2.setTextSize(9);
}
} else {
if (bIsRound) {
mIOB2.setTextSize(13);
} else {
mIOB2.setTextSize(12);
}
}
}
if ((mUploaderBattery.getVisibility() != View.GONE) && (mRigBattery.getVisibility() != View.GONE)) {
if (bIsRound) {
mUploaderBattery.setTextSize(12);
mRigBattery.setTextSize(12);
} else {
mUploaderBattery.setTextSize(10);
mRigBattery.setTextSize(10);
}
} else {
if (bIsRound) {
mUploaderBattery.setTextSize(13);
mRigBattery.setTextSize(13);
} else {
mUploaderBattery.setTextSize(12);
mRigBattery.setTextSize(12);
}
}
}
}

View file

@ -0,0 +1,105 @@
@file:Suppress("DEPRECATION")
package info.nightscout.androidaps.watchfaces
import android.annotation.SuppressLint
import android.content.Intent
import android.support.wearable.watchface.WatchFaceStyle
import android.view.LayoutInflater
import android.view.View
import info.nightscout.androidaps.R
import info.nightscout.androidaps.interaction.menus.MainMenuActivity
/**
* Created by andrew-warrington on 18/11/2017.
* Refactored by MilosKozak 24/04/2022
*/
class CockpitWatchface : BaseWatchFace() {
private var sgvTapTime: Long = 0
@SuppressLint("InflateParams")
override fun onCreate() {
super.onCreate()
val inflater = getSystemService(LAYOUT_INFLATER_SERVICE) as LayoutInflater
layoutView = inflater.inflate(R.layout.activity_cockpit, null)
performViewSetup()
}
override fun onTapCommand(tapType: Int, x: Int, y: Int, eventTime: Long) {
if (tapType == TAP_TYPE_TAP) {
if (eventTime - sgvTapTime < 800) {
val intent = Intent(this, MainMenuActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
}
sgvTapTime = eventTime
}
}
override fun getWatchFaceStyle(): WatchFaceStyle {
return WatchFaceStyle.Builder(this).setAcceptsTapEvents(true).build()
}
override fun setColorDark() {
mRelativeLayout?.setBackgroundResource(R.drawable.airplane_cockpit_outside_clouds)
setTextSizes()
when (singleBg.sgvLevel) {
1L -> {
mHighLight?.setBackgroundResource(R.drawable.airplane_led_yellow_lit)
mLowLight?.setBackgroundResource(R.drawable.airplane_led_grey_unlit)
}
0L -> {
mHighLight?.setBackgroundResource(R.drawable.airplane_led_grey_unlit)
mLowLight?.setBackgroundResource(R.drawable.airplane_led_grey_unlit)
}
-1L -> {
mHighLight?.setBackgroundResource(R.drawable.airplane_led_grey_unlit)
mLowLight?.setBackgroundResource(R.drawable.airplane_led_red_lit)
}
}
when (loopLevel) {
-1 -> mLoop?.setBackgroundResource(R.drawable.loop_grey_25)
1 -> mLoop?.setBackgroundResource(R.drawable.loop_green_25)
else -> mLoop?.setBackgroundResource(R.drawable.loop_red_25)
}
invalidate()
}
override fun setColorLowRes() {
mRelativeLayout?.setBackgroundResource(R.drawable.airplane_cockpit_outside_clouds_lowres)
}
override fun setColorBright() {
setColorDark()
}
private fun setTextSizes() {
if (status.detailedIob) {
if (bIsRound) mIOB2?.textSize = 10f
else mIOB2?.textSize = 9f
} else {
if (bIsRound) mIOB2?.textSize = 13f
else mIOB2?.textSize = 12f
}
if (mUploaderBattery?.visibility != View.GONE && mRigBattery?.visibility != View.GONE) {
if (bIsRound) {
mUploaderBattery?.textSize = 12f
mRigBattery?.textSize = 12f
} else {
mUploaderBattery?.textSize = 10f
mRigBattery?.textSize = 10f
}
} else {
if (bIsRound) {
mUploaderBattery?.textSize = 13f
mRigBattery?.textSize = 13f
} else {
mUploaderBattery?.textSize = 12f
mRigBattery?.textSize = 12f
}
}
}
}

View file

@ -1,173 +0,0 @@
package info.nightscout.androidaps.watchfaces;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.support.wearable.watchface.WatchFaceStyle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.core.content.ContextCompat;
import java.text.SimpleDateFormat;
import java.util.Date;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interaction.menus.MainMenuActivity;
import info.nightscout.shared.logging.LTag;
public class DigitalStyle extends BaseWatchFace {
private static final long TIME_TAP_THRESHOLD = 800;
private long sgvTapTime = 0;
@SuppressLint("InflateParams") @Override
public void onCreate() {
super.onCreate();
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
layoutView = inflater.inflate(R.layout.activity_digitalstyle, null);
performViewSetup();
}
@Override
protected void onTapCommand(int tapType, int x, int y, long eventTime) {
//tapType = TAP_TYPE_TAP;
aapsLogger.debug(LTag.WEAR,"onTapCommand: DeviceWidth x DeviceHeight /// x , y, TapType >> ", getWidth() + " x " + getHeight() + " /// " + x + " , " + y + " , " + tapType);
if (tapType == TAP_TYPE_TAP) {
if (eventTime - sgvTapTime < TIME_TAP_THRESHOLD) {
Intent intent = new Intent(this, MainMenuActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
sgvTapTime = eventTime;
}
}
@SuppressWarnings("deprecation")
@Override
protected WatchFaceStyle getWatchFaceStyle() {
return new WatchFaceStyle.Builder(this)
.setAcceptsTapEvents(true)
.setHideNotificationIndicator(false)
.setShowUnreadCountIndicator(true)
.build();
}
protected void setColorDark() {
if (singleBg.getSgvLevel() == 1) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor));
mDirection.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor));
} else if (singleBg.getSgvLevel() == 0) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mDirection.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
} else if (singleBg.getSgvLevel() == -1) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor));
mDirection.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor));
}
if (ageLevel == 1) {
mTimestamp.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
} else {
mTimestamp.setTextColor(ContextCompat.getColor(this, R.color.dark_TimestampOld));
}
if (status.getBatteryLevel() == 1) {
mUploaderBattery.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
} else {
mUploaderBattery.setTextColor(ContextCompat.getColor(this, R.color.dark_uploaderBatteryEmpty));
}
if (chart != null) {
highColor = ContextCompat.getColor(this, R.color.dark_highColor);
lowColor = ContextCompat.getColor(this, R.color.dark_lowColor);
midColor = ContextCompat.getColor(this, R.color.dark_midColor);
gridColor = ContextCompat.getColor(this, R.color.dark_gridColor);
basalBackgroundColor = ContextCompat.getColor(this, R.color.basal_dark);
basalCenterColor = ContextCompat.getColor(this, R.color.basal_light);
pointSize = 1;
setupCharts();
setWatchfaceStyle();
}
}
private void setWatchfaceStyle(){
/* frame styles*/
LinearLayout mShapesElements = layoutView.findViewById(R.id.shapes_elements);
if (mShapesElements != null) {
String displayFormatType = (mShapesElements.getContentDescription().toString().startsWith("round") ? "round" : "rect");
String displayStyle=sp.getString("digitalstyle_frameStyle", "full");
String displayFrameColor=sp.getString("digitalstyle_frameColor", "red");
String displayFrameColorSaturation=sp.getString("digitalstyle_frameColorSaturation",
"500");
String displayFrameColorOpacity=sp.getString("digitalstyle_frameColorOpacity", "1");
// Load image with shapes
String styleDrawableName = "digitalstyle_bg_" + displayStyle + "_" + displayFormatType;
try {
mShapesElements.setBackground(getResources().getDrawable(getResources().getIdentifier(styleDrawableName, "drawable", this.getPackageName())));
} catch (Exception e) {
aapsLogger.error("digitalstyle_frameStyle", "RESOURCE NOT FOUND >> " + styleDrawableName);
}
// set background-tint-color
if (displayFrameColor.equalsIgnoreCase("multicolor") || displayStyle.equalsIgnoreCase("none")) {
mShapesElements.setBackgroundTintList(null);
} else {
String strColorName =(( displayFrameColor.equals("white") || displayFrameColor.equals("black") )?displayFrameColor:displayFrameColor+"_"+displayFrameColorSaturation);
aapsLogger.debug(LTag.WEAR,"digitalstyle_strColorName",strColorName);
try {
ColorStateList colorStateList = ContextCompat.getColorStateList(this, getResources().getIdentifier(strColorName, "color", this.getPackageName()));
mShapesElements.setBackgroundTintList(colorStateList);
} catch (Exception e) {
mShapesElements.setBackgroundTintList(null);
aapsLogger.error("digitalstyle_colorName", "COLOR NOT FOUND >> " + strColorName);
}
}
// set opacity of shapes
mShapesElements.setAlpha(Float.parseFloat(displayFrameColorOpacity));
}
/* optimize font-size --> when date is off then increase font-size of time */
Boolean isShowDate = sp.getBoolean("show_date", false);
if (!isShowDate) {
layoutView.findViewById(R.id.date_time).setVisibility(View.GONE);
mHour.setTextSize(62);
mMinute.setTextSize(40);
mHour.setLetterSpacing((float) -0.066);
mMinute.setLetterSpacing((float) -0.066);
} else {
layoutView.findViewById(R.id.date_time).setVisibility(View.VISIBLE);
mHour.setTextSize(40);
mMinute.setTextSize(26);
mHour.setLetterSpacing((float) 0);
mMinute.setLetterSpacing((float) 0);
/* display week number */
Boolean isShowWeekNumber = sp.getBoolean("show_weeknumber", false);
aapsLogger.info(LTag.WEAR,"---------------------------------","weeknumber refresh ");
TextView mWeekNumber= layoutView.findViewById(R.id.weeknumber);
if (isShowWeekNumber) {
mWeekNumber.setVisibility(View.VISIBLE);
mWeekNumber.setText("(" + (new SimpleDateFormat("ww")).format(new Date()) + ")");
} else {
mWeekNumber.setVisibility(View.GONE);
mWeekNumber.setText("");
}
}
}
protected void setColorLowRes() {
setColorDark();
}
protected void setColorBright() { setColorDark(); /* getCurrentWatchMode() == WatchMode.AMBIENT or WatchMode.INTERACTIVE */}
}

View file

@ -0,0 +1,162 @@
@file:Suppress("DEPRECATION")
package info.nightscout.androidaps.watchfaces
import android.annotation.SuppressLint
import android.content.Intent
import android.support.wearable.watchface.WatchFaceStyle
import android.view.LayoutInflater
import android.view.View
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.content.ContextCompat
import info.nightscout.androidaps.R
import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.interaction.menus.MainMenuActivity
import info.nightscout.shared.logging.LTag
class DigitalStyleWatchface : BaseWatchFace() {
private var sgvTapTime: Long = 0
@SuppressLint("InflateParams")
override fun onCreate() {
super.onCreate()
val inflater = getSystemService(LAYOUT_INFLATER_SERVICE) as LayoutInflater
layoutView = inflater.inflate(R.layout.activity_digitalstyle, null)
performViewSetup()
}
override fun onTapCommand(tapType: Int, x: Int, y: Int, eventTime: Long) {
//tapType = TAP_TYPE_TAP;
aapsLogger.debug(LTag.WEAR, "onTapCommand: DeviceWidth x DeviceHeight /// x , y, TapType >> ", "$width x $height /// $x , $y , $tapType")
if (tapType == TAP_TYPE_TAP) {
if (eventTime - sgvTapTime < TIME_TAP_THRESHOLD) {
val intent = Intent(this, MainMenuActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
}
sgvTapTime = eventTime
}
}
override fun getWatchFaceStyle(): WatchFaceStyle {
return WatchFaceStyle.Builder(this)
.setAcceptsTapEvents(true)
.setHideNotificationIndicator(false)
.setShowUnreadCountIndicator(true)
.build()
}
override fun setColorDark() {
when (singleBg.sgvLevel) {
1L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor))
mDirection?.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor))
}
0L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mDirection?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
}
-1L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor))
mDirection?.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor))
}
}
if (ageLevel == 1) mTimestamp?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
else mTimestamp?.setTextColor(ContextCompat.getColor(this, R.color.dark_TimestampOld))
if (status.batteryLevel == 1) mUploaderBattery?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
else mUploaderBattery?.setTextColor(ContextCompat.getColor(this, R.color.dark_uploaderBatteryEmpty))
if (chart != null) {
highColor = ContextCompat.getColor(this, R.color.dark_highColor)
lowColor = ContextCompat.getColor(this, R.color.dark_lowColor)
midColor = ContextCompat.getColor(this, R.color.dark_midColor)
gridColor = ContextCompat.getColor(this, R.color.dark_gridColor)
basalBackgroundColor = ContextCompat.getColor(this, R.color.basal_dark)
basalCenterColor = ContextCompat.getColor(this, R.color.basal_light)
pointSize = 1
setupCharts()
setWatchfaceStyle()
}
}
@SuppressLint("SetTextI18n")
private fun setWatchfaceStyle() {
/* frame styles*/
val mShapesElements = layoutView?.findViewById<LinearLayout>(R.id.shapes_elements)
if (mShapesElements != null) {
val displayFormatType = if (mShapesElements.contentDescription.toString().startsWith("round")) "round" else "rect"
val displayStyle = sp.getString("digitalstyle_frameStyle", "full")
val displayFrameColor = sp.getString("digitalstyle_frameColor", "red")
val displayFrameColorSaturation = sp.getString(
"digitalstyle_frameColorSaturation",
"500"
)
val displayFrameColorOpacity = sp.getString("digitalstyle_frameColorOpacity", "1")
// Load image with shapes
val styleDrawableName = "digitalstyle_bg_" + displayStyle + "_" + displayFormatType
try {
mShapesElements.background = ContextCompat.getDrawable(this, resources.getIdentifier(styleDrawableName, "drawable", this.packageName))
} catch (e: Exception) {
aapsLogger.error("digitalstyle_frameStyle", "RESOURCE NOT FOUND >> $styleDrawableName")
}
// set background-tint-color
if (displayFrameColor.equals("multicolor", ignoreCase = true) || displayStyle.equals("none", ignoreCase = true)) {
mShapesElements.backgroundTintList = null
} else {
val strColorName = if (displayFrameColor == "white" || displayFrameColor == "black") displayFrameColor else displayFrameColor + "_" + displayFrameColorSaturation
aapsLogger.debug(LTag.WEAR, "digitalstyle_strColorName", strColorName)
try {
val colorStateList = ContextCompat.getColorStateList(this, resources.getIdentifier(strColorName, "color", this.packageName))
mShapesElements.backgroundTintList = colorStateList
} catch (e: Exception) {
mShapesElements.backgroundTintList = null
aapsLogger.error("digitalstyle_colorName", "COLOR NOT FOUND >> $strColorName")
}
}
// set opacity of shapes
mShapesElements.alpha = displayFrameColorOpacity.toFloat()
}
/* optimize font-size --> when date is off then increase font-size of time */
val isShowDate = sp.getBoolean(R.string.key_show_date, false)
if (!isShowDate) {
layoutView?.findViewById<View>(R.id.date_time)?.visibility = View.GONE
mHour?.textSize = 62f
mMinute?.textSize = 40f
mHour?.letterSpacing = (-0.066).toFloat()
mMinute?.letterSpacing = (-0.066).toFloat()
} else {
layoutView?.findViewById<View>(R.id.date_time)?.visibility = View.VISIBLE
mHour?.textSize = 40f
mMinute?.textSize = 26f
mHour?.letterSpacing = 0.toFloat()
mMinute?.letterSpacing = 0.toFloat()
/* display week number */
val mWeekNumber = layoutView?.findViewById<TextView>(R.id.weeknumber)
mWeekNumber?.visibility = sp.getBoolean(R.string.key_show_week_number, false).toVisibility()
mWeekNumber?.text = "(" + dateUtil.weekString() + ")"
}
}
override fun setColorLowRes() {
setColorDark()
}
override fun setColorBright() {
setColorDark() /* getCurrentWatchMode() == WatchMode.AMBIENT or WatchMode.INTERACTIVE */
}
companion object {
private const val TIME_TAP_THRESHOLD: Long = 800
}
}

View file

@ -1,185 +0,0 @@
package info.nightscout.androidaps.watchfaces;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.graphics.Color;
import androidx.core.content.ContextCompat;
import android.support.wearable.watchface.WatchFaceStyle;
import android.view.LayoutInflater;
import com.ustwo.clockwise.common.WatchMode;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interaction.menus.MainMenuActivity;
public class Home extends BaseWatchFace {
private long chartTapTime = 0;
private long sgvTapTime = 0;
@SuppressLint("InflateParams") @Override
public void onCreate() {
super.onCreate();
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
layoutView = inflater.inflate(R.layout.activity_home, null);
performViewSetup();
}
@Override
protected void onTapCommand(int tapType, int x, int y, long eventTime) {
int extra = mSgv!=null?(mSgv.getRight() - mSgv.getLeft())/2:0;
if (tapType == TAP_TYPE_TAP&&
x >=chart.getLeft() &&
x <= chart.getRight()&&
y >= chart.getTop() &&
y <= chart.getBottom()){
if (eventTime - chartTapTime < 800){
changeChartTimeframe();
}
chartTapTime = eventTime;
} else if (tapType == TAP_TYPE_TAP&&
x + extra >=mSgv.getLeft() &&
x - extra <= mSgv.getRight()&&
y >= mSgv.getTop() &&
y <= mSgv.getBottom()){
if (eventTime - sgvTapTime < 800){
Intent intent = new Intent(this, MainMenuActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
sgvTapTime = eventTime;
}
}
private void changeChartTimeframe() {
int timeframe = sp.getInt("chart_timeframe", 3);
timeframe = (timeframe%5) + 1;
sp.putString("chart_timeframe", "" + timeframe);
}
@SuppressWarnings("deprecation")
@Override
protected WatchFaceStyle getWatchFaceStyle(){
return new WatchFaceStyle.Builder(this).setAcceptsTapEvents(true).build();
}
protected void setColorDark() {
mLinearLayout.setBackgroundColor(ContextCompat.getColor(this, dividerMatchesBg ?
R.color.dark_background : R.color.dark_statusView));
mTime.setTextColor(ContextCompat.getColor(this, R.color.dark_mTime));
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(this, R.color.dark_background));
if (singleBg.getSgvLevel() == 1) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor));
mDelta.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor));
mDirection.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor));
} else if (singleBg.getSgvLevel() == 0) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mDelta.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mDirection.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
} else if (singleBg.getSgvLevel() == -1) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor));
mDelta.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor));
mDirection.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor));
}
if (ageLevel == 1) {
mTimestamp.setTextColor(ContextCompat.getColor(this, dividerMatchesBg ?
R.color.dark_midColor : R.color.dark_mTimestamp1_home));
} else {
mTimestamp.setTextColor(ContextCompat.getColor(this, R.color.dark_TimestampOld));
}
if (status.getBatteryLevel() == 1) {
mUploaderBattery.setTextColor(ContextCompat.getColor(this, dividerMatchesBg ?
R.color.dark_midColor : R.color.dark_uploaderBattery));
} else {
mUploaderBattery.setTextColor(ContextCompat.getColor(this, R.color.dark_uploaderBatteryEmpty));
}
mStatus.setTextColor(ContextCompat.getColor(this, dividerMatchesBg ?
R.color.dark_midColor : R.color.dark_mStatus_home));
if (chart != null) {
highColor = ContextCompat.getColor(this, R.color.dark_highColor);
lowColor = ContextCompat.getColor(this, R.color.dark_lowColor);
midColor = ContextCompat.getColor(this, R.color.dark_midColor);
gridColor = ContextCompat.getColor(this, R.color.dark_gridColor);
basalBackgroundColor = ContextCompat.getColor(this, R.color.basal_dark);
basalCenterColor = ContextCompat.getColor(this, R.color.basal_light);
pointSize = 2;
setupCharts();
}
}
protected void setColorLowRes() {
mTime.setTextColor(ContextCompat.getColor(this, R.color.dark_mTime));
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(this, R.color.dark_background));
mSgv.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mDelta.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mTimestamp.setTextColor(ContextCompat.getColor(this, R.color.dark_Timestamp));
if (chart != null) {
highColor = ContextCompat.getColor(this, R.color.dark_midColor);
lowColor = ContextCompat.getColor(this, R.color.dark_midColor);
midColor = ContextCompat.getColor(this, R.color.dark_midColor);
gridColor = ContextCompat.getColor(this, R.color.dark_gridColor);
basalBackgroundColor = ContextCompat.getColor(this, R.color.basal_dark_lowres);
basalCenterColor = ContextCompat.getColor(this, R.color.basal_light_lowres);
pointSize = 2;
setupCharts();
}
}
protected void setColorBright() {
if (getCurrentWatchMode() == WatchMode.INTERACTIVE) {
mLinearLayout.setBackgroundColor(ContextCompat.getColor(this, dividerMatchesBg ?
R.color.light_background : R.color.light_stripe_background));
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(this, R.color.light_background));
if (singleBg.getSgvLevel() == 1) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.light_highColor));
mDelta.setTextColor(ContextCompat.getColor(this, R.color.light_highColor));
mDirection.setTextColor(ContextCompat.getColor(this, R.color.light_highColor));
} else if (singleBg.getSgvLevel() == 0) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.light_midColor));
mDelta.setTextColor(ContextCompat.getColor(this, R.color.light_midColor));
mDirection.setTextColor(ContextCompat.getColor(this, R.color.light_midColor));
} else if (singleBg.getSgvLevel() == -1) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.light_lowColor));
mDelta.setTextColor(ContextCompat.getColor(this, R.color.light_lowColor));
mDirection.setTextColor(ContextCompat.getColor(this, R.color.light_lowColor));
}
if (ageLevel == 1) {
mTimestamp.setTextColor(dividerMatchesBg ? Color.BLACK : Color.WHITE);
} else {
mTimestamp.setTextColor(Color.RED);
}
if (status.getBatteryLevel() == 1) {
mUploaderBattery.setTextColor(dividerMatchesBg ? Color.BLACK : Color.WHITE);
} else {
mUploaderBattery.setTextColor(Color.RED);
}
mStatus.setTextColor(dividerMatchesBg ? Color.BLACK : Color.WHITE);
mTime.setTextColor(Color.BLACK);
if (chart != null) {
highColor = ContextCompat.getColor(this, R.color.light_highColor);
lowColor = ContextCompat.getColor(this, R.color.light_lowColor);
midColor = ContextCompat.getColor(this, R.color.light_midColor);
gridColor = ContextCompat.getColor(this, R.color.light_gridColor);
basalBackgroundColor = ContextCompat.getColor(this, R.color.basal_light);
basalCenterColor = ContextCompat.getColor(this, R.color.basal_dark);
pointSize = 2;
setupCharts();
}
} else {
setColorDark();
}
}
}

View file

@ -1,270 +0,0 @@
package info.nightscout.androidaps.watchfaces;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.graphics.Color;
import androidx.annotation.ColorInt;
import androidx.core.content.ContextCompat;
import android.support.wearable.watchface.WatchFaceStyle;
import android.view.LayoutInflater;
import com.ustwo.clockwise.common.WatchMode;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interaction.menus.MainMenuActivity;
public class Home2 extends BaseWatchFace {
private long chartTapTime = 0;
private long sgvTapTime = 0;
@SuppressLint("InflateParams") @Override
public void onCreate() {
super.onCreate();
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
layoutView = inflater.inflate(R.layout.activity_home_2, null);
performViewSetup();
}
@Override
protected void onTapCommand(int tapType, int x, int y, long eventTime) {
int extra = mSgv != null ? (mSgv.getRight() - mSgv.getLeft()) / 2 : 0;
if (tapType == TAP_TYPE_TAP &&
x >= chart.getLeft() &&
x <= chart.getRight() &&
y >= chart.getTop() &&
y <= chart.getBottom()) {
if (eventTime - chartTapTime < 800) {
changeChartTimeframe();
}
chartTapTime = eventTime;
} else if (tapType == TAP_TYPE_TAP &&
x + extra >= mSgv.getLeft() &&
x - extra <= mSgv.getRight() &&
y >= mSgv.getTop() &&
y <= mSgv.getBottom()) {
if (eventTime - sgvTapTime < 800) {
Intent intent = new Intent(this, MainMenuActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
sgvTapTime = eventTime;
}
}
private void changeChartTimeframe() {
int timeframe = sp.getInt("chart_timeframe", 3);
timeframe = (timeframe % 5) + 1;
sp.putString("chart_timeframe", "" + timeframe);
}
@SuppressWarnings("deprecation")
@Override
protected WatchFaceStyle getWatchFaceStyle() {
return new WatchFaceStyle.Builder(this).setAcceptsTapEvents(true).build();
}
protected void setColorDark() {
@ColorInt final int dividerTxtColor = dividerMatchesBg ?
ContextCompat.getColor(this, R.color.dark_midColor) : Color.BLACK;
@ColorInt final int dividerBatteryOkColor = ContextCompat.getColor(this,
dividerMatchesBg ? R.color.dark_midColor : R.color.dark_uploaderBattery);
@ColorInt final int dividerBgColor = ContextCompat.getColor(this,
dividerMatchesBg ? R.color.dark_background : R.color.dark_statusView);
mLinearLayout.setBackgroundColor(dividerBgColor);
mLinearLayout2.setBackgroundColor(ContextCompat.getColor(this, R.color.dark_background));
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(this, R.color.dark_background));
mTime.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mIOB1.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mIOB2.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mCOB1.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mCOB2.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mDay.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mMonth.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mLoop.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
setTextSizes();
if (singleBg.getSgvLevel() == 1) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor));
mDirection.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor));
} else if (singleBg.getSgvLevel() == 0) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mDirection.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
} else if (singleBg.getSgvLevel() == -1) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor));
mDirection.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor));
}
if (ageLevel == 1) {
mTimestamp.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
} else {
mTimestamp.setTextColor(ContextCompat.getColor(this, R.color.dark_TimestampOld));
}
if (status.getBatteryLevel() == 1) {
mUploaderBattery.setTextColor(dividerBatteryOkColor);
} else {
mUploaderBattery.setTextColor(ContextCompat.getColor(this, R.color.dark_uploaderBatteryEmpty));
}
mRigBattery.setTextColor(dividerTxtColor);
mDelta.setTextColor(dividerTxtColor);
mAvgDelta.setTextColor(dividerTxtColor);
mBasalRate.setTextColor(dividerTxtColor);
mBgi.setTextColor(dividerTxtColor);
if (loopLevel == -1) {
mLoop.setBackgroundResource(R.drawable.loop_grey_25);
} else if (loopLevel == 1) {
mLoop.setBackgroundResource(R.drawable.loop_green_25);
} else {
mLoop.setBackgroundResource(R.drawable.loop_red_25);
}
if (chart != null) {
highColor = ContextCompat.getColor(this, R.color.dark_highColor);
lowColor = ContextCompat.getColor(this, R.color.dark_lowColor);
midColor = ContextCompat.getColor(this, R.color.dark_midColor);
gridColor = ContextCompat.getColor(this, R.color.dark_gridColor);
basalBackgroundColor = ContextCompat.getColor(this, R.color.basal_dark);
basalCenterColor = ContextCompat.getColor(this, R.color.basal_light);
pointSize = 2;
setupCharts();
}
}
protected void setColorLowRes() {
@ColorInt final int dividerTxtColor = dividerMatchesBg ?
ContextCompat.getColor(this, R.color.dark_midColor) : Color.BLACK;
@ColorInt final int dividerBgColor = ContextCompat.getColor(this,
dividerMatchesBg ? R.color.dark_background : R.color.dark_statusView);
mLinearLayout.setBackgroundColor(dividerBgColor);
mLinearLayout2.setBackgroundColor(ContextCompat.getColor(this, R.color.dark_background));
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(this, R.color.dark_background));
mLoop.setBackgroundResource(R.drawable.loop_grey_25);
mLoop.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mSgv.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mDirection.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mTimestamp.setTextColor(ContextCompat.getColor(this, R.color.dark_Timestamp));
mDelta.setTextColor(dividerTxtColor);
mAvgDelta.setTextColor(dividerTxtColor);
mRigBattery.setTextColor(dividerTxtColor);
mUploaderBattery.setTextColor(dividerTxtColor);
mBasalRate.setTextColor(dividerTxtColor);
mBgi.setTextColor(dividerTxtColor);
mIOB1.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mIOB2.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mCOB1.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mCOB2.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mDay.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mMonth.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mTime.setTextColor(ContextCompat.getColor(this, R.color.dark_mTime));
if (chart != null) {
highColor = ContextCompat.getColor(this, R.color.dark_midColor);
lowColor = ContextCompat.getColor(this, R.color.dark_midColor);
midColor = ContextCompat.getColor(this, R.color.dark_midColor);
gridColor = ContextCompat.getColor(this, R.color.dark_gridColor);
basalBackgroundColor = ContextCompat.getColor(this, R.color.basal_dark_lowres);
basalCenterColor = ContextCompat.getColor(this, R.color.basal_light_lowres);
pointSize = 2;
setupCharts();
}
setTextSizes();
}
protected void setColorBright() {
if (getCurrentWatchMode() == WatchMode.INTERACTIVE) {
@ColorInt final int dividerTxtColor = dividerMatchesBg ? Color.BLACK :
ContextCompat.getColor(this, R.color.dark_midColor);
@ColorInt final int dividerBgColor = ContextCompat.getColor(this,
dividerMatchesBg ? R.color.light_background : R.color.light_stripe_background);
mLinearLayout.setBackgroundColor(dividerBgColor);
mLinearLayout2.setBackgroundColor(ContextCompat.getColor(this, R.color.light_background));
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(this, R.color.light_background));
mTime.setTextColor(Color.BLACK);
mIOB1.setTextColor(Color.BLACK);
mIOB2.setTextColor(Color.BLACK);
mCOB1.setTextColor(Color.BLACK);
mCOB2.setTextColor(Color.BLACK);
mDay.setTextColor(Color.BLACK);
mMonth.setTextColor(Color.BLACK);
mLoop.setTextColor(Color.BLACK);
setTextSizes();
if (singleBg.getSgvLevel() == 1) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.light_highColor));
mDirection.setTextColor(ContextCompat.getColor(this, R.color.light_highColor));
} else if (singleBg.getSgvLevel() == 0) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.light_midColor));
mDirection.setTextColor(ContextCompat.getColor(this, R.color.light_midColor));
} else if (singleBg.getSgvLevel() == -1) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.light_lowColor));
mDirection.setTextColor(ContextCompat.getColor(this, R.color.light_lowColor));
}
if (ageLevel == 1) {
mTimestamp.setTextColor(Color.BLACK);
} else {
mTimestamp.setTextColor(Color.RED);
}
if (status.getBatteryLevel() == 1) {
mUploaderBattery.setTextColor(dividerTxtColor);
} else {
mUploaderBattery.setTextColor(Color.RED);
}
mRigBattery.setTextColor(dividerTxtColor);
mDelta.setTextColor(dividerTxtColor);
mAvgDelta.setTextColor(dividerTxtColor);
mBasalRate.setTextColor(dividerTxtColor);
mBgi.setTextColor(dividerTxtColor);
if (loopLevel == -1) {
mLoop.setBackgroundResource(R.drawable.loop_grey_25);
} else if (loopLevel == 1) {
mLoop.setBackgroundResource(R.drawable.loop_green_25);
} else {
mLoop.setBackgroundResource(R.drawable.loop_red_25);
}
if (chart != null) {
highColor = ContextCompat.getColor(this, R.color.light_highColor);
lowColor = ContextCompat.getColor(this, R.color.light_lowColor);
midColor = ContextCompat.getColor(this, R.color.light_midColor);
gridColor = ContextCompat.getColor(this, R.color.light_gridColor);
basalBackgroundColor = ContextCompat.getColor(this, R.color.basal_light);
basalCenterColor = ContextCompat.getColor(this, R.color.basal_dark);
pointSize = 2;
setupCharts();
}
} else {
setColorDark();
}
}
protected void setTextSizes() {
if (mIOB1 != null && mIOB2 != null) {
if (status.getDetailedIob()) {
mIOB1.setTextSize(14);
mIOB2.setTextSize(10);
} else {
mIOB1.setTextSize(10);
mIOB2.setTextSize(14);
}
}
}
}

View file

@ -1,158 +0,0 @@
package info.nightscout.androidaps.watchfaces;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.graphics.Color;
import androidx.core.content.ContextCompat;
import android.support.wearable.watchface.WatchFaceStyle;
import android.view.LayoutInflater;
import com.ustwo.clockwise.common.WatchMode;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interaction.menus.MainMenuActivity;
public class LargeHome extends BaseWatchFace {
private long sgvTapTime = 0;
@SuppressLint("InflateParams") @Override
public void onCreate() {
super.onCreate();
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
layoutView = inflater.inflate(R.layout.activity_home_large, null);
performViewSetup();
}
@Override
protected void onTapCommand(int tapType, int x, int y, long eventTime) {
if (mSgv == null) return;
int extra = (mSgv.getRight() - mSgv.getLeft())/2;
if (tapType == TAP_TYPE_TAP&&
x + extra >=mSgv.getLeft() &&
x - extra <= mSgv.getRight()&&
y >= mSgv.getTop() &&
y <= mSgv.getBottom()){
if (eventTime - sgvTapTime < 800){
Intent intent = new Intent(this, MainMenuActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
sgvTapTime = eventTime;
}
}
@SuppressWarnings("deprecation")
@Override
protected WatchFaceStyle getWatchFaceStyle(){
return new WatchFaceStyle.Builder(this).setAcceptsTapEvents(true).build();
}
@Override
protected void setColorDark(){
mLinearLayout.setBackgroundColor(ContextCompat.getColor(this, dividerMatchesBg ?
R.color.dark_background : R.color.dark_mLinearLayout));
mTime.setTextColor(ContextCompat.getColor(this, R.color.dark_mTime));
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(this, R.color.dark_background));
if (singleBg.getSgvLevel() == 1) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor));
mDelta.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor));
mDirection.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor));
} else if (singleBg.getSgvLevel() == 0) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mDelta.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mDirection.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
} else if (singleBg.getSgvLevel() == -1) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor));
mDelta.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor));
mDirection.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor));
}
if (ageLevel == 1) {
mTimestamp.setTextColor(ContextCompat.getColor(this, dividerMatchesBg ?
R.color.dark_midColor : R.color.dark_mTimestamp1_home));
} else {
mTimestamp.setTextColor(ContextCompat.getColor(this, R.color.dark_TimestampOld));
}
if (status.getBatteryLevel() == 1) {
mUploaderBattery.setTextColor(ContextCompat.getColor(this, dividerMatchesBg ?
R.color.dark_midColor : R.color.dark_uploaderBattery));
} else {
mUploaderBattery.setTextColor(ContextCompat.getColor(this, R.color.dark_uploaderBatteryEmpty));
}
mStatus.setTextColor(ContextCompat.getColor(this, dividerMatchesBg ? R.color.dark_midColor : R.color.dark_mStatus_home));
}
@Override
protected void setColorBright() {
if (getCurrentWatchMode() == WatchMode.INTERACTIVE) {
mLinearLayout.setBackgroundColor(ContextCompat.getColor(this, dividerMatchesBg ?
R.color.light_background : R.color.light_stripe_background));
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(this, R.color.light_background));
if (singleBg.getSgvLevel() == 1) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.light_highColor));
mDelta.setTextColor(ContextCompat.getColor(this, R.color.light_highColor));
mDirection.setTextColor(ContextCompat.getColor(this, R.color.light_highColor));
} else if (singleBg.getSgvLevel() == 0) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.light_midColor));
mDelta.setTextColor(ContextCompat.getColor(this, R.color.light_midColor));
mDirection.setTextColor(ContextCompat.getColor(this, R.color.light_midColor));
} else if (singleBg.getSgvLevel() == -1) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.light_lowColor));
mDelta.setTextColor(ContextCompat.getColor(this, R.color.light_lowColor));
mDirection.setTextColor(ContextCompat.getColor(this, R.color.light_lowColor));
}
if (ageLevel == 1) {
mTimestamp.setTextColor(dividerMatchesBg ? Color.BLACK : Color.WHITE);
} else {
mTimestamp.setTextColor(Color.RED);
}
if (status.getBatteryLevel() == 1) {
mUploaderBattery.setTextColor(dividerMatchesBg ? Color.BLACK : Color.WHITE);
} else {
mUploaderBattery.setTextColor(Color.RED);
}
mStatus.setTextColor(dividerMatchesBg ? Color.BLACK : Color.WHITE);
mTime.setTextColor(Color.BLACK);
} else {
mRelativeLayout.setBackgroundColor(Color.BLACK);
mLinearLayout.setBackgroundColor(dividerMatchesBg ? Color.BLACK : Color.LTGRAY);
if (singleBg.getSgvLevel() == 1) {
mSgv.setTextColor(Color.YELLOW);
mDirection.setTextColor(Color.YELLOW);
mDelta.setTextColor(Color.YELLOW);
} else if (singleBg.getSgvLevel() == 0) {
mSgv.setTextColor(Color.WHITE);
mDirection.setTextColor(Color.WHITE);
mDelta.setTextColor(Color.WHITE);
} else if (singleBg.getSgvLevel() == -1) {
mSgv.setTextColor(Color.RED);
mDirection.setTextColor(Color.RED);
mDelta.setTextColor(Color.RED);
}
mUploaderBattery.setTextColor(dividerMatchesBg ? Color.WHITE : Color.BLACK);
mTimestamp.setTextColor(dividerMatchesBg ? Color.WHITE : Color.BLACK);
mStatus.setTextColor(dividerMatchesBg ? Color.WHITE : Color.BLACK);
mTime.setTextColor(Color.WHITE);
}
}
@Override
protected void setColorLowRes() {
mLinearLayout.setBackgroundColor(ContextCompat.getColor(this, dividerMatchesBg ? R.color.dark_background : R.color.dark_mLinearLayout));
mTime.setTextColor(ContextCompat.getColor(this, R.color.dark_mTime));
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(this, R.color.dark_background));
mSgv.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mDelta.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mDirection.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mTimestamp.setTextColor(ContextCompat.getColor(this, dividerMatchesBg ? R.color.dark_midColor : R.color.dark_mTimestamp1_home));
mUploaderBattery.setTextColor(ContextCompat.getColor(this, dividerMatchesBg ? R.color.dark_midColor : R.color.dark_uploaderBattery));
mStatus.setTextColor(ContextCompat.getColor(this, dividerMatchesBg ? R.color.dark_midColor : R.color.dark_mStatus_home));
}
}

View file

@ -1,368 +0,0 @@
package info.nightscout.androidaps.watchfaces;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.PowerManager;
import android.support.wearable.view.WatchViewStub;
import android.support.wearable.watchface.WatchFaceStyle;
import android.text.format.DateFormat;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.core.content.ContextCompat;
import com.ustwo.clockwise.common.WatchFaceTime;
import com.ustwo.clockwise.common.WatchMode;
import com.ustwo.clockwise.common.WatchShape;
import com.ustwo.clockwise.wearable.WatchFace;
import javax.inject.Inject;
import dagger.android.AndroidInjection;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.events.EventWearToMobile;
import info.nightscout.androidaps.interaction.menus.MainMenuActivity;
import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.utils.rx.AapsSchedulers;
import info.nightscout.shared.logging.AAPSLogger;
import info.nightscout.shared.logging.LTag;
import info.nightscout.shared.sharedPreferences.SP;
import info.nightscout.shared.weardata.EventData;
import io.reactivex.rxjava3.disposables.CompositeDisposable;
/**
* Created by adrianLxM.
*/
public class NOChart extends WatchFace {
@Inject RxBus rxBus;
@Inject AapsSchedulers aapsSchedulers;
@Inject AAPSLogger aapsLogger;
@Inject SP sp;
CompositeDisposable disposable = new CompositeDisposable();
private EventData.SingleBg singleBg;
private EventData.Status status;
public static final int SCREENSIZE_SMALL = 280;
public TextView mTime, mSgv, mTimestamp, mDelta, mAvgDelta;
public RelativeLayout mRelativeLayout;
public long sgvLevel = 0;
public int ageLevel = 1;
public boolean lowResMode = false;
public boolean layoutSet = false;
public PowerManager.WakeLock wakeLock;
public View layoutView;
private final Point displaySize = new Point();
private int specW, specH;
private TextView statusView;
private long sgvTapTime = 0L;
@SuppressLint("InflateParams") @Override
public void onCreate() {
AndroidInjection.inject(this);
super.onCreate();
Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay();
display.getSize(displaySize);
wakeLock = ((PowerManager) getSystemService(Context.POWER_SERVICE)).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidAPS:NOChart");
specW = View.MeasureSpec.makeMeasureSpec(displaySize.x,
View.MeasureSpec.EXACTLY);
specH = View.MeasureSpec.makeMeasureSpec(displaySize.y,
View.MeasureSpec.EXACTLY);
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
DisplayMetrics metrics = getResources().getDisplayMetrics();
if (metrics.widthPixels < SCREENSIZE_SMALL || metrics.heightPixels < SCREENSIZE_SMALL) {
layoutView = inflater.inflate(R.layout.activity_nochart_small, null);
} else {
layoutView = inflater.inflate(R.layout.activity_nochart, null);
}
disposable.add(rxBus
.toObservable(EventData.SingleBg.class)
.observeOn(aapsSchedulers.getMain())
.subscribe(event -> {
aapsLogger.debug(LTag.WEAR, "SingleBg received");
singleBg = event;
mSgv.setText(singleBg.getSgvString());
if (ageLevel() <= 0)
mSgv.setPaintFlags(mSgv.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
else mSgv.setPaintFlags(mSgv.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
final java.text.DateFormat timeFormat = DateFormat.getTimeFormat(this);
mTime.setText(timeFormat.format(System.currentTimeMillis()));
mDelta.setText(singleBg.getDelta());
mAvgDelta.setText(singleBg.getAvgDelta());
})
);
disposable.add(rxBus
.toObservable(EventData.Status.class)
.observeOn(aapsSchedulers.getMain())
.subscribe(event -> {
// this event is received as last batch of data
aapsLogger.debug(LTag.WEAR, "Status received");
status = event;
showAgeAndStatus();
mRelativeLayout.measure(specW, specH);
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
mRelativeLayout.getMeasuredHeight());
invalidate();
setColor();
})
);
disposable.add(rxBus
.toObservable(EventData.Preferences.class)
.observeOn(aapsSchedulers.getMain())
.subscribe(event -> {
setColor();
if (layoutSet) {
showAgeAndStatus();
mRelativeLayout.measure(specW, specH);
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
mRelativeLayout.getMeasuredHeight());
}
invalidate();
})
);
performViewSetup();
}
@Override
protected void onLayout(WatchShape shape, Rect screenBounds, WindowInsets screenInsets) {
super.onLayout(shape, screenBounds, screenInsets);
layoutView.onApplyWindowInsets(screenInsets);
}
public void performViewSetup() {
mTime = layoutView.findViewById(R.id.watch_time);
mSgv = layoutView.findViewById(R.id.sgv);
mTimestamp = layoutView.findViewById(R.id.timestamp);
mDelta = layoutView.findViewById(R.id.delta);
mAvgDelta = layoutView.findViewById(R.id.avgdelta);
mRelativeLayout = layoutView.findViewById(R.id.main_layout);
statusView = layoutView.findViewById(R.id.aps_status);
layoutSet = true;
showAgeAndStatus();
mRelativeLayout.measure(specW, specH);
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(), mRelativeLayout.getMeasuredHeight());
rxBus.send(new EventWearToMobile(new EventData.ActionResendData("NOChart:performViewSetup")));
wakeLock.acquire(50);
}
@Override
protected void onTapCommand(int tapType, int x, int y, long eventTime) {
if (mSgv == null) return;
int extra = (mSgv.getRight() - mSgv.getLeft()) / 2;
if (tapType == TAP_TYPE_TAP &&
x + extra >= mSgv.getLeft() &&
x - extra <= mSgv.getRight() &&
y >= mSgv.getTop() &&
y <= mSgv.getBottom()) {
if (eventTime - sgvTapTime < 800) {
Intent intent = new Intent(this, MainMenuActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
sgvTapTime = eventTime;
}
}
protected void onWatchModeChanged(WatchMode watchMode) {
if (lowResMode ^ isLowRes(watchMode)) { //if there was a change in lowResMode
lowResMode = isLowRes(watchMode);
setColor();
} else if (!sp.getBoolean("dark", true)) {
//in bright mode: different colours if active:
setColor();
}
}
private boolean isLowRes(WatchMode watchMode) {
return (watchMode == WatchMode.LOW_BIT) || (watchMode == WatchMode.LOW_BIT_BURN_IN);
}
@SuppressWarnings("deprecation")
@Override
protected WatchFaceStyle getWatchFaceStyle() {
return new WatchFaceStyle.Builder(this).setAcceptsTapEvents(true).build();
}
public int ageLevel() {
if (timeSince() <= (1000 * 60 * 12)) {
return 1;
} else {
return 0;
}
}
public double timeSince() {
return System.currentTimeMillis() - singleBg.getTimeStamp();
}
public String readingAge(boolean shortString) {
if (singleBg == null || singleBg.getTimeStamp() == 0) {
return shortString ? "--'" : "-- Minute ago";
}
int minutesAgo = (int) Math.floor(timeSince() / (1000 * 60));
if (minutesAgo == 1) {
return minutesAgo + (shortString ? "'" : " Minute ago");
}
return minutesAgo + (shortString ? "'" : " Minutes ago");
}
@Override
public void onDestroy() {
disposable.clear();
super.onDestroy();
}
@Override
protected void onDraw(Canvas canvas) {
if (layoutSet) {
this.mRelativeLayout.draw(canvas);
}
}
@Override
protected void onTimeChanged(WatchFaceTime oldTime, WatchFaceTime newTime) {
if (layoutSet && (newTime.hasHourChanged(oldTime) || newTime.hasMinuteChanged(oldTime))) {
wakeLock.acquire(50);
final java.text.DateFormat timeFormat = DateFormat.getTimeFormat(NOChart.this);
mTime.setText(timeFormat.format(System.currentTimeMillis()));
showAgeAndStatus();
if (ageLevel() <= 0) {
mSgv.setPaintFlags(mSgv.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
} else {
mSgv.setPaintFlags(mSgv.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
}
missedReadingAlert();
mRelativeLayout.measure(specW, specH);
mRelativeLayout.layout(0, 0, mRelativeLayout.getMeasuredWidth(),
mRelativeLayout.getMeasuredHeight());
}
}
private void showAgeAndStatus() {
if (mTimestamp != null) {
mTimestamp.setText(readingAge(true));
}
boolean showAvgDelta = sp.getBoolean("showAvgDelta", true);
if (showAvgDelta) {
mAvgDelta.setVisibility(View.VISIBLE);
} else {
mAvgDelta.setVisibility(View.GONE);
}
if (status != null) {
statusView.setText(status.getExternalStatus());
statusView.setVisibility(View.VISIBLE);
}
}
public void setColor() {
if (lowResMode) {
setColorLowRes();
} else if (sp.getBoolean("dark", true)) {
setColorDark();
} else {
setColorBright();
}
}
protected void setColorLowRes() {
mTime.setTextColor(ContextCompat.getColor(this, R.color.dark_mTime));
statusView.setTextColor(ContextCompat.getColor(this, R.color.dark_statusView));
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(this, R.color.dark_background));
mSgv.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mDelta.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mAvgDelta.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mTimestamp.setTextColor(ContextCompat.getColor(this, R.color.dark_Timestamp));
}
protected void setColorDark() {
mTime.setTextColor(ContextCompat.getColor(this, R.color.dark_mTime));
statusView.setTextColor(ContextCompat.getColor(this, R.color.dark_statusView));
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(this, R.color.dark_background));
if (sgvLevel == 1) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor));
mDelta.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor));
mAvgDelta.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor));
} else if (sgvLevel == 0) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mDelta.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
mAvgDelta.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor));
} else if (sgvLevel == -1) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor));
mDelta.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor));
mAvgDelta.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor));
}
if (ageLevel == 1) {
mTimestamp.setTextColor(ContextCompat.getColor(this, R.color.dark_Timestamp));
} else {
mTimestamp.setTextColor(ContextCompat.getColor(this, R.color.dark_TimestampOld));
}
}
protected void setColorBright() {
if (getCurrentWatchMode() == WatchMode.INTERACTIVE) {
mTime.setTextColor(ContextCompat.getColor(this, R.color.light_bigchart_time));
statusView.setTextColor(ContextCompat.getColor(this, R.color.light_bigchart_status));
mRelativeLayout.setBackgroundColor(ContextCompat.getColor(this, R.color.light_background));
if (sgvLevel == 1) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.light_highColor));
mDelta.setTextColor(ContextCompat.getColor(this, R.color.light_highColor));
mAvgDelta.setTextColor(ContextCompat.getColor(this, R.color.light_highColor));
} else if (sgvLevel == 0) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.light_midColor));
mDelta.setTextColor(ContextCompat.getColor(this, R.color.light_midColor));
mAvgDelta.setTextColor(ContextCompat.getColor(this, R.color.light_midColor));
} else if (sgvLevel == -1) {
mSgv.setTextColor(ContextCompat.getColor(this, R.color.light_lowColor));
mDelta.setTextColor(ContextCompat.getColor(this, R.color.light_lowColor));
mAvgDelta.setTextColor(ContextCompat.getColor(this, R.color.light_lowColor));
}
if (ageLevel == 1) {
mTimestamp.setTextColor(ContextCompat.getColor(this, R.color.light_mTimestamp1));
} else {
mTimestamp.setTextColor(ContextCompat.getColor(this, R.color.light_mTimestamp));
}
} else {
setColorDark();
}
}
public void missedReadingAlert() {
int minutes_since = (int) Math.floor(timeSince() / (1000 * 60));
if (minutes_since >= 16 && ((minutes_since - 16) % 5) == 0) {
// attempt endTime recover missing data
rxBus.send(new EventWearToMobile(new EventData.ActionResendData("NOChart" +
":missedReadingAlert")));
}
}
}

View file

@ -0,0 +1,324 @@
@file:Suppress("DEPRECATION")
package info.nightscout.androidaps.watchfaces
import android.annotation.SuppressLint
import android.content.Intent
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Point
import android.graphics.Rect
import android.os.PowerManager
import android.support.wearable.watchface.WatchFaceStyle
import android.text.format.DateFormat
import android.view.LayoutInflater
import android.view.View
import android.view.WindowInsets
import android.view.WindowManager
import android.widget.RelativeLayout
import android.widget.TextView
import androidx.core.content.ContextCompat
import com.ustwo.clockwise.common.WatchFaceTime
import com.ustwo.clockwise.common.WatchMode
import com.ustwo.clockwise.common.WatchShape
import com.ustwo.clockwise.wearable.WatchFace
import dagger.android.AndroidInjection
import info.nightscout.androidaps.R
import info.nightscout.androidaps.events.EventWearToMobile
import info.nightscout.androidaps.extensions.toVisibility
import info.nightscout.androidaps.interaction.menus.MainMenuActivity
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.rx.AapsSchedulers
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP
import info.nightscout.shared.weardata.EventData
import info.nightscout.shared.weardata.EventData.ActionResendData
import info.nightscout.shared.weardata.EventData.SingleBg
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import javax.inject.Inject
import kotlin.math.floor
class NoChartWatchface : WatchFace() {
@Inject lateinit var rxBus: RxBus
@Inject lateinit var aapsSchedulers: AapsSchedulers
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var sp: SP
@Inject lateinit var dateUtil: DateUtil
private var disposable = CompositeDisposable()
private var singleBg = SingleBg(0, "---", "-", "--", "--", "--", 0, 0.0, 0.0, 0.0, 0)
private var status = EventData.Status("no status", "IOB", "-.--", false, "--g", "-.--U/h", "--", "--", -1, "--", false, 1)
private var mTime: TextView? = null
private var mSgv: TextView? = null
private var mTimestamp: TextView? = null
private var mDelta: TextView? = null
private var mAvgDelta: TextView? = null
private var mRelativeLayout: RelativeLayout? = null
private var sgvLevel: Long = 0
private var ageLevel = 1
private var lowResMode = false
private var layoutSet = false
private var wakeLock: PowerManager.WakeLock? = null
private var layoutView: View? = null
private val displaySize = Point()
private var specW = 0
private var specH = 0
private var statusView: TextView? = null
private var sgvTapTime = 0L
@SuppressLint("InflateParams")
override fun onCreate() {
AndroidInjection.inject(this)
super.onCreate()
val display = (getSystemService(WINDOW_SERVICE) as WindowManager).defaultDisplay
display.getSize(displaySize)
wakeLock = (getSystemService(POWER_SERVICE) as PowerManager).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidAPS:NOChart")
specW = View.MeasureSpec.makeMeasureSpec(displaySize.x, View.MeasureSpec.EXACTLY)
specH = View.MeasureSpec.makeMeasureSpec(displaySize.y, View.MeasureSpec.EXACTLY)
val inflater = getSystemService(LAYOUT_INFLATER_SERVICE) as LayoutInflater
val metrics = resources.displayMetrics
layoutView = if (metrics.widthPixels < SCREEN_SIZE_SMALL || metrics.heightPixels < SCREEN_SIZE_SMALL) {
inflater.inflate(R.layout.activity_nochart_small, null)
} else {
inflater.inflate(R.layout.activity_nochart, null)
}
disposable += rxBus
.toObservable(SingleBg::class.java)
.observeOn(aapsSchedulers.main)
.subscribe { event: SingleBg ->
aapsLogger.debug(LTag.WEAR, "SingleBg received")
singleBg = event
mSgv?.let { sgv ->
sgv.text = singleBg.sgvString
if (ageLevel() <= 0) sgv.paintFlags = sgv.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
else sgv.paintFlags = sgv.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv()
}
mTime?.text = dateUtil.timeString()
mDelta?.text = singleBg.delta
mAvgDelta?.text = singleBg.avgDelta
}
disposable += rxBus
.toObservable(EventData.Status::class.java)
.observeOn(aapsSchedulers.main)
.subscribe { event: EventData.Status ->
// this event is received as last batch of data
aapsLogger.debug(LTag.WEAR, "Status received")
status = event
showAgeAndStatus()
mRelativeLayout?.measure(specW, specH)
mRelativeLayout?.layout(0, 0, mRelativeLayout?.measuredWidth ?: 0, mRelativeLayout?.measuredHeight ?: 0)
invalidate()
setColor()
}
disposable += rxBus
.toObservable(EventData.Preferences::class.java)
.observeOn(aapsSchedulers.main)
.subscribe {
setColor()
if (layoutSet) {
showAgeAndStatus()
mRelativeLayout?.measure(specW, specH)
mRelativeLayout?.layout(0, 0, mRelativeLayout?.measuredWidth ?: 0, mRelativeLayout?.measuredHeight ?: 0)
}
invalidate()
}
performViewSetup()
}
override fun onLayout(shape: WatchShape, screenBounds: Rect, screenInsets: WindowInsets) {
super.onLayout(shape, screenBounds, screenInsets)
layoutView?.onApplyWindowInsets(screenInsets)
}
private fun performViewSetup() {
mTime = layoutView?.findViewById(R.id.watch_time)
mSgv = layoutView?.findViewById(R.id.sgv)
mTimestamp = layoutView?.findViewById(R.id.timestamp)
mDelta = layoutView?.findViewById(R.id.delta)
mAvgDelta = layoutView?.findViewById(R.id.avgdelta)
mRelativeLayout = layoutView?.findViewById(R.id.main_layout)
statusView = layoutView?.findViewById(R.id.aps_status)
layoutSet = true
showAgeAndStatus()
mRelativeLayout?.measure(specW, specH)
mRelativeLayout?.layout(0, 0, mRelativeLayout?.measuredWidth ?: 0, mRelativeLayout?.measuredHeight ?: 0)
rxBus.send(EventWearToMobile(ActionResendData("NOChart:performViewSetup")))
}
override fun onTapCommand(tapType: Int, x: Int, y: Int, eventTime: Long) {
mSgv?.let { mSgv ->
val extra = (mSgv.right - mSgv.left) / 2
if (tapType == TAP_TYPE_TAP && x + extra >= mSgv.left && x - extra <= mSgv.right && y >= mSgv.top && y <= mSgv.bottom) {
if (eventTime - sgvTapTime < 800) {
startActivity(Intent(this, MainMenuActivity::class.java).also { it.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) })
}
sgvTapTime = eventTime
}
}
}
override fun onWatchModeChanged(watchMode: WatchMode) {
if (lowResMode xor isLowRes(watchMode)) { //if there was a change in lowResMode
lowResMode = isLowRes(watchMode)
setColor()
} else if (!sp.getBoolean("dark", true)) {
//in bright mode: different colours if active:
setColor()
}
}
private fun isLowRes(watchMode: WatchMode): Boolean {
return watchMode == WatchMode.LOW_BIT || watchMode == WatchMode.LOW_BIT_BURN_IN
}
override fun getWatchFaceStyle(): WatchFaceStyle {
return WatchFaceStyle.Builder(this).setAcceptsTapEvents(true).build()
}
private fun ageLevel(): Int = if (timeSince() <= 1000 * 60 * 12) 1 else 0
fun timeSince(): Double = (System.currentTimeMillis() - singleBg.timeStamp).toDouble()
private fun readingAge(): String {
if (singleBg.timeStamp == 0L) return "--'"
val minutesAgo = floor(timeSince() / (1000 * 60)).toInt()
return if (minutesAgo == 1) "$minutesAgo'"
else "$minutesAgo'"
}
override fun onDestroy() {
disposable.clear()
super.onDestroy()
}
override fun onDraw(canvas: Canvas) {
if (layoutSet) {
mRelativeLayout?.draw(canvas)
}
}
override fun onTimeChanged(oldTime: WatchFaceTime, newTime: WatchFaceTime) {
if (layoutSet && (newTime.hasHourChanged(oldTime) || newTime.hasMinuteChanged(oldTime))) {
mTime?.text = dateUtil.timeString()
showAgeAndStatus()
mSgv?.let { sgv ->
if (ageLevel() <= 0) {
sgv.paintFlags = sgv.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
} else {
sgv.paintFlags = sgv.paintFlags and Paint.STRIKE_THRU_TEXT_FLAG.inv()
}
}
missedReadingAlert()
mRelativeLayout?.measure(specW, specH)
mRelativeLayout?.layout(0, 0, mRelativeLayout?.measuredWidth ?: 0, mRelativeLayout?.measuredHeight ?: 0)
}
}
private fun showAgeAndStatus() {
mTimestamp?.text = readingAge()
mAvgDelta?.visibility = sp.getBoolean(R.string.key_show_avg_delta, true).toVisibility()
statusView?.text = status.externalStatus
statusView?.visibility = View.VISIBLE
}
private fun setColor() {
when {
lowResMode -> setColorLowRes()
sp.getBoolean("dark", true) -> setColorDark()
else -> setColorBright()
}
}
private fun setColorLowRes() {
mTime?.setTextColor(ContextCompat.getColor(this, R.color.dark_mTime))
statusView?.setTextColor(ContextCompat.getColor(this, R.color.dark_statusView))
mRelativeLayout?.setBackgroundColor(ContextCompat.getColor(this, R.color.dark_background))
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mDelta?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mAvgDelta?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mTimestamp?.setTextColor(ContextCompat.getColor(this, R.color.dark_Timestamp))
}
private fun setColorDark() {
mTime?.setTextColor(ContextCompat.getColor(this, R.color.dark_mTime))
statusView?.setTextColor(ContextCompat.getColor(this, R.color.dark_statusView))
mRelativeLayout?.setBackgroundColor(ContextCompat.getColor(this, R.color.dark_background))
when (sgvLevel) {
1L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor))
mDelta?.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor))
mAvgDelta?.setTextColor(ContextCompat.getColor(this, R.color.dark_highColor))
}
0L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mDelta?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
mAvgDelta?.setTextColor(ContextCompat.getColor(this, R.color.dark_midColor))
}
-1L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor))
mDelta?.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor))
mAvgDelta?.setTextColor(ContextCompat.getColor(this, R.color.dark_lowColor))
}
}
if (ageLevel == 1) {
mTimestamp?.setTextColor(ContextCompat.getColor(this, R.color.dark_Timestamp))
} else {
mTimestamp?.setTextColor(ContextCompat.getColor(this, R.color.dark_TimestampOld))
}
}
private fun setColorBright() {
if (currentWatchMode == WatchMode.INTERACTIVE) {
mTime?.setTextColor(ContextCompat.getColor(this, R.color.light_bigchart_time))
statusView?.setTextColor(ContextCompat.getColor(this, R.color.light_bigchart_status))
mRelativeLayout?.setBackgroundColor(ContextCompat.getColor(this, R.color.light_background))
when (sgvLevel) {
1L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.light_highColor))
mDelta?.setTextColor(ContextCompat.getColor(this, R.color.light_highColor))
mAvgDelta?.setTextColor(ContextCompat.getColor(this, R.color.light_highColor))
}
0L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.light_midColor))
mDelta?.setTextColor(ContextCompat.getColor(this, R.color.light_midColor))
mAvgDelta?.setTextColor(ContextCompat.getColor(this, R.color.light_midColor))
}
-1L -> {
mSgv?.setTextColor(ContextCompat.getColor(this, R.color.light_lowColor))
mDelta?.setTextColor(ContextCompat.getColor(this, R.color.light_lowColor))
mAvgDelta?.setTextColor(ContextCompat.getColor(this, R.color.light_lowColor))
}
}
if (ageLevel == 1) {
mTimestamp?.setTextColor(ContextCompat.getColor(this, R.color.light_mTimestamp1))
} else {
mTimestamp?.setTextColor(ContextCompat.getColor(this, R.color.light_mTimestamp))
}
} else {
setColorDark()
}
}
private fun missedReadingAlert() {
val minutesSince = floor(timeSince() / (1000 * 60)).toInt()
if (minutesSince >= 16 && (minutesSince - 16) % 5 == 0) {
// attempt endTime recover missing data
rxBus.send(EventWearToMobile(ActionResendData("NOChart::missedReadingAlert")))
}
}
companion object {
const val SCREEN_SIZE_SMALL = 280
}
}

View file

@ -13,6 +13,7 @@ import androidx.core.content.ContextCompat
import info.nightscout.androidaps.R
import info.nightscout.androidaps.interaction.menus.MainMenuActivity
import info.nightscout.shared.SafeParse.stringToFloat
import org.joda.time.TimeOfDay
/**
* Created by andrew-warrington on 01/12/2017.
@ -35,16 +36,23 @@ class SteampunkWatchface : BaseWatchFace() {
}
override fun onTapCommand(tapType: Int, x: Int, y: Int, eventTime: Long) {
if (tapType == TAP_TYPE_TAP && x >= mChartTap.left && x <= mChartTap.right && y >= mChartTap.top && y <= mChartTap.bottom) {
if (eventTime - chartTapTime < 800) {
changeChartTimeframe()
mChartTap?.let { mChartTap ->
if (tapType == TAP_TYPE_TAP && x >= mChartTap.left && x <= mChartTap.right && y >= mChartTap.top && y <= mChartTap.bottom) {
if (eventTime - chartTapTime < 800) {
changeChartTimeframe()
}
chartTapTime = eventTime
return
}
chartTapTime = eventTime
} else if (tapType == TAP_TYPE_TAP && x >= mMainMenuTap.left && x <= mMainMenuTap.right && y >= mMainMenuTap.top && y <= mMainMenuTap.bottom) {
if (eventTime - mainMenuTapTime < 800) {
startActivity(Intent(this, MainMenuActivity::class.java).also { it.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) })
}
mMainMenuTap?.let { mMainMenuTap ->
if (tapType == TAP_TYPE_TAP && x >= mMainMenuTap.left && x <= mMainMenuTap.right && y >= mMainMenuTap.top && y <= mMainMenuTap.bottom) {
if (eventTime - mainMenuTapTime < 800) {
startActivity(Intent(this, MainMenuActivity::class.java).also { it.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) })
}
mainMenuTapTime = eventTime
return
}
mainMenuTapTime = eventTime
}
}
@ -53,14 +61,12 @@ class SteampunkWatchface : BaseWatchFace() {
}
override fun setColorDark() {
if (mLinearLayout2 != null) {
if (ageLevel() <= 0 && singleBg.timeStamp != 0L) {
mLinearLayout2.setBackgroundResource(R.drawable.redline)
mTimestamp.setTextColor(ContextCompat.getColor(this, R.color.red_600))
} else {
mLinearLayout2.setBackgroundResource(0)
mTimestamp.setTextColor(ContextCompat.getColor(this, R.color.black_86p))
}
if (ageLevel() <= 0 && singleBg.timeStamp != 0L) {
mLinearLayout2?.setBackgroundResource(R.drawable.redline)
mTimestamp?.setTextColor(ContextCompat.getColor(this, R.color.red_600))
} else {
mLinearLayout2?.setBackgroundResource(0)
mTimestamp?.setTextColor(ContextCompat.getColor(this, R.color.black_86p))
}
if (loopLevel == 0) {
mLoop?.setTextColor(ContextCompat.getColor(this, R.color.red_600))
@ -73,9 +79,9 @@ class SteampunkWatchface : BaseWatchFace() {
//ensure the glucose dial is the correct units
if (singleBg.glucoseUnits == "mmol") {
mGlucoseDial.setImageResource(R.drawable.steampunk_dial_mmol)
mGlucoseDial?.setImageResource(R.drawable.steampunk_dial_mmol)
} else {
mGlucoseDial.setImageResource(R.drawable.steampunk_dial_mgdl)
mGlucoseDial?.setImageResource(R.drawable.steampunk_dial_mgdl)
}
//convert the Sgv to degrees of rotation
@ -99,7 +105,7 @@ class SteampunkWatchface : BaseWatchFace() {
rotate.fillAfter = true
rotate.interpolator = LinearInterpolator()
rotate.duration = 1
mGlucoseDial.startAnimation(rotate)
mGlucoseDial?.startAnimation(rotate)
lastEndDegrees = rotationAngle //store the final angle as a starting point for the next rotation.
}
@ -123,15 +129,15 @@ class SteampunkWatchface : BaseWatchFace() {
}
}
if (sp.getString("delta_granularity", "2") == "1" || autoGranularity == "1") { //low
mLinearLayout.setBackgroundResource(R.drawable.steampunk_gauge_mmol_10)
mLinearLayout?.setBackgroundResource(R.drawable.steampunk_gauge_mmol_10)
deltaRotationAngle = absAvgDelta * 30f
}
if (sp.getString("delta_granularity", "2") == "2" || autoGranularity == "2") { //medium
mLinearLayout.setBackgroundResource(R.drawable.steampunk_gauge_mmol_05)
mLinearLayout?.setBackgroundResource(R.drawable.steampunk_gauge_mmol_05)
deltaRotationAngle = absAvgDelta * 60f
}
if (sp.getString("delta_granularity", "2") == "3" || autoGranularity == "3") { //high
mLinearLayout.setBackgroundResource(R.drawable.steampunk_gauge_mmol_03)
mLinearLayout?.setBackgroundResource(R.drawable.steampunk_gauge_mmol_03)
deltaRotationAngle = absAvgDelta * 100f
}
} else {
@ -144,28 +150,28 @@ class SteampunkWatchface : BaseWatchFace() {
}
}
if (sp.getString("delta_granularity", "2") == "1" || autoGranularity == "1") { //low
mLinearLayout.setBackgroundResource(R.drawable.steampunk_gauge_mgdl_20)
mLinearLayout?.setBackgroundResource(R.drawable.steampunk_gauge_mgdl_20)
deltaRotationAngle = absAvgDelta * 1.5f
}
if (sp.getString("delta_granularity", "2") == "2" || autoGranularity == "2") { //medium
mLinearLayout.setBackgroundResource(R.drawable.steampunk_gauge_mgdl_10)
mLinearLayout?.setBackgroundResource(R.drawable.steampunk_gauge_mgdl_10)
deltaRotationAngle = absAvgDelta * 3f
}
if (sp.getString("delta_granularity", "2") == "3" || autoGranularity == "3") { //high
mLinearLayout.setBackgroundResource(R.drawable.steampunk_gauge_mgdl_5)
mLinearLayout?.setBackgroundResource(R.drawable.steampunk_gauge_mgdl_5)
deltaRotationAngle = absAvgDelta * 6f
}
}
}
if (deltaRotationAngle > 40) deltaRotationAngle = 40f
mDeltaGauge.rotation = deltaRotationAngle * deltaIsNegative
mDeltaGauge?.rotation = deltaRotationAngle * deltaIsNegative
}
//rotate the minute hand.
mMinuteHand.rotation = sMinute.toFloat() * 6f
mMinuteHand?.rotation = TimeOfDay().minuteOfHour * 6f
//rotate the hour hand.
mHourHand.rotation = sHour.toFloat() * 30f + sMinute.toFloat() * 0.5f
mHourHand?.rotation = TimeOfDay().hourOfDay * 30f + TimeOfDay().minuteOfHour * 0.5f
setTextSizes()
mLoop?.setBackgroundResource(0)
if (chart != null) {
@ -175,7 +181,7 @@ class SteampunkWatchface : BaseWatchFace() {
gridColor = ContextCompat.getColor(this, R.color.grey_steampunk)
basalBackgroundColor = ContextCompat.getColor(this, R.color.basal_dark)
basalCenterColor = ContextCompat.getColor(this, R.color.basal_dark)
pointSize = if (sp.getInt("chart_timeframe", 3) < 3) {
pointSize = if (sp.getInt(R.string.key_chart_time_frame, 3) < 3) {
2
} else {
1
@ -204,38 +210,39 @@ class SteampunkWatchface : BaseWatchFace() {
}
//top row. large font unless text too big (i.e. detailedIOB)
mCOB2.textSize = fontLarge
mBasalRate.textSize = fontLarge
mCOB2?.textSize = fontLarge
mBasalRate?.textSize = fontLarge
if (status.iobDetail.length < 7) {
mIOB2.textSize = fontLarge
mIOB2?.textSize = fontLarge
} else {
mIOB2.textSize = fontSmall
mIOB2?.textSize = fontSmall
}
//bottom row. font medium unless text too long (i.e. longer than 9' timestamp)
if (mTimestamp.text.length < 3 || mLoop.text.length < 3) { //always resize these fields together, for symmetry.
mTimestamp.textSize = fontMedium
mLoop.textSize = fontMedium
} else {
mTimestamp.textSize = fontSmall
mLoop.textSize = fontSmall
mLoop?.let { mLoop ->
mTimestamp?.let { mTimestamp ->
if (mTimestamp.text.length < 3 || mLoop.text.length < 3) { //always resize these fields together, for symmetry.
mTimestamp.textSize = fontMedium
mLoop.textSize = fontMedium
} else {
mTimestamp.textSize = fontSmall
mLoop.textSize = fontSmall
}
}
}
//if both batteries are shown, make them smaller.
if (sp.getBoolean("show_uploader_battery", true) && sp.getBoolean(
"show_rig_battery", false
)
) {
mUploaderBattery.textSize = fontSmall
mRigBattery.textSize = fontSmall
if (sp.getBoolean("show_uploader_battery", true) && sp.getBoolean("show_rig_battery", false)) {
mUploaderBattery?.textSize = fontSmall
mRigBattery?.textSize = fontSmall
} else {
mUploaderBattery.textSize = fontMedium
mRigBattery.textSize = fontMedium
mUploaderBattery?.textSize = fontMedium
mRigBattery?.textSize = fontMedium
}
}
private fun changeChartTimeframe() {
var timeframe = sp.getInt("chart_timeframe", 3)
var timeframe = sp.getInt(R.string.key_chart_time_frame, 3)
timeframe = timeframe % 5 + 1
pointSize = if (timeframe < 3) {
2
@ -243,6 +250,6 @@ class SteampunkWatchface : BaseWatchFace() {
1
}
setupCharts()
sp.putString("chart_timeframe", "" + timeframe)
sp.putInt(R.string.key_chart_time_frame, timeframe)
}
}

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".watchfaces.Home" tools:deviceIds="wear_square"
android:layout_height="match_parent" tools:context=".watchfaces.AapsWatchface" tools:deviceIds="wear_square"
android:background="@color/black"
android:id="@+id/main_layout">

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".watchfaces.Home" tools:deviceIds="wear_square"
android:layout_height="match_parent" tools:context=".watchfaces.AapsWatchface" tools:deviceIds="wear_square"
android:background="@color/black"
android:id="@+id/main_layout">

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".watchfaces.Cockpit" tools:deviceIds="wear_square"
android:layout_height="match_parent" tools:context=".watchfaces.CockpitWatchface" tools:deviceIds="wear_square"
android:id="@+id/main_layout"
android:background="@drawable/airplane_cockpit_outside_clouds">

View file

@ -6,7 +6,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
tools:context=".watchfaces.DigitalStyle"
tools:context=".watchfaces.DigitalStyleWatchface"
tools:deviceIds="wear_square">
<!-- background-image with shapes elements-->
@ -425,21 +425,10 @@
android:textSize="26sp"
android:textStyle="bold" />
<!-- 12h period AM / PM-->
<TextView
android:id="@+id/timePeriod"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginStart="8sp"
android:layout_marginTop="-1.5sp"
android:fontFamily="@font/roboto_condensed_bold"
android:text="AM"
android:textColor="@color/light_grey"
android:textSize="10sp"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<!-- right side 1/2 height - bottom halft -->

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".watchfaces.Home" tools:deviceIds="wear_square"
android:layout_height="match_parent" tools:context=".watchfaces.AapsWatchface" tools:deviceIds="wear_square"
android:background="@color/black"
android:id="@+id/main_layout">

View file

@ -5,7 +5,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
tools:context=".watchfaces.Home2"
tools:context=".watchfaces.AapsV2Watchface"
tools:deviceIds="wear_square">
<LinearLayout

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".watchfaces.Home" tools:deviceIds="wear_square"
android:layout_height="match_parent" tools:context=".watchfaces.AapsWatchface" tools:deviceIds="wear_square"
android:background="@color/black"
android:id="@+id/main_layout">

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".watchfaces.Home" tools:deviceIds="wear_square"
android:layout_height="match_parent" tools:context=".watchfaces.AapsWatchface" tools:deviceIds="wear_square"
android:background="@color/black"
android:id="@+id/main_layout">

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".watchfaces.Home" tools:deviceIds="wear_square"
android:layout_height="match_parent" tools:context=".watchfaces.AapsWatchface" tools:deviceIds="wear_square"
android:background="@color/black"
android:id="@+id/main_layout">

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".watchfaces.Home" tools:deviceIds="wear_square"
android:layout_height="match_parent" tools:context=".watchfaces.AapsWatchface" tools:deviceIds="wear_square"
android:background="@color/black"
android:id="@+id/main_layout">

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".watchfaces.Home" tools:deviceIds="wear_square"
android:layout_height="match_parent" tools:context=".watchfaces.AapsWatchface" tools:deviceIds="wear_square"
android:background="@color/black"
android:id="@+id/main_layout">

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".watchfaces.Cockpit" tools:deviceIds="wear_round"
android:layout_height="match_parent" tools:context=".watchfaces.CockpitWatchface" tools:deviceIds="wear_round"
android:id="@+id/main_layout"
android:background="@drawable/airplane_cockpit_outside_clouds">

View file

@ -6,7 +6,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
tools:context=".watchfaces.DigitalStyle"
tools:context=".watchfaces.DigitalStyleWatchface"
tools:deviceIds="wear_round">
<!-- background-image with shapes elements-->
@ -425,21 +425,10 @@
android:textSize="26sp"
android:textStyle="bold" />
<!-- 12h period AM / PM -->
<TextView
android:id="@+id/timePeriod"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8sp"
android:layout_marginTop="-1.5sp"
android:fontFamily="@font/roboto_condensed_bold"
android:gravity="top"
android:text="AM"
android:textColor="@color/light_grey"
android:textSize="10sp"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<!-- right side 1/2 height - bottom halft -->

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".watchfaces.Home" tools:deviceIds="wear_round"
android:layout_height="match_parent" tools:context=".watchfaces.AapsWatchface" tools:deviceIds="wear_round"
android:background="@color/black"
android:id="@+id/main_layout">

View file

@ -5,7 +5,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
tools:context=".watchfaces.Home2"
tools:context=".watchfaces.AapsV2Watchface"
tools:deviceIds="wear_round">
<LinearLayout

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".watchfaces.Home" tools:deviceIds="wear_round"
android:layout_height="match_parent" tools:context=".watchfaces.AapsWatchface" tools:deviceIds="wear_round"
android:background="@color/black"
android:id="@+id/main_layout">

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".watchfaces.Home" tools:deviceIds="wear_square"
android:layout_height="match_parent" tools:context=".watchfaces.AapsWatchface" tools:deviceIds="wear_square"
android:background="@color/black"
android:id="@+id/main_layout">

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".watchfaces.Home" tools:deviceIds="wear_square"
android:layout_height="match_parent" tools:context=".watchfaces.AapsWatchface" tools:deviceIds="wear_square"
android:background="@color/black"
android:id="@+id/main_layout">

View file

@ -4,15 +4,15 @@
<string name="app_name">AAPS</string>
<string name="label_actions_activity">AAPS</string>
<string name="label_xdrip">AAPS</string>
<string name="label_xdrip_large">AAPS(Large)</string>
<string name="label_xdrip_big_chart">AAPS(BigChart)</string>
<string name="label_xdrip_no_chart">AAPS(NoChart)</string>
<string name="label_xdrip_circle">AAPS(Circle)</string>
<string name="label_xdrip_v2">AAPSv2</string>
<string name="label_xdrip_cockpit">AAPS(Cockpit)</string>
<string name="label_xdrip_steampunk">AAPS(Steampunk)</string>
<string name="label_digitalstyle">AAPS(DigitalStyle)</string>
<string name="label_watchface">AAPS</string>
<string name="label_watchface_large">AAPS(Large)</string>
<string name="label_watchface_big_chart">AAPS(BigChart)</string>
<string name="label_watchface_no_chart">AAPS(NoChart)</string>
<string name="label_watchface_circle">AAPS(Circle)</string>
<string name="label_watchface_v2">AAPS(v2)</string>
<string name="label_watchface_cockpit">AAPS(Cockpit)</string>
<string name="label_watchface_steampunk">AAPS(Steampunk)</string>
<string name="label_watchface_digital_style">AAPS(DigitalStyle)</string>
<string name="label_actions_tile">AAPS(Actions)</string>
<string name="label_temp_target_tile">AAPS(Temp Target)</string>
@ -196,5 +196,16 @@
<string name="key_single_target" translatable="false">singletarget</string>
<string name="key_wizard_percentage" translatable="false">wizardpercentage</string>
<string name="key_highlight_basals" translatable="false">highlight_basals</string>
<string name="key_chart_time_frame" translatable="false">chart_time_frame</string>
<string name="key_show_week_number" translatable="false">show_week_number</string>
<string name="key_show_date" translatable="false">show_date</string>
<string name="key_show_cob" translatable="false">show_cob</string>
<string name="key_show_bg" translatable="false">showBG</string>
<string name="key_show_external_status" translatable="false">showExternalStatus</string>
<string name="key_show_ago" translatable="false">showAgo</string>
<string name="key_show_big_numbers" translatable="false">showBigNumbers</string>
<string name="key_show_delta" translatable="false">showDelta</string>
<string name="key_show_avg_delta" translatable="false">showAvgDelta</string>
<string name="key_show_ring_history" translatable="false">showRingHistory</string>
</resources>

View file

@ -12,7 +12,7 @@
<CheckBoxPreference
android:defaultValue="true"
android:key="show_cob"
android:key="@string/key_show_cob"
android:summary="Show carb on board."
android:title="@string/pref_show_cob"
app:wear_iconOff="@drawable/settings_off"
@ -20,7 +20,7 @@
<CheckBoxPreference
android:defaultValue="true"
android:key="showBG"
android:key="@string/key_show_bg"
android:summary="Show BG."
android:title="@string/pref_show_bg"
app:wear_iconOff="@drawable/settings_off"
@ -28,7 +28,7 @@
<CheckBoxPreference
android:defaultValue="true"
android:key="showDelta"
android:key="@string/key_show_delta"
android:summary="Show delta."
android:title="@string/pref_show_delta"
app:wear_iconOff="@drawable/settings_off"
@ -36,7 +36,7 @@
<CheckBoxPreference
android:defaultValue="true"
android:key="showAvgDelta"
android:key="@string/key_show_avg_delta"
android:summary="Show the avgDelta."
android:title="@string/pref_show_avgdelta"
app:wear_iconOff="@drawable/settings_off"
@ -51,7 +51,7 @@
<CheckBoxPreference
android:defaultValue="true"
android:key="showAgo"
android:key="@string/key_show_ago"
android:summary="Minutes since last reading."
android:title="@string/pref_show_ago"
app:wear_iconOff="@drawable/settings_off"
@ -80,7 +80,7 @@
<CheckBoxPreference
android:defaultValue="true"
android:key="showExternalStatus"
android:key="@string/key_show_external_status"
android:title="@string/pref_show_loop_status"
app:wear_iconOff="@drawable/settings_off"
app:wear_iconOn="@drawable/settings_on" />
@ -97,7 +97,7 @@
android:defaultValue="3"
android:entries="@array/chart_timeframe"
android:entryValues="@array/chart_timeframe_values"
android:key="chart_timeframe"
android:key="@string/key_chart_time_frame"
android:summary="Chart Timeframe"
android:title="@string/pref_chart_timeframe" />

View file

@ -12,7 +12,7 @@
<CheckBoxPreference
android:defaultValue="false"
android:key="showBigNumbers"
android:key="@string/key_show_big_numbers"
android:summary="Big numbers. (Circle WF)"
android:title="@string/pref_big_numbers"
app:wear_iconOff="@drawable/settings_off"
@ -20,7 +20,7 @@
<CheckBoxPreference
android:defaultValue="false"
android:key="showRingHistory"
android:key="@string/key_show_ring_history"
android:summary="Graphical history. (Circle WF)"
android:title="@string/pref_ring_history"
app:wear_iconOff="@drawable/settings_off"

View file

@ -31,14 +31,14 @@
<CheckBoxPreference
android:defaultValue="true"
android:key="show_date"
android:key="@string/key_show_date"
android:title="@string/pref_show_date"
app:wear_iconOff="@drawable/settings_off"
app:wear_iconOn="@drawable/settings_on" />
<CheckBoxPreference
android:defaultValue="false"
android:key="show_weeknumber"
android:key="@string/key_show_week_number"
android:title="@string/pref_show_weeknumber"
app:wear_iconOff="@drawable/settings_off"
app:wear_iconOn="@drawable/settings_on" />

View file

@ -20,7 +20,7 @@
<CheckBoxPreference
android:defaultValue="false"
android:key="show_date"
android:key="@string/key_show_date"
android:title="@string/pref_show_date"
app:wear_iconOff="@drawable/settings_off"
app:wear_iconOn="@drawable/settings_on" />