Merge pull request #2308 from Andries-Smit/wear/extract-simple-ui
Wear extract simple UI
This commit is contained in:
commit
b9486f6b86
2 changed files with 182 additions and 134 deletions
|
@ -1,20 +1,16 @@
|
||||||
@file:Suppress("DEPRECATION")
|
@file:Suppress("DEPRECATION")
|
||||||
|
|
||||||
package info.nightscout.androidaps.watchfaces.utils
|
package info.nightscout.androidaps.watchfaces.utils
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.BroadcastReceiver
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
|
||||||
import android.graphics.*
|
import android.graphics.*
|
||||||
import android.os.BatteryManager
|
|
||||||
import android.os.Vibrator
|
import android.os.Vibrator
|
||||||
import android.support.wearable.watchface.WatchFaceStyle
|
import android.support.wearable.watchface.WatchFaceStyle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.WindowInsets
|
import android.view.WindowInsets
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import androidx.core.content.ContextCompat
|
|
||||||
import androidx.viewbinding.ViewBinding
|
import androidx.viewbinding.ViewBinding
|
||||||
import com.ustwo.clockwise.common.WatchFaceTime
|
import com.ustwo.clockwise.common.WatchFaceTime
|
||||||
import com.ustwo.clockwise.common.WatchMode
|
import com.ustwo.clockwise.common.WatchMode
|
||||||
|
@ -24,21 +20,20 @@ import dagger.android.AndroidInjection
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.data.RawDisplayData
|
import info.nightscout.androidaps.data.RawDisplayData
|
||||||
import info.nightscout.androidaps.events.EventWearPreferenceChange
|
import info.nightscout.androidaps.events.EventWearPreferenceChange
|
||||||
import info.nightscout.rx.events.EventWearToMobile
|
|
||||||
import info.nightscout.shared.extensions.toVisibility
|
|
||||||
import info.nightscout.shared.extensions.toVisibilityKeepSpace
|
|
||||||
import info.nightscout.androidaps.interaction.menus.MainMenuActivity
|
import info.nightscout.androidaps.interaction.menus.MainMenuActivity
|
||||||
import info.nightscout.androidaps.interaction.utils.Persistence
|
import info.nightscout.androidaps.interaction.utils.Persistence
|
||||||
import info.nightscout.androidaps.interaction.utils.WearUtil
|
import info.nightscout.androidaps.interaction.utils.WearUtil
|
||||||
import info.nightscout.rx.bus.RxBus
|
|
||||||
import info.nightscout.shared.utils.DateUtil
|
|
||||||
import info.nightscout.rx.AapsSchedulers
|
import info.nightscout.rx.AapsSchedulers
|
||||||
|
import info.nightscout.rx.bus.RxBus
|
||||||
|
import info.nightscout.rx.events.EventWearToMobile
|
||||||
import info.nightscout.rx.logging.AAPSLogger
|
import info.nightscout.rx.logging.AAPSLogger
|
||||||
import info.nightscout.rx.logging.LTag
|
import info.nightscout.rx.logging.LTag
|
||||||
|
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
|
||||||
import info.nightscout.rx.weardata.EventData
|
import info.nightscout.rx.weardata.EventData
|
||||||
import info.nightscout.rx.weardata.EventData.ActionResendData
|
import info.nightscout.rx.weardata.EventData.ActionResendData
|
||||||
|
import info.nightscout.shared.extensions.toVisibility
|
||||||
|
import info.nightscout.shared.extensions.toVisibilityKeepSpace
|
||||||
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
|
import info.nightscout.shared.utils.DateUtil
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -60,6 +55,7 @@ abstract class BaseWatchFace : WatchFace() {
|
||||||
@Inject lateinit var aapsSchedulers: AapsSchedulers
|
@Inject lateinit var aapsSchedulers: AapsSchedulers
|
||||||
@Inject lateinit var sp: SP
|
@Inject lateinit var sp: SP
|
||||||
@Inject lateinit var dateUtil: DateUtil
|
@Inject lateinit var dateUtil: DateUtil
|
||||||
|
@Inject lateinit var simpleUi: SimpleUi
|
||||||
|
|
||||||
private var disposable = CompositeDisposable()
|
private var disposable = CompositeDisposable()
|
||||||
private val rawData = RawDisplayData()
|
private val rawData = RawDisplayData()
|
||||||
|
@ -69,8 +65,6 @@ abstract class BaseWatchFace : WatchFace() {
|
||||||
private val treatmentData get() = rawData.treatmentData
|
private val treatmentData get() = rawData.treatmentData
|
||||||
private val graphData get() = rawData.graphData
|
private val graphData get() = rawData.graphData
|
||||||
|
|
||||||
// Layout
|
|
||||||
// @LayoutRes abstract fun layoutResource(): Int
|
|
||||||
abstract fun inflateLayout(inflater: LayoutInflater): ViewBinding
|
abstract fun inflateLayout(inflater: LayoutInflater): ViewBinding
|
||||||
|
|
||||||
private val displaySize = Point()
|
private val displaySize = Point()
|
||||||
|
@ -100,28 +94,17 @@ abstract class BaseWatchFace : WatchFace() {
|
||||||
private var specW = 0
|
private var specW = 0
|
||||||
private var specH = 0
|
private var specH = 0
|
||||||
var forceSquareCanvas = false // Set to true by the Steampunk watch face.
|
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 lateinit var binding: WatchfaceViewAdapter
|
private lateinit var binding: WatchfaceViewAdapter
|
||||||
|
|
||||||
private var mLastSvg = ""
|
private var mLastSvg = ""
|
||||||
private var mLastDirection = ""
|
private var mLastDirection = ""
|
||||||
private var mYOffset = 0f
|
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
// Not derived from DaggerService, do injection here
|
// Not derived from DaggerService, do injection here
|
||||||
AndroidInjection.inject(this)
|
AndroidInjection.inject(this)
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
colorDarkHigh = ContextCompat.getColor(this, R.color.dark_highColor)
|
simpleUi.onCreate(::forceUpdate)
|
||||||
colorDarkMid = ContextCompat.getColor(this, R.color.dark_midColor)
|
|
||||||
colorDarkLow = ContextCompat.getColor(this, R.color.dark_lowColor)
|
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
(getSystemService(WINDOW_SERVICE) as WindowManager).defaultDisplay.getSize(displaySize)
|
(getSystemService(WINDOW_SERVICE) as WindowManager).defaultDisplay.getSize(displaySize)
|
||||||
specW = View.MeasureSpec.makeMeasureSpec(displaySize.x, View.MeasureSpec.EXACTLY)
|
specW = View.MeasureSpec.makeMeasureSpec(displaySize.x, View.MeasureSpec.EXACTLY)
|
||||||
|
@ -130,7 +113,7 @@ abstract class BaseWatchFace : WatchFace() {
|
||||||
.toObservable(EventWearPreferenceChange::class.java)
|
.toObservable(EventWearPreferenceChange::class.java)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.subscribe { event: EventWearPreferenceChange ->
|
.subscribe { event: EventWearPreferenceChange ->
|
||||||
setupBatteryReceiver()
|
simpleUi.updatePreferences()
|
||||||
if (event.changedKey != null && event.changedKey == "delta_granularity") rxBus.send(EventWearToMobile(ActionResendData("BaseWatchFace:onSharedPreferenceChanged")))
|
if (event.changedKey != null && event.changedKey == "delta_granularity") rxBus.send(EventWearToMobile(ActionResendData("BaseWatchFace:onSharedPreferenceChanged")))
|
||||||
if (layoutSet) setDataFields()
|
if (layoutSet) setDataFields()
|
||||||
invalidate()
|
invalidate()
|
||||||
|
@ -141,7 +124,7 @@ abstract class BaseWatchFace : WatchFace() {
|
||||||
.subscribe {
|
.subscribe {
|
||||||
// this event is received as last batch of data
|
// this event is received as last batch of data
|
||||||
rawData.updateFromPersistence(persistence)
|
rawData.updateFromPersistence(persistence)
|
||||||
if (!isSimpleUi || !needUpdate()) {
|
if (!simpleUi.isEnabled(currentWatchMode) || !needUpdate()) {
|
||||||
setupCharts()
|
setupCharts()
|
||||||
setDataFields()
|
setDataFields()
|
||||||
}
|
}
|
||||||
|
@ -149,8 +132,6 @@ abstract class BaseWatchFace : WatchFace() {
|
||||||
}
|
}
|
||||||
rawData.updateFromPersistence(persistence)
|
rawData.updateFromPersistence(persistence)
|
||||||
persistence.turnOff()
|
persistence.turnOff()
|
||||||
setupBatteryReceiver()
|
|
||||||
setupSimpleUi()
|
|
||||||
|
|
||||||
val inflater = (getSystemService(LAYOUT_INFLATER_SERVICE) as LayoutInflater)
|
val inflater = (getSystemService(LAYOUT_INFLATER_SERVICE) as LayoutInflater)
|
||||||
val bindLayout = inflateLayout(inflater)
|
val bindLayout = inflateLayout(inflater)
|
||||||
|
@ -160,6 +141,11 @@ abstract class BaseWatchFace : WatchFace() {
|
||||||
rxBus.send(EventWearToMobile(ActionResendData("BaseWatchFace::onCreate")))
|
rxBus.send(EventWearToMobile(ActionResendData("BaseWatchFace::onCreate")))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun forceUpdate() {
|
||||||
|
setDataFields()
|
||||||
|
invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onTapCommand(tapType: Int, x: Int, y: Int, eventTime: Long) {
|
override fun onTapCommand(tapType: Int, x: Int, y: Int, eventTime: Long) {
|
||||||
binding.chart?.let { chart ->
|
binding.chart?.let { chart ->
|
||||||
if (tapType == TAP_TYPE_TAP && x >= chart.left && x <= chart.right && y >= chart.top && y <= chart.bottom) {
|
if (tapType == TAP_TYPE_TAP && x >= chart.left && x <= chart.right && y >= chart.top && y <= chart.bottom) {
|
||||||
|
@ -209,45 +195,6 @@ abstract class BaseWatchFace : WatchFace() {
|
||||||
return WatchFaceStyle.Builder(this).setAcceptsTapEvents(true).build()
|
return WatchFaceStyle.Builder(this).setAcceptsTapEvents(true).build()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupBatteryReceiver() {
|
|
||||||
val setting = sp.getString(R.string.key_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) {
|
override fun onLayout(shape: WatchShape, screenBounds: Rect, screenInsets: WindowInsets) {
|
||||||
super.onLayout(shape, screenBounds, screenInsets)
|
super.onLayout(shape, screenBounds, screenInsets)
|
||||||
layoutView?.onApplyWindowInsets(screenInsets)
|
layoutView?.onApplyWindowInsets(screenInsets)
|
||||||
|
@ -280,9 +227,7 @@ abstract class BaseWatchFace : WatchFace() {
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
disposable.clear()
|
disposable.clear()
|
||||||
if (batteryReceiver != null) {
|
simpleUi.onDestroy()
|
||||||
unregisterReceiver(batteryReceiver)
|
|
||||||
}
|
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,8 +236,8 @@ abstract class BaseWatchFace : WatchFace() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDraw(canvas: Canvas) {
|
override fun onDraw(canvas: Canvas) {
|
||||||
if (isSimpleUi) {
|
if (simpleUi.isEnabled(currentWatchMode)) {
|
||||||
onDrawSimpleUi(canvas)
|
simpleUi.onDraw(canvas, singleBg)
|
||||||
} else {
|
} else {
|
||||||
if (layoutSet) {
|
if (layoutSet) {
|
||||||
binding.mainLayout.measure(specW, specH)
|
binding.mainLayout.measure(specW, specH)
|
||||||
|
@ -303,51 +248,14 @@ abstract class BaseWatchFace : WatchFace() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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.slopeArrow + "\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) {
|
override fun onTimeChanged(oldTime: WatchFaceTime, newTime: WatchFaceTime) {
|
||||||
if (layoutSet && (newTime.hasHourChanged(oldTime) || newTime.hasMinuteChanged(oldTime))) {
|
if (layoutSet && (newTime.hasHourChanged(oldTime) || newTime.hasMinuteChanged(oldTime))) {
|
||||||
missedReadingAlert()
|
missedReadingAlert()
|
||||||
checkVibrateHourly(oldTime, newTime)
|
checkVibrateHourly(oldTime, newTime)
|
||||||
if (!isSimpleUi) setDataFields()
|
if (!simpleUi.isEnabled(currentWatchMode)) setDataFields()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("MissingPermission")
|
@SuppressLint("MissingPermission")
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
private fun checkVibrateHourly(oldTime: WatchFaceTime, newTime: WatchFaceTime) {
|
private fun checkVibrateHourly(oldTime: WatchFaceTime, newTime: WatchFaceTime) {
|
||||||
|
@ -416,7 +324,7 @@ abstract class BaseWatchFace : WatchFace() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun on24HourFormatChanged(is24HourFormat: Boolean) {
|
override fun on24HourFormatChanged(is24HourFormat: Boolean) {
|
||||||
if (!isSimpleUi) {
|
if (!simpleUi.isEnabled(currentWatchMode)) {
|
||||||
setDataFields()
|
setDataFields()
|
||||||
}
|
}
|
||||||
invalidate()
|
invalidate()
|
||||||
|
@ -453,30 +361,15 @@ abstract class BaseWatchFace : WatchFace() {
|
||||||
|
|
||||||
override fun onWatchModeChanged(watchMode: WatchMode) {
|
override fun onWatchModeChanged(watchMode: WatchMode) {
|
||||||
lowResMode = isLowRes(watchMode)
|
lowResMode = isLowRes(watchMode)
|
||||||
if (isSimpleUi) setSimpleUiAntiAlias()
|
if (simpleUi.isEnabled(currentWatchMode)) simpleUi.setAntiAlias(currentWatchMode)
|
||||||
else setDataFields()
|
else setDataFields()
|
||||||
invalidate()
|
invalidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setSimpleUiAntiAlias() {
|
|
||||||
val antiAlias = currentWatchMode == WatchMode.AMBIENT
|
|
||||||
mSvgPaint.isAntiAlias = antiAlias
|
|
||||||
mDirectionPaint.isAntiAlias = antiAlias
|
|
||||||
mTimePaint.isAntiAlias = antiAlias
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isLowRes(watchMode: WatchMode): Boolean {
|
private fun isLowRes(watchMode: WatchMode): Boolean {
|
||||||
return watchMode == WatchMode.LOW_BIT || watchMode == WatchMode.LOW_BIT_BURN_IN
|
return watchMode == WatchMode.LOW_BIT || watchMode == WatchMode.LOW_BIT_BURN_IN
|
||||||
}
|
}
|
||||||
|
|
||||||
private val isSimpleUi: Boolean
|
|
||||||
get() {
|
|
||||||
val simplify = sp.getString(R.string.key_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 setColorDark()
|
||||||
protected abstract fun setColorBright()
|
protected abstract fun setColorBright()
|
||||||
protected abstract fun setColorLowRes()
|
protected abstract fun setColorLowRes()
|
||||||
|
@ -489,7 +382,7 @@ abstract class BaseWatchFace : WatchFace() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setupCharts() {
|
fun setupCharts() {
|
||||||
if (isSimpleUi) {
|
if (simpleUi.isEnabled(currentWatchMode)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (binding.chart != null && graphData.entries.size > 0) {
|
if (binding.chart != null && graphData.entries.size > 0) {
|
||||||
|
@ -521,8 +414,6 @@ abstract class BaseWatchFace : WatchFace() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
var iFilter = IntentFilter(Intent.ACTION_BATTERY_CHANGED)
|
const val SCREEN_SIZE_SMALL = 280
|
||||||
val NORMAL_TYPEFACE: Typeface = Typeface.create(Typeface.SANS_SERIF, Typeface.NORMAL)
|
|
||||||
val BOLD_TYPEFACE: Typeface = Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,157 @@
|
||||||
|
package info.nightscout.androidaps.watchfaces.utils
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.IntentFilter
|
||||||
|
import android.graphics.Canvas
|
||||||
|
import android.graphics.Paint
|
||||||
|
import android.graphics.Point
|
||||||
|
import android.graphics.Typeface
|
||||||
|
import android.os.BatteryManager
|
||||||
|
import android.view.WindowManager
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import com.ustwo.clockwise.common.WatchMode
|
||||||
|
import com.ustwo.clockwise.wearable.WatchFace
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.rx.weardata.EventData
|
||||||
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
|
import info.nightscout.shared.utils.DateUtil
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class SimpleUi @Inject constructor(
|
||||||
|
private val context: Context,
|
||||||
|
private val sp: SP,
|
||||||
|
private val dateUtil: DateUtil
|
||||||
|
) {
|
||||||
|
private var batteryReceiver: BroadcastReceiver? = null
|
||||||
|
private var mBackgroundPaint = Paint()
|
||||||
|
private lateinit var mTimePaint: Paint
|
||||||
|
private lateinit var mSvgPaint: Paint
|
||||||
|
private lateinit var mDirectionPaint: Paint
|
||||||
|
private var mYOffset = 0f
|
||||||
|
private val colorDarkHigh = ContextCompat.getColor(context, R.color.dark_highColor)
|
||||||
|
private var colorDarkMid = ContextCompat.getColor(context, R.color.dark_midColor)
|
||||||
|
private var colorDarkLow = ContextCompat.getColor(context, R.color.dark_lowColor)
|
||||||
|
private val displaySize = Point()
|
||||||
|
private lateinit var callback: () -> Unit
|
||||||
|
|
||||||
|
fun onCreate(callback: () -> Unit) {
|
||||||
|
this.callback = callback
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
(context.getSystemService(WatchFace.WINDOW_SERVICE) as WindowManager).defaultDisplay.getSize(displaySize)
|
||||||
|
setupBatteryReceiver()
|
||||||
|
setupUi()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updatePreferences() {
|
||||||
|
setupBatteryReceiver()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setAntiAlias(currentWatchMode: WatchMode) {
|
||||||
|
val antiAlias = currentWatchMode == WatchMode.AMBIENT
|
||||||
|
mSvgPaint.isAntiAlias = antiAlias
|
||||||
|
mDirectionPaint.isAntiAlias = antiAlias
|
||||||
|
mTimePaint.isAntiAlias = antiAlias
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isEnabled(currentWatchMode: WatchMode): Boolean {
|
||||||
|
val simplify = sp.getString(R.string.key_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
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onDraw(canvas: Canvas, singleBg: EventData.SingleBg) {
|
||||||
|
canvas.drawRect(0f, 0f, displaySize.x.toFloat(), displaySize.y.toFloat(), mBackgroundPaint)
|
||||||
|
val xHalf = displaySize.x / 2f
|
||||||
|
val yThird = displaySize.y / 3f
|
||||||
|
|
||||||
|
mSvgPaint.isStrikeThruText = isOutdated(singleBg)
|
||||||
|
mSvgPaint.color = getBgColour(singleBg.sgvLevel)
|
||||||
|
mDirectionPaint.color = getBgColour(singleBg.sgvLevel)
|
||||||
|
val sSvg = singleBg.sgvString
|
||||||
|
val svgWidth = mSvgPaint.measureText(sSvg)
|
||||||
|
val sDirection = " " + singleBg.slopeArrow + "\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)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onDestroy() {
|
||||||
|
if (batteryReceiver != null) {
|
||||||
|
context.unregisterReceiver(batteryReceiver)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isOutdated(singleBg: EventData.SingleBg): Boolean {
|
||||||
|
val timeSince = (System.currentTimeMillis() - singleBg.timeStamp).toDouble()
|
||||||
|
return singleBg.timeStamp > 0 && (timeSince <= 1000 * 60 * 12)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getBgColour(level: Long): Int {
|
||||||
|
if (level == 1L) {
|
||||||
|
return colorDarkHigh
|
||||||
|
}
|
||||||
|
return if (level == 0L) {
|
||||||
|
colorDarkMid
|
||||||
|
} else colorDarkLow
|
||||||
|
}
|
||||||
|
|
||||||
|
private val isCharging: Boolean
|
||||||
|
get() {
|
||||||
|
val mBatteryStatus = context.registerReceiver(null, iFilter)
|
||||||
|
val status = mBatteryStatus?.getIntExtra(BatteryManager.EXTRA_STATUS, -1)
|
||||||
|
return status == BatteryManager.BATTERY_STATUS_CHARGING || status == BatteryManager.BATTERY_STATUS_FULL
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupUi() {
|
||||||
|
val black = ContextCompat.getColor(context, R.color.black)
|
||||||
|
mBackgroundPaint.color = black
|
||||||
|
val white = ContextCompat.getColor(context, R.color.white)
|
||||||
|
val resources = context.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 setupBatteryReceiver() {
|
||||||
|
val setting = sp.getString(R.string.key_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) {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
context.registerReceiver(batteryReceiver, intentBatteryFilter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue