Merge pull request #1799 from Andries-Smit/chore/wear-to-kt
Chore: Wear OS Java to Kotlin
This commit is contained in:
commit
2d8e67e591
28 changed files with 657 additions and 755 deletions
|
@ -7,6 +7,7 @@ import android.support.wearable.complications.ComplicationData
|
|||
import android.support.wearable.complications.ComplicationText
|
||||
import dagger.android.AndroidInjection
|
||||
import info.nightscout.androidaps.data.RawDisplayData
|
||||
import info.nightscout.androidaps.interaction.utils.DisplayFormat
|
||||
import info.nightscout.androidaps.interaction.utils.SmallestDoubleString
|
||||
import info.nightscout.shared.logging.LTag
|
||||
import kotlin.math.max
|
||||
|
@ -25,8 +26,8 @@ class BrCobIobComplication : BaseComplicationProviderService() {
|
|||
override fun buildComplicationData(dataType: Int, raw: RawDisplayData, complicationPendingIntent: PendingIntent): ComplicationData? {
|
||||
var complicationData: ComplicationData? = null
|
||||
if (dataType == ComplicationData.TYPE_SHORT_TEXT) {
|
||||
val cob = SmallestDoubleString(raw.status.cob, SmallestDoubleString.Units.USE).minimise(displayFormat.MIN_FIELD_LEN_COB)
|
||||
val iob = SmallestDoubleString(raw.status.iobSum, SmallestDoubleString.Units.USE).minimise(max(displayFormat.MIN_FIELD_LEN_IOB, displayFormat.MAX_FIELD_LEN_SHORT - 1 - cob.length))
|
||||
val cob = SmallestDoubleString(raw.status.cob, SmallestDoubleString.Units.USE).minimise(DisplayFormat.MIN_FIELD_LEN_COB)
|
||||
val iob = SmallestDoubleString(raw.status.iobSum, SmallestDoubleString.Units.USE).minimise(max(DisplayFormat.MIN_FIELD_LEN_IOB, DisplayFormat.MAX_FIELD_LEN_SHORT - 1 - cob.length))
|
||||
val builder = ComplicationData.Builder(ComplicationData.TYPE_SHORT_TEXT)
|
||||
.setShortText(ComplicationText.plainText(displayFormat.basalRateSymbol() + raw.status.currentBasal))
|
||||
.setShortTitle(ComplicationText.plainText("$cob $iob"))
|
||||
|
@ -39,4 +40,4 @@ class BrCobIobComplication : BaseComplicationProviderService() {
|
|||
}
|
||||
|
||||
override fun getProviderCanonicalName(): String = BrCobIobComplication::class.java.canonicalName!!
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import android.app.PendingIntent
|
|||
import android.support.wearable.complications.ComplicationData
|
||||
import android.support.wearable.complications.ComplicationText
|
||||
import info.nightscout.androidaps.data.RawDisplayData
|
||||
import info.nightscout.androidaps.interaction.utils.DisplayFormat
|
||||
import info.nightscout.androidaps.interaction.utils.SmallestDoubleString
|
||||
import info.nightscout.shared.logging.LTag
|
||||
|
||||
|
@ -18,7 +19,7 @@ class CobIobComplication : BaseComplicationProviderService() {
|
|||
var complicationData: ComplicationData? = null
|
||||
if (dataType == ComplicationData.TYPE_SHORT_TEXT) {
|
||||
val cob = raw.status.cob
|
||||
val iob = SmallestDoubleString(raw.status.iobSum, SmallestDoubleString.Units.USE).minimise(displayFormat.MAX_FIELD_LEN_SHORT)
|
||||
val iob = SmallestDoubleString(raw.status.iobSum, SmallestDoubleString.Units.USE).minimise(DisplayFormat.MAX_FIELD_LEN_SHORT)
|
||||
val builder = ComplicationData.Builder(ComplicationData.TYPE_SHORT_TEXT)
|
||||
.setShortText(ComplicationText.plainText(cob))
|
||||
.setShortTitle(ComplicationText.plainText(iob))
|
||||
|
@ -31,4 +32,4 @@ class CobIobComplication : BaseComplicationProviderService() {
|
|||
}
|
||||
|
||||
override fun getProviderCanonicalName(): String = CobIobComplication::class.java.canonicalName!!
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import android.support.wearable.complications.ComplicationData
|
|||
import android.support.wearable.complications.ComplicationText
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.data.RawDisplayData
|
||||
import info.nightscout.androidaps.interaction.utils.DisplayFormat
|
||||
import info.nightscout.androidaps.interaction.utils.SmallestDoubleString
|
||||
import info.nightscout.shared.logging.LTag
|
||||
|
||||
|
@ -19,7 +20,7 @@ class IobIconComplication : BaseComplicationProviderService() {
|
|||
override fun buildComplicationData(dataType: Int, raw: RawDisplayData, complicationPendingIntent: PendingIntent): ComplicationData? {
|
||||
var complicationData: ComplicationData? = null
|
||||
if (dataType == ComplicationData.TYPE_SHORT_TEXT) {
|
||||
val iob = SmallestDoubleString(raw.status.iobSum, SmallestDoubleString.Units.USE).minimise(displayFormat.MAX_FIELD_LEN_SHORT)
|
||||
val iob = SmallestDoubleString(raw.status.iobSum, SmallestDoubleString.Units.USE).minimise(DisplayFormat.MAX_FIELD_LEN_SHORT)
|
||||
val builder = ComplicationData.Builder(ComplicationData.TYPE_SHORT_TEXT)
|
||||
.setShortText(ComplicationText.plainText(iob))
|
||||
.setIcon(Icon.createWithResource(this, R.drawable.ic_ins))
|
||||
|
@ -34,4 +35,4 @@ class IobIconComplication : BaseComplicationProviderService() {
|
|||
|
||||
override fun getProviderCanonicalName(): String = IobIconComplication::class.java.canonicalName!!
|
||||
override fun getComplicationAction(): ComplicationAction = ComplicationAction.BOLUS
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ class FillMenuActivity : MenuListActivity() {
|
|||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
override fun getElements(): List<MenuItem> =
|
||||
override fun provideElements(): List<MenuItem> =
|
||||
ArrayList<MenuItem>().apply {
|
||||
add(MenuItem(R.drawable.ic_canula, getString(R.string.action_preset_1)))
|
||||
add(MenuItem(R.drawable.ic_canula, getString(R.string.action_preset_2)))
|
||||
|
@ -31,4 +31,4 @@ class FillMenuActivity : MenuListActivity() {
|
|||
getString(R.string.action_free_amount) -> startActivity(Intent(this, FillActivity::class.java).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ class MainMenuActivity : MenuListActivity() {
|
|||
rxBus.send(EventWearToMobile(ActionResendData("MainMenuListActivity")))
|
||||
}
|
||||
|
||||
override fun getElements(): List<MenuItem> =
|
||||
override fun provideElements(): List<MenuItem> =
|
||||
ArrayList<MenuItem>().apply {
|
||||
if (!sp.getBoolean(R.string.key_wear_control, false)) {
|
||||
add(MenuItem(R.drawable.ic_settings, getString(R.string.menu_settings)))
|
||||
|
@ -53,4 +53,4 @@ class MainMenuActivity : MenuListActivity() {
|
|||
getString(R.string.menu_ecarb) -> startActivity(Intent(this, ECarbActivity::class.java).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ class StatusMenuActivity : MenuListActivity() {
|
|||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
override fun getElements(): List<MenuItem> =
|
||||
override fun provideElements(): List<MenuItem> =
|
||||
ArrayList<MenuItem>().apply {
|
||||
add(MenuItem(R.drawable.ic_status, getString(R.string.status_pump)))
|
||||
add(MenuItem(R.drawable.ic_loop_closed, getString(R.string.status_loop)))
|
||||
|
@ -29,4 +29,4 @@ class StatusMenuActivity : MenuListActivity() {
|
|||
getString(R.string.status_tdd) -> rxBus.send(EventWearToMobile(ActionTddStatus(System.currentTimeMillis())))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,158 +0,0 @@
|
|||
package info.nightscout.androidaps.interaction.utils;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import info.nightscout.androidaps.data.RawDisplayData;
|
||||
import info.nightscout.shared.sharedPreferences.SP;
|
||||
|
||||
@Singleton
|
||||
public class DisplayFormat {
|
||||
|
||||
@Inject SP sp;
|
||||
@Inject WearUtil wearUtil;
|
||||
|
||||
@Inject DisplayFormat() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Maximal and minimal lengths of fields/labels shown in complications, in characters
|
||||
* For MAX values - above that WearOS and watch faces may start ellipsize (...) contents
|
||||
* For MIN values - this is minimal length that can hold legible data
|
||||
*/
|
||||
public final int MAX_FIELD_LEN_LONG = 22; // this is found out empirical, for TYPE_LONG_TEXT
|
||||
public final int MAX_FIELD_LEN_SHORT = 7; // according to Wear OS docs for TYPE_SHORT_TEXT
|
||||
public final int MIN_FIELD_LEN_COB = 3; // since carbs are usually 0..99g
|
||||
public final int MIN_FIELD_LEN_IOB = 3; // IoB can range from like .1U to 99U
|
||||
|
||||
private boolean areComplicationsUnicode() {
|
||||
return sp.getBoolean("complication_unicode", true);
|
||||
}
|
||||
|
||||
public String deltaSymbol() {
|
||||
return areComplicationsUnicode() ? "\u0394" : "";
|
||||
}
|
||||
|
||||
public String verticalSeparatorSymbol() {
|
||||
return areComplicationsUnicode() ? "\u205E" : "|";
|
||||
}
|
||||
|
||||
public String basalRateSymbol() {
|
||||
return areComplicationsUnicode() ? "\u238D\u2006" : "";
|
||||
}
|
||||
|
||||
public String shortTimeSince(final long refTime) {
|
||||
|
||||
long deltaTimeMs = wearUtil.msSince(refTime);
|
||||
|
||||
if (deltaTimeMs < Constants.MINUTE_IN_MS) {
|
||||
return "0'";
|
||||
} else if (deltaTimeMs < Constants.HOUR_IN_MS) {
|
||||
int minutes = (int) (deltaTimeMs / Constants.MINUTE_IN_MS);
|
||||
return minutes + "'";
|
||||
} else if (deltaTimeMs < Constants.DAY_IN_MS) {
|
||||
int hours = (int) (deltaTimeMs / Constants.HOUR_IN_MS);
|
||||
return hours + "h";
|
||||
} else {
|
||||
int days = (int) (deltaTimeMs / Constants.DAY_IN_MS);
|
||||
if (days < 7) {
|
||||
return days + "d";
|
||||
} else {
|
||||
int weeks = days / 7;
|
||||
return weeks + "w";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String shortTrend(final RawDisplayData raw) {
|
||||
String minutes = "--";
|
||||
if (raw.getSingleBg().getTimeStamp() > 0) {
|
||||
minutes = shortTimeSince(raw.getSingleBg().getTimeStamp());
|
||||
}
|
||||
|
||||
if (minutes.length() + raw.getSingleBg().getDelta().length() + deltaSymbol().length() + 1 <= MAX_FIELD_LEN_SHORT) {
|
||||
return minutes + " " + deltaSymbol() + raw.getSingleBg().getDelta();
|
||||
}
|
||||
|
||||
// that only optimizes obvious things like 0 before . or at end, + at beginning
|
||||
String delta = (new SmallestDoubleString(raw.getSingleBg().getDelta())).minimise(MAX_FIELD_LEN_SHORT - 1);
|
||||
if (minutes.length() + delta.length() + deltaSymbol().length() + 1 <= MAX_FIELD_LEN_SHORT) {
|
||||
return minutes + " " + deltaSymbol() + delta;
|
||||
}
|
||||
|
||||
String shortDelta = (new SmallestDoubleString(raw.getSingleBg().getDelta())).minimise(MAX_FIELD_LEN_SHORT - (1 + minutes.length()));
|
||||
|
||||
return minutes + " " + shortDelta;
|
||||
}
|
||||
|
||||
public String longGlucoseLine(final RawDisplayData raw) {
|
||||
return raw.getSingleBg().getSgvString() + raw.getSingleBg().getSlopeArrow() + " " + deltaSymbol() + (new SmallestDoubleString(raw.getSingleBg().getDelta())).minimise(8) + " (" + shortTimeSince(raw.getSingleBg().getTimeStamp()) + ")";
|
||||
}
|
||||
|
||||
public String longDetailsLine(final RawDisplayData raw) {
|
||||
|
||||
final String SEP_LONG = " " + verticalSeparatorSymbol() + " ";
|
||||
final String SEP_SHORT = " " + verticalSeparatorSymbol() + " ";
|
||||
final int SEP_SHORT_LEN = SEP_SHORT.length();
|
||||
final String SEP_MIN = " ";
|
||||
|
||||
String line =
|
||||
raw.getStatus().getCob() + SEP_LONG + raw.getStatus().getIobSum() + SEP_LONG + basalRateSymbol() + raw.getStatus().getCurrentBasal();
|
||||
if (line.length() <= MAX_FIELD_LEN_LONG) {
|
||||
return line;
|
||||
}
|
||||
line = raw.getStatus().getCob() + SEP_SHORT + raw.getStatus().getIobSum() + SEP_SHORT + raw.getStatus().getCurrentBasal();
|
||||
if (line.length() <= MAX_FIELD_LEN_LONG) {
|
||||
return line;
|
||||
}
|
||||
|
||||
int remainingMax = MAX_FIELD_LEN_LONG - (raw.getStatus().getCob().length() + raw.getStatus().getCurrentBasal().length() + SEP_SHORT_LEN * 2);
|
||||
final String smallestIoB = new SmallestDoubleString(raw.getStatus().getIobSum(), SmallestDoubleString.Units.USE).minimise(Math.max(MIN_FIELD_LEN_IOB, remainingMax));
|
||||
line = raw.getStatus().getCob() + SEP_SHORT + smallestIoB + SEP_SHORT + raw.getStatus().getCurrentBasal();
|
||||
if (line.length() <= MAX_FIELD_LEN_LONG) {
|
||||
return line;
|
||||
}
|
||||
|
||||
remainingMax = MAX_FIELD_LEN_LONG - (smallestIoB.length() + raw.getStatus().getCurrentBasal().length() + SEP_SHORT_LEN * 2);
|
||||
final String simplifiedCob = new SmallestDoubleString(raw.getStatus().getCob(), SmallestDoubleString.Units.USE).minimise(Math.max(MIN_FIELD_LEN_COB, remainingMax));
|
||||
|
||||
line = simplifiedCob + SEP_SHORT + smallestIoB + SEP_SHORT + raw.getStatus().getCurrentBasal();
|
||||
if (line.length() <= MAX_FIELD_LEN_LONG) {
|
||||
return line;
|
||||
}
|
||||
|
||||
line = simplifiedCob + SEP_MIN + smallestIoB + SEP_MIN + raw.getStatus().getCurrentBasal();
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
public Pair<String, String> detailedIob(RawDisplayData raw) {
|
||||
final String iob1 = new SmallestDoubleString(raw.getStatus().getIobSum(), SmallestDoubleString.Units.USE).minimise(MAX_FIELD_LEN_SHORT);
|
||||
String iob2 = "";
|
||||
if (raw.getStatus().getIobDetail().contains("|")) {
|
||||
String[] iobs = raw.getStatus().getIobDetail().replace("(", "").replace(")", "").split("\\|");
|
||||
|
||||
String iobBolus = new SmallestDoubleString(iobs[0]).minimise(MIN_FIELD_LEN_IOB);
|
||||
if (iobBolus.trim().length() == 0) {
|
||||
iobBolus = "--";
|
||||
}
|
||||
String iobBasal = new SmallestDoubleString(iobs[1]).minimise((MAX_FIELD_LEN_SHORT - 1) - Math.max(MIN_FIELD_LEN_IOB, iobBolus.length()));
|
||||
if (iobBasal.trim().length() == 0) {
|
||||
iobBasal = "--";
|
||||
}
|
||||
iob2 = iobBolus + " " + iobBasal;
|
||||
}
|
||||
return Pair.Companion.create(iob1, iob2);
|
||||
}
|
||||
|
||||
public Pair<String, String> detailedCob(final RawDisplayData raw) {
|
||||
SmallestDoubleString cobMini = new SmallestDoubleString(raw.getStatus().getCob(), SmallestDoubleString.Units.USE);
|
||||
|
||||
String cob2 = "";
|
||||
if (cobMini.getExtra().length() > 0) {
|
||||
cob2 = cobMini.getExtra() + cobMini.getUnits();
|
||||
}
|
||||
final String cob1 = cobMini.minimise(MAX_FIELD_LEN_SHORT);
|
||||
return Pair.Companion.create(cob1, cob2);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
package info.nightscout.androidaps.interaction.utils
|
||||
|
||||
import info.nightscout.androidaps.interaction.utils.Pair.Companion.create
|
||||
import javax.inject.Singleton
|
||||
import javax.inject.Inject
|
||||
import info.nightscout.shared.sharedPreferences.SP
|
||||
import info.nightscout.androidaps.data.RawDisplayData
|
||||
import kotlin.math.max
|
||||
|
||||
@Singleton
|
||||
class DisplayFormat @Inject internal constructor() {
|
||||
|
||||
companion object {
|
||||
|
||||
const val MAX_FIELD_LEN_LONG = 22 // this is found out empirical, for TYPE_LONG_TEXT
|
||||
const val MAX_FIELD_LEN_SHORT = 7 // according to Wear OS docs for TYPE_SHORT_TEXT
|
||||
const val MIN_FIELD_LEN_COB = 3 // since carbs are usually 0..99g
|
||||
const val MIN_FIELD_LEN_IOB = 3 // IoB can range from like .1U to 99U
|
||||
}
|
||||
|
||||
@Inject lateinit var sp: SP
|
||||
@Inject lateinit var wearUtil: WearUtil
|
||||
|
||||
/**
|
||||
* Maximal and minimal lengths of fields/labels shown in complications, in characters
|
||||
* For MAX values - above that WearOS and watch faces may start ellipsize (...) contents
|
||||
* For MIN values - this is minimal length that can hold legible data
|
||||
*/
|
||||
|
||||
private fun areComplicationsUnicode() = sp.getBoolean("complication_unicode", true)
|
||||
|
||||
private fun deltaSymbol() = if (areComplicationsUnicode()) "\u0394" else ""
|
||||
|
||||
private fun verticalSeparatorSymbol() = if (areComplicationsUnicode()) "\u205E" else "|"
|
||||
|
||||
fun basalRateSymbol() = if (areComplicationsUnicode()) "\u238D\u2006" else ""
|
||||
|
||||
fun shortTimeSince(refTime: Long): String {
|
||||
val deltaTimeMs = wearUtil.msSince(refTime)
|
||||
return if (deltaTimeMs < Constants.MINUTE_IN_MS) {
|
||||
"0'"
|
||||
} else if (deltaTimeMs < Constants.HOUR_IN_MS) {
|
||||
val minutes = (deltaTimeMs / Constants.MINUTE_IN_MS).toInt()
|
||||
"$minutes'"
|
||||
} else if (deltaTimeMs < Constants.DAY_IN_MS) {
|
||||
val hours = (deltaTimeMs / Constants.HOUR_IN_MS).toInt()
|
||||
hours.toString() + "h"
|
||||
} else {
|
||||
val days = (deltaTimeMs / Constants.DAY_IN_MS).toInt()
|
||||
if (days < 7) {
|
||||
days.toString() + "d"
|
||||
} else {
|
||||
val weeks = days / 7
|
||||
weeks.toString() + "w"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun shortTrend(raw: RawDisplayData): String {
|
||||
var minutes = "--"
|
||||
if (raw.singleBg.timeStamp > 0) {
|
||||
minutes = shortTimeSince(raw.singleBg.timeStamp)
|
||||
}
|
||||
if (minutes.length + raw.singleBg.delta.length + deltaSymbol().length + 1 <= MAX_FIELD_LEN_SHORT) {
|
||||
return minutes + " " + deltaSymbol() + raw.singleBg.delta
|
||||
}
|
||||
|
||||
// that only optimizes obvious things like 0 before . or at end, + at beginning
|
||||
val delta = SmallestDoubleString(raw.singleBg.delta).minimise(MAX_FIELD_LEN_SHORT - 1)
|
||||
if (minutes.length + delta.length + deltaSymbol().length + 1 <= MAX_FIELD_LEN_SHORT) {
|
||||
return minutes + " " + deltaSymbol() + delta
|
||||
}
|
||||
val shortDelta = SmallestDoubleString(raw.singleBg.delta).minimise(MAX_FIELD_LEN_SHORT - (1 + minutes.length))
|
||||
return "$minutes $shortDelta"
|
||||
}
|
||||
|
||||
fun longGlucoseLine(raw: RawDisplayData): String {
|
||||
return raw.singleBg.sgvString + raw.singleBg.slopeArrow + " " + deltaSymbol() + SmallestDoubleString(raw.singleBg.delta).minimise(8) + " (" + shortTimeSince(raw.singleBg.timeStamp) + ")"
|
||||
}
|
||||
|
||||
fun longDetailsLine(raw: RawDisplayData): String {
|
||||
val sepLong = " " + verticalSeparatorSymbol() + " "
|
||||
val sepShort = " " + verticalSeparatorSymbol() + " "
|
||||
val sepShortLen = sepShort.length
|
||||
val sepMin = " "
|
||||
var line = raw.status.cob + sepLong + raw.status.iobSum + sepLong + basalRateSymbol() + raw.status.currentBasal
|
||||
if (line.length <= MAX_FIELD_LEN_LONG) {
|
||||
return line
|
||||
}
|
||||
line = raw.status.cob + sepShort + raw.status.iobSum + sepShort + raw.status.currentBasal
|
||||
if (line.length <= MAX_FIELD_LEN_LONG) {
|
||||
return line
|
||||
}
|
||||
var remainingMax = MAX_FIELD_LEN_LONG - (raw.status.cob.length + raw.status.currentBasal.length + sepShortLen * 2)
|
||||
val smallestIoB = SmallestDoubleString(raw.status.iobSum, SmallestDoubleString.Units.USE).minimise(max(MIN_FIELD_LEN_IOB, remainingMax))
|
||||
line = raw.status.cob + sepShort + smallestIoB + sepShort + raw.status.currentBasal
|
||||
if (line.length <= MAX_FIELD_LEN_LONG) {
|
||||
return line
|
||||
}
|
||||
remainingMax = MAX_FIELD_LEN_LONG - (smallestIoB.length + raw.status.currentBasal.length + sepShortLen * 2)
|
||||
val simplifiedCob = SmallestDoubleString(raw.status.cob, SmallestDoubleString.Units.USE).minimise(max(MIN_FIELD_LEN_COB, remainingMax))
|
||||
line = simplifiedCob + sepShort + smallestIoB + sepShort + raw.status.currentBasal
|
||||
if (line.length <= MAX_FIELD_LEN_LONG) {
|
||||
return line
|
||||
}
|
||||
line = simplifiedCob + sepMin + smallestIoB + sepMin + raw.status.currentBasal
|
||||
return line
|
||||
}
|
||||
|
||||
fun detailedIob(raw: RawDisplayData): Pair<String, String> {
|
||||
val iob1 = SmallestDoubleString(raw.status.iobSum, SmallestDoubleString.Units.USE).minimise(MAX_FIELD_LEN_SHORT)
|
||||
var iob2 = ""
|
||||
if (raw.status.iobDetail.contains("|")) {
|
||||
val iobs = raw.status.iobDetail.replace("(", "").replace(")", "").split("|").toTypedArray()
|
||||
var iobBolus = SmallestDoubleString(iobs[0]).minimise(MIN_FIELD_LEN_IOB)
|
||||
if (iobBolus.trim().isEmpty()) {
|
||||
iobBolus = "--"
|
||||
}
|
||||
var iobBasal = SmallestDoubleString(iobs[1]).minimise(MAX_FIELD_LEN_SHORT - 1 - max(MIN_FIELD_LEN_IOB, iobBolus.length))
|
||||
if (iobBasal.trim().isEmpty()) {
|
||||
iobBasal = "--"
|
||||
}
|
||||
iob2 = "$iobBolus $iobBasal"
|
||||
}
|
||||
return create(iob1, iob2)
|
||||
}
|
||||
|
||||
fun detailedCob(raw: RawDisplayData): Pair<String, String> {
|
||||
val cobMini = SmallestDoubleString(raw.status.cob, SmallestDoubleString.Units.USE)
|
||||
var cob2 = ""
|
||||
if (cobMini.extra.isNotEmpty()) {
|
||||
cob2 = cobMini.extra + cobMini.units
|
||||
}
|
||||
val cob1 = cobMini.minimise(MAX_FIELD_LEN_SHORT)
|
||||
return create(cob1, cob2)
|
||||
}
|
||||
}
|
|
@ -1,160 +0,0 @@
|
|||
package info.nightscout.androidaps.interaction.utils;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.wear.widget.CurvedTextView;
|
||||
import androidx.wear.widget.WearableLinearLayoutManager;
|
||||
import androidx.wear.widget.WearableRecyclerView;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import dagger.android.DaggerActivity;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||
import info.nightscout.shared.sharedPreferences.SP;
|
||||
|
||||
/**
|
||||
* Created by adrian on 08/02/17.
|
||||
*/
|
||||
|
||||
public abstract class MenuListActivity extends DaggerActivity {
|
||||
|
||||
@Inject public RxBus rxBus;
|
||||
@Inject public SP sp;
|
||||
|
||||
List<MenuItem> elements;
|
||||
|
||||
protected abstract List<MenuItem> getElements();
|
||||
|
||||
protected abstract void doAction(String position);
|
||||
|
||||
public interface AdapterCallback {
|
||||
void onItemClicked(MenuAdapter.ItemViewHolder v);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.actions_list_activity);
|
||||
setTitleBasedOnScreenShape(String.valueOf(getTitle()));
|
||||
|
||||
elements = getElements();
|
||||
CustomScrollingLayoutCallback customScrollingLayoutCallback = new CustomScrollingLayoutCallback();
|
||||
WearableLinearLayoutManager layoutManager = new WearableLinearLayoutManager(this);
|
||||
WearableRecyclerView listView = findViewById(R.id.action_list);
|
||||
boolean isScreenRound = this.getResources().getConfiguration().isScreenRound();
|
||||
if (isScreenRound) {
|
||||
layoutManager.setLayoutCallback(customScrollingLayoutCallback);
|
||||
listView.setEdgeItemsCenteringEnabled(true);
|
||||
} else {
|
||||
// Bug in androidx.wear:wear:1.2.0
|
||||
// WearableRecyclerView setEdgeItemsCenteringEnabled requires fix for square screen
|
||||
listView.setPadding(0, 50, 0, 0);
|
||||
}
|
||||
listView.setHasFixedSize(true);
|
||||
listView.setLayoutManager(layoutManager);
|
||||
listView.setAdapter(new MenuAdapter(elements, v -> {
|
||||
String tag = (String) v.itemView.getTag();
|
||||
doAction(tag);
|
||||
}));
|
||||
}
|
||||
|
||||
private void setTitleBasedOnScreenShape(String title) {
|
||||
CurvedTextView titleViewCurved = findViewById(R.id.title_curved);
|
||||
TextView titleView = findViewById(R.id.title);
|
||||
if (this.getResources().getConfiguration().isScreenRound()) {
|
||||
titleViewCurved.setText(title);
|
||||
titleViewCurved.setVisibility(View.VISIBLE);
|
||||
titleView.setVisibility((View.GONE));
|
||||
} else {
|
||||
titleView.setText(title);
|
||||
titleView.setVisibility(View.VISIBLE);
|
||||
titleViewCurved.setVisibility((View.GONE));
|
||||
}
|
||||
}
|
||||
|
||||
private static class MenuAdapter extends RecyclerView.Adapter<MenuAdapter.ItemViewHolder> {
|
||||
private final List<MenuItem> mDataset;
|
||||
private final AdapterCallback callback;
|
||||
|
||||
public MenuAdapter(List<MenuItem> dataset, AdapterCallback callback) {
|
||||
mDataset = dataset;
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
public static class ItemViewHolder extends RecyclerView.ViewHolder {
|
||||
protected final RelativeLayout menuContainer;
|
||||
protected final TextView actionItem;
|
||||
protected final ImageView actionIcon;
|
||||
|
||||
public ItemViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
menuContainer = itemView.findViewById(R.id.menu_container);
|
||||
actionItem = itemView.findViewById(R.id.menuItemText);
|
||||
actionIcon = itemView.findViewById(R.id.menuItemIcon);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull @Override
|
||||
public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
|
||||
|
||||
return new ItemViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(ItemViewHolder holder, final int position) {
|
||||
MenuItem item = mDataset.get(position);
|
||||
holder.actionItem.setText(item.actionItem);
|
||||
holder.actionIcon.setImageResource(item.actionIcon);
|
||||
holder.itemView.setTag(item.actionItem);
|
||||
holder.menuContainer.setOnClickListener(v -> callback.onItemClicked(holder));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mDataset.size();
|
||||
}
|
||||
}
|
||||
|
||||
protected static class MenuItem {
|
||||
public MenuItem(int actionIcon, String actionItem) {
|
||||
this.actionIcon = actionIcon;
|
||||
this.actionItem = actionItem;
|
||||
}
|
||||
|
||||
public int actionIcon;
|
||||
public String actionItem;
|
||||
}
|
||||
|
||||
public static class CustomScrollingLayoutCallback extends WearableLinearLayoutManager.LayoutCallback {
|
||||
// How much should we scale the icon at most.
|
||||
private static final float MAX_ICON_PROGRESS = 0.65f;
|
||||
|
||||
@Override
|
||||
public void onLayoutFinished(View child, RecyclerView parent) {
|
||||
// Figure out % progress from top to bottom
|
||||
float centerOffset = ((float) child.getHeight() / 2.0f) / (float) parent.getHeight();
|
||||
float yRelativeToCenterOffset = (child.getY() / parent.getHeight()) + centerOffset;
|
||||
|
||||
// Normalize for center
|
||||
float progressToCenter = Math.abs(0.5f - yRelativeToCenterOffset);
|
||||
// Adjust to the maximum scale
|
||||
progressToCenter = Math.min(progressToCenter, MAX_ICON_PROGRESS);
|
||||
|
||||
child.setScaleX(1 - progressToCenter);
|
||||
child.setScaleY(1 - progressToCenter);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
package info.nightscout.androidaps.interaction.utils
|
||||
|
||||
import dagger.android.DaggerActivity
|
||||
import javax.inject.Inject
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.shared.sharedPreferences.SP
|
||||
import info.nightscout.androidaps.interaction.utils.MenuListActivity.MenuAdapter.ItemViewHolder
|
||||
import android.os.Bundle
|
||||
import info.nightscout.androidaps.R
|
||||
import androidx.wear.widget.WearableLinearLayoutManager
|
||||
import androidx.wear.widget.CurvedTextView
|
||||
import android.widget.TextView
|
||||
import android.widget.RelativeLayout
|
||||
import android.view.ViewGroup
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.wear.widget.WearableLinearLayoutManager.LayoutCallback
|
||||
import androidx.wear.widget.WearableRecyclerView
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.min
|
||||
|
||||
/**
|
||||
* Created by adrian on 08/02/17.
|
||||
*/
|
||||
abstract class MenuListActivity : DaggerActivity() {
|
||||
|
||||
@Inject lateinit var sp: SP
|
||||
@Inject lateinit var rxBus: RxBus
|
||||
|
||||
private var elements: List<MenuItem> = listOf()
|
||||
protected abstract fun provideElements(): List<MenuItem>
|
||||
protected abstract fun doAction(position: String)
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.actions_list_activity)
|
||||
setTitleBasedOnScreenShape(title.toString())
|
||||
elements = provideElements()
|
||||
val customScrollingLayoutCallback = CustomScrollingLayoutCallback()
|
||||
val layoutManager = WearableLinearLayoutManager(this)
|
||||
val listView = findViewById<WearableRecyclerView>(R.id.action_list)
|
||||
val isScreenRound = this.resources.configuration.isScreenRound
|
||||
if (isScreenRound) {
|
||||
layoutManager.layoutCallback = customScrollingLayoutCallback
|
||||
listView.isEdgeItemsCenteringEnabled = true
|
||||
} else {
|
||||
// Bug in androidx.wear:wear:1.2.0
|
||||
// WearableRecyclerView setEdgeItemsCenteringEnabled requires fix for square screen
|
||||
listView.setPadding(0, 50, 0, 0)
|
||||
}
|
||||
listView.setHasFixedSize(true)
|
||||
listView.layoutManager = layoutManager
|
||||
listView.adapter = MenuAdapter(elements) { v: ItemViewHolder ->
|
||||
val tag = v.itemView.tag as String
|
||||
doAction(tag)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setTitleBasedOnScreenShape(title: String) {
|
||||
val titleViewCurved = findViewById<CurvedTextView>(R.id.title_curved)
|
||||
val titleView = findViewById<TextView>(R.id.title)
|
||||
if (this.resources.configuration.isScreenRound) {
|
||||
titleViewCurved.text = title
|
||||
titleViewCurved.visibility = View.VISIBLE
|
||||
titleView.visibility = View.GONE
|
||||
} else {
|
||||
titleView.text = title
|
||||
titleView.visibility = View.VISIBLE
|
||||
titleViewCurved.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
class MenuAdapter(private val mDataset: List<MenuItem>, private val callback: (ItemViewHolder) -> Unit) : RecyclerView.Adapter<ItemViewHolder>() {
|
||||
class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
|
||||
val menuContainer: RelativeLayout
|
||||
val actionItem: TextView
|
||||
val actionIcon: ImageView
|
||||
|
||||
init {
|
||||
menuContainer = itemView.findViewById(R.id.menu_container)
|
||||
actionItem = itemView.findViewById(R.id.menuItemText)
|
||||
actionIcon = itemView.findViewById(R.id.menuItemIcon)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
|
||||
val view = LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false)
|
||||
return ItemViewHolder(view)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
|
||||
val item = mDataset[position]
|
||||
holder.actionItem.text = item.actionItem
|
||||
holder.actionIcon.setImageResource(item.actionIcon)
|
||||
holder.itemView.tag = item.actionItem
|
||||
holder.menuContainer.setOnClickListener { callback(holder) }
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return mDataset.size
|
||||
}
|
||||
}
|
||||
|
||||
class MenuItem(var actionIcon: Int, var actionItem: String)
|
||||
class CustomScrollingLayoutCallback : LayoutCallback() {
|
||||
|
||||
override fun onLayoutFinished(child: View, parent: RecyclerView) {
|
||||
// Figure out % progress from top to bottom
|
||||
val centerOffset = child.height.toFloat() / 2.0f / parent.height.toFloat()
|
||||
val yRelativeToCenterOffset = child.y / parent.height + centerOffset
|
||||
|
||||
// Normalize for center
|
||||
var progressToCenter = abs(0.5f - yRelativeToCenterOffset)
|
||||
// Adjust to the maximum scale
|
||||
progressToCenter = min(progressToCenter, MAX_ICON_PROGRESS)
|
||||
child.scaleX = 1 - progressToCenter
|
||||
child.scaleY = 1 - progressToCenter
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
// How much should we scale the icon at most.
|
||||
private const val MAX_ICON_PROGRESS = 0.65f
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
package info.nightscout.androidaps.interaction.utils
|
||||
|
||||
import android.util.Base64
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import info.nightscout.shared.logging.LTag
|
||||
|
@ -182,4 +181,4 @@ class Persistence @Inject constructor(
|
|||
aapsLogger.debug(LTag.WEAR, "TURNING OFF all active complications")
|
||||
putString(KEY_COMPLICATIONS, "")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,235 +0,0 @@
|
|||
package info.nightscout.androidaps.interaction.utils;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.core.view.InputDeviceCompat;
|
||||
import androidx.core.view.MotionEventCompat;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Created by mike on 28.06.2016.
|
||||
*/
|
||||
public class PlusMinusEditText implements View.OnKeyListener,
|
||||
View.OnTouchListener, View.OnClickListener, View.OnGenericMotionListener {
|
||||
|
||||
public TextView editText;
|
||||
ImageView minusImage;
|
||||
ImageView plusImage;
|
||||
|
||||
Double value;
|
||||
Double minValue;
|
||||
Double maxValue;
|
||||
Double step;
|
||||
NumberFormat formatter;
|
||||
boolean allowZero;
|
||||
boolean roundRobin;
|
||||
|
||||
private int mChangeCounter = 0;
|
||||
private long mLastChange = 0;
|
||||
private final static int THRESHOLD_COUNTER = 5;
|
||||
private final static int THRESHOLD_COUNTER_LONG = 10;
|
||||
private final static int THRESHOLD_TIME = 100;
|
||||
|
||||
private final Handler mHandler;
|
||||
private ScheduledExecutorService mUpdater;
|
||||
|
||||
private class UpdateCounterTask implements Runnable {
|
||||
private final boolean mInc;
|
||||
private int repeated = 0;
|
||||
private int multiplier = 1;
|
||||
|
||||
public UpdateCounterTask(boolean inc) {
|
||||
mInc = inc;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
Message msg = new Message();
|
||||
int doubleLimit = 5;
|
||||
if (repeated % doubleLimit == 0) multiplier *= 2;
|
||||
repeated++;
|
||||
msg.arg1 = multiplier;
|
||||
msg.arg2 = repeated;
|
||||
if (mInc) {
|
||||
msg.what = MSG_INC;
|
||||
} else {
|
||||
msg.what = MSG_DEC;
|
||||
}
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
private static final int MSG_INC = 0;
|
||||
private static final int MSG_DEC = 1;
|
||||
|
||||
public PlusMinusEditText(View view, int editTextID, int plusID, int minusID, Double initValue, Double minValue, Double maxValue, Double step, NumberFormat formatter, boolean allowZero) {
|
||||
this(view, editTextID, plusID, minusID, initValue, minValue, maxValue, step, formatter, allowZero, false);
|
||||
}
|
||||
|
||||
public PlusMinusEditText(View view, int editTextID, int plusID, int minusID, Double initValue, Double minValue, Double maxValue, Double step, NumberFormat formatter, boolean allowZero, boolean roundRobin) {
|
||||
editText = view.findViewById(editTextID);
|
||||
minusImage = view.findViewById(minusID);
|
||||
plusImage = view.findViewById(plusID);
|
||||
|
||||
this.value = initValue;
|
||||
this.minValue = minValue;
|
||||
this.maxValue = maxValue;
|
||||
this.step = step;
|
||||
this.formatter = formatter;
|
||||
this.allowZero = allowZero;
|
||||
this.roundRobin = roundRobin;
|
||||
|
||||
mHandler = new Handler(Looper.getMainLooper()) {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case MSG_INC:
|
||||
inc(msg.arg1);
|
||||
return;
|
||||
case MSG_DEC:
|
||||
dec(msg.arg1);
|
||||
return;
|
||||
}
|
||||
super.handleMessage(msg);
|
||||
}
|
||||
};
|
||||
|
||||
minusImage.setOnTouchListener(this);
|
||||
minusImage.setOnKeyListener(this);
|
||||
minusImage.setOnClickListener(this);
|
||||
plusImage.setOnTouchListener(this);
|
||||
plusImage.setOnKeyListener(this);
|
||||
plusImage.setOnClickListener(this);
|
||||
editText.setOnGenericMotionListener(this);
|
||||
updateEditText();
|
||||
}
|
||||
|
||||
public void setValue(Double value) {
|
||||
this.value = value;
|
||||
updateEditText();
|
||||
}
|
||||
|
||||
public Double getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
private void inc(int multiplier) {
|
||||
value += step * multiplier;
|
||||
if (value > maxValue) {
|
||||
if (roundRobin) {
|
||||
value = minValue;
|
||||
} else {
|
||||
value = maxValue;
|
||||
stopUpdating();
|
||||
}
|
||||
}
|
||||
updateEditText();
|
||||
}
|
||||
|
||||
private void dec(int multiplier) {
|
||||
value -= step * multiplier;
|
||||
if (value < minValue) {
|
||||
if (roundRobin) {
|
||||
value = maxValue;
|
||||
} else {
|
||||
value = minValue;
|
||||
stopUpdating();
|
||||
}
|
||||
}
|
||||
updateEditText();
|
||||
}
|
||||
|
||||
private void updateEditText() {
|
||||
if (value == 0d && !allowZero)
|
||||
editText.setText("");
|
||||
else
|
||||
editText.setText(formatter.format(value));
|
||||
}
|
||||
|
||||
private void startUpdating(boolean inc) {
|
||||
if (mUpdater != null) {
|
||||
return;
|
||||
}
|
||||
mUpdater = Executors.newSingleThreadScheduledExecutor();
|
||||
mUpdater.scheduleAtFixedRate(new UpdateCounterTask(inc), 200, 200,
|
||||
TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
private void stopUpdating() {
|
||||
if (mUpdater != null) {
|
||||
mUpdater.shutdownNow();
|
||||
mUpdater = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (mUpdater == null) {
|
||||
if (v == plusImage) {
|
||||
inc(1);
|
||||
} else {
|
||||
dec(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
||||
boolean isKeyOfInterest = keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_ENTER;
|
||||
boolean isReleased = event.getAction() == KeyEvent.ACTION_UP;
|
||||
boolean isPressed = event.getAction() == KeyEvent.ACTION_DOWN;
|
||||
|
||||
if (isKeyOfInterest && isReleased) {
|
||||
stopUpdating();
|
||||
} else if (isKeyOfInterest && isPressed) {
|
||||
startUpdating(v == plusImage);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
boolean isReleased = event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL;
|
||||
boolean isPressed = event.getAction() == MotionEvent.ACTION_DOWN;
|
||||
|
||||
if (isReleased) {
|
||||
stopUpdating();
|
||||
} else if (isPressed) {
|
||||
startUpdating(v == plusImage);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onGenericMotion(View v, MotionEvent ev) {
|
||||
if (ev.getAction() == MotionEvent.ACTION_SCROLL && ev.isFromSource(InputDeviceCompat.SOURCE_ROTARY_ENCODER)) {
|
||||
long now = System.currentTimeMillis();
|
||||
if (now - mLastChange > THRESHOLD_TIME) mChangeCounter = 0;
|
||||
|
||||
int dynamicMultiplier = mChangeCounter < THRESHOLD_COUNTER ? 1 :
|
||||
mChangeCounter < THRESHOLD_COUNTER_LONG ? 2 : 4;
|
||||
|
||||
float delta = -ev.getAxisValue(MotionEventCompat.AXIS_SCROLL);
|
||||
if (delta > 0) {
|
||||
inc(dynamicMultiplier);
|
||||
} else {
|
||||
dec(dynamicMultiplier);
|
||||
}
|
||||
mLastChange = System.currentTimeMillis();
|
||||
mChangeCounter++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,217 @@
|
|||
package info.nightscout.androidaps.interaction.utils
|
||||
|
||||
import android.os.Handler
|
||||
import kotlin.jvm.JvmOverloads
|
||||
import android.view.View.OnTouchListener
|
||||
import android.view.View.OnGenericMotionListener
|
||||
import android.widget.TextView
|
||||
import android.view.MotionEvent
|
||||
import android.os.Looper
|
||||
import android.os.Message
|
||||
import android.view.KeyEvent
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import androidx.core.view.InputDeviceCompat
|
||||
import androidx.core.view.MotionEventCompat
|
||||
import java.text.NumberFormat
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.ScheduledExecutorService
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
* Created by mike on 28.06.2016.
|
||||
*/
|
||||
class PlusMinusEditText @JvmOverloads constructor(
|
||||
view: View,
|
||||
editTextID: Int,
|
||||
plusID: Int,
|
||||
minusID: Int,
|
||||
initValue: Double,
|
||||
minValue: Double,
|
||||
maxValue: Double,
|
||||
step: Double,
|
||||
formatter: NumberFormat,
|
||||
allowZero: Boolean,
|
||||
roundRobin: Boolean = false
|
||||
) : View.OnKeyListener, OnTouchListener, View.OnClickListener, OnGenericMotionListener {
|
||||
|
||||
var editText: TextView
|
||||
private set
|
||||
private var minusImage: ImageView
|
||||
private var plusImage: ImageView
|
||||
private var value: Double
|
||||
private var minValue: Double
|
||||
private var maxValue: Double
|
||||
private var step: Double
|
||||
private var formatter: NumberFormat
|
||||
private var allowZero: Boolean
|
||||
private var roundRobin: Boolean
|
||||
private var mChangeCounter = 0
|
||||
private var mLastChange: Long = 0
|
||||
private val mHandler: Handler
|
||||
private var mUpdater: ScheduledExecutorService? = null
|
||||
|
||||
private inner class UpdateCounterTask(private val mInc: Boolean) : Runnable {
|
||||
|
||||
private var repeated = 0
|
||||
private var multiplier = 1
|
||||
override fun run() {
|
||||
val msg = Message()
|
||||
val doubleLimit = 5
|
||||
if (repeated % doubleLimit == 0) multiplier *= 2
|
||||
repeated++
|
||||
msg.arg1 = multiplier
|
||||
msg.arg2 = repeated
|
||||
if (mInc) {
|
||||
msg.what = MSG_INC
|
||||
} else {
|
||||
msg.what = MSG_DEC
|
||||
}
|
||||
mHandler.sendMessage(msg)
|
||||
}
|
||||
}
|
||||
|
||||
private fun inc(multiplier: Int) {
|
||||
value += step * multiplier
|
||||
if (value > maxValue) {
|
||||
if (roundRobin) {
|
||||
value = minValue
|
||||
} else {
|
||||
value = maxValue
|
||||
stopUpdating()
|
||||
}
|
||||
}
|
||||
updateEditText()
|
||||
}
|
||||
|
||||
private fun dec(multiplier: Int) {
|
||||
value -= step * multiplier
|
||||
if (value < minValue) {
|
||||
if (roundRobin) {
|
||||
value = maxValue
|
||||
} else {
|
||||
value = minValue
|
||||
stopUpdating()
|
||||
}
|
||||
}
|
||||
updateEditText()
|
||||
}
|
||||
|
||||
private fun updateEditText() {
|
||||
if (value == 0.0 && !allowZero) editText.text = "" else editText.text = formatter.format(value)
|
||||
}
|
||||
|
||||
private fun startUpdating(inc: Boolean) {
|
||||
if (mUpdater != null) {
|
||||
return
|
||||
}
|
||||
|
||||
mUpdater = Executors.newSingleThreadScheduledExecutor()
|
||||
mUpdater?.scheduleAtFixedRate(
|
||||
UpdateCounterTask(inc), 200, 200,
|
||||
TimeUnit.MILLISECONDS
|
||||
)
|
||||
}
|
||||
|
||||
private fun stopUpdating() {
|
||||
mUpdater?.shutdownNow()
|
||||
mUpdater = null
|
||||
}
|
||||
|
||||
override fun onClick(v: View) {
|
||||
if (mUpdater == null) {
|
||||
if (v === plusImage) {
|
||||
inc(1)
|
||||
} else {
|
||||
dec(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onKey(v: View, keyCode: Int, event: KeyEvent): Boolean {
|
||||
val isKeyOfInterest = keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_ENTER
|
||||
val isReleased = event.action == KeyEvent.ACTION_UP
|
||||
val isPressed = event.action == KeyEvent.ACTION_DOWN
|
||||
if (isKeyOfInterest && isReleased) {
|
||||
stopUpdating()
|
||||
} else if (isKeyOfInterest && isPressed) {
|
||||
startUpdating(v === plusImage)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onTouch(v: View, event: MotionEvent): Boolean {
|
||||
val isReleased = event.action == MotionEvent.ACTION_UP || event.action == MotionEvent.ACTION_CANCEL
|
||||
val isPressed = event.action == MotionEvent.ACTION_DOWN
|
||||
if (isReleased) {
|
||||
stopUpdating()
|
||||
} else if (isPressed) {
|
||||
startUpdating(v === plusImage)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onGenericMotion(v: View, ev: MotionEvent): Boolean {
|
||||
if (ev.action == MotionEvent.ACTION_SCROLL && ev.isFromSource(InputDeviceCompat.SOURCE_ROTARY_ENCODER)) {
|
||||
val now = System.currentTimeMillis()
|
||||
if (now - mLastChange > THRESHOLD_TIME) mChangeCounter = 0
|
||||
val dynamicMultiplier = if (mChangeCounter < THRESHOLD_COUNTER) 1 else if (mChangeCounter < THRESHOLD_COUNTER_LONG) 2 else 4
|
||||
val delta = -ev.getAxisValue(MotionEventCompat.AXIS_SCROLL)
|
||||
if (delta > 0) {
|
||||
inc(dynamicMultiplier)
|
||||
} else {
|
||||
dec(dynamicMultiplier)
|
||||
}
|
||||
mLastChange = System.currentTimeMillis()
|
||||
mChangeCounter++
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private const val THRESHOLD_COUNTER = 5
|
||||
private const val THRESHOLD_COUNTER_LONG = 10
|
||||
private const val THRESHOLD_TIME = 100
|
||||
private const val MSG_INC = 0
|
||||
private const val MSG_DEC = 1
|
||||
}
|
||||
|
||||
init {
|
||||
editText = view.findViewById(editTextID)
|
||||
minusImage = view.findViewById(minusID)
|
||||
plusImage = view.findViewById(plusID)
|
||||
value = initValue
|
||||
this.minValue = minValue
|
||||
this.maxValue = maxValue
|
||||
this.step = step
|
||||
this.formatter = formatter
|
||||
this.allowZero = allowZero
|
||||
this.roundRobin = roundRobin
|
||||
mHandler = object : Handler(Looper.getMainLooper()) {
|
||||
override fun handleMessage(msg: Message) {
|
||||
when (msg.what) {
|
||||
MSG_INC -> {
|
||||
inc(msg.arg1)
|
||||
return
|
||||
}
|
||||
|
||||
MSG_DEC -> {
|
||||
dec(msg.arg1)
|
||||
return
|
||||
}
|
||||
}
|
||||
super.handleMessage(msg)
|
||||
}
|
||||
}
|
||||
minusImage.setOnTouchListener(this)
|
||||
minusImage.setOnKeyListener(this)
|
||||
minusImage.setOnClickListener(this)
|
||||
plusImage.setOnTouchListener(this)
|
||||
plusImage.setOnKeyListener(this)
|
||||
plusImage.setOnClickListener(this)
|
||||
editText.setOnGenericMotionListener(this)
|
||||
updateEditText()
|
||||
}
|
||||
}
|
|
@ -1,135 +0,0 @@
|
|||
package info.nightscout.androidaps.interaction.utils;
|
||||
|
||||
import java.math.RoundingMode;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Helper to minimise various floating point values, with or without unit, to fit into specified
|
||||
* and limited size, scarifying precision (rounding up) and extra characters like leading zero,
|
||||
* following zero(s) in fractional part, extra plus sign etc.
|
||||
*
|
||||
* Created by dlvoy on 2019-11-12
|
||||
*/
|
||||
public class SmallestDoubleString {
|
||||
|
||||
private String sign = "";
|
||||
private String decimal = "";
|
||||
private String separator = "";
|
||||
private String fractional = "";
|
||||
private String extra = "";
|
||||
private String units = "";
|
||||
|
||||
private final Units withUnits;
|
||||
|
||||
public enum Units {
|
||||
SKIP,
|
||||
USE
|
||||
}
|
||||
|
||||
private static final Pattern pattern = Pattern.compile("^([+-]?)([0-9]*)([,.]?)([0-9]*)(\\([^)]*\\))?(.*?)$", Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE );
|
||||
|
||||
public SmallestDoubleString(String inputString) {
|
||||
this(inputString, Units.SKIP);
|
||||
}
|
||||
|
||||
public SmallestDoubleString(String inputString, Units withUnits) {
|
||||
Matcher matcher = pattern.matcher(inputString);
|
||||
matcher.matches();
|
||||
|
||||
sign = matcher.group(1);
|
||||
decimal = matcher.group(2);
|
||||
separator = matcher.group(3);
|
||||
fractional = matcher.group(4);
|
||||
units = matcher.group(6);
|
||||
|
||||
if (fractional == null || fractional.length() == 0) {
|
||||
separator = "";
|
||||
fractional = "";
|
||||
}
|
||||
if (decimal == null || decimal.length() == 0) {
|
||||
decimal = "";
|
||||
}
|
||||
if (separator == null || separator.length() == 0) {
|
||||
separator = "";
|
||||
}
|
||||
if (sign == null || sign.length() == 0) {
|
||||
sign = "";
|
||||
}
|
||||
|
||||
final String extraCandidate = matcher.group(5);
|
||||
if (extraCandidate != null && extraCandidate.length() > 2) {
|
||||
extra = extraCandidate.substring(1, extraCandidate.length()-1);
|
||||
}
|
||||
|
||||
if (units != null) {
|
||||
units = units.trim();
|
||||
}
|
||||
|
||||
this.withUnits = withUnits;
|
||||
}
|
||||
|
||||
public String minimise(int maxSize) {
|
||||
final String originalSeparator = separator;
|
||||
|
||||
if (Integer.parseInt("0"+fractional) == 0) {
|
||||
separator = "";
|
||||
fractional = "";
|
||||
}
|
||||
if (Integer.parseInt("0"+decimal) == 0 && (fractional.length() >0)) {
|
||||
decimal = "";
|
||||
}
|
||||
if (currentLen() <= maxSize)
|
||||
return toString();
|
||||
|
||||
if (sign.equals("+")) {
|
||||
sign = "";
|
||||
}
|
||||
if (currentLen() <= maxSize) {
|
||||
return toString();
|
||||
}
|
||||
|
||||
while ((fractional.length() > 1)&&(fractional.charAt(fractional.length()-1) == '0')) {
|
||||
fractional = fractional.substring(0, fractional.length()-1);
|
||||
}
|
||||
if (currentLen() <= maxSize) {
|
||||
return toString();
|
||||
}
|
||||
|
||||
if (fractional.length() > 0) {
|
||||
int remainingForFraction = maxSize-currentLen()+fractional.length();
|
||||
String formatCandidate = "#";
|
||||
if (remainingForFraction>=1) {
|
||||
formatCandidate = "#."+("#######".substring(0, remainingForFraction));
|
||||
}
|
||||
DecimalFormat df = new DecimalFormat(formatCandidate);
|
||||
df.setRoundingMode(RoundingMode.HALF_UP);
|
||||
|
||||
final String decimalSup = (decimal.length() > 0) ? decimal : "0";
|
||||
String result = sign + df.format(Double.parseDouble(decimalSup+"."+fractional)).replace(",", originalSeparator).replace(".", originalSeparator) +
|
||||
((withUnits == Units.USE) ? units : "");
|
||||
return (decimal.length() > 0) ? result : result.substring(1);
|
||||
}
|
||||
return toString();
|
||||
}
|
||||
|
||||
private int currentLen() {
|
||||
return sign.length() + decimal.length() + separator.length() + fractional.length() +
|
||||
((withUnits == Units.USE) ? units.length() : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return sign+decimal+separator+fractional +
|
||||
((withUnits == Units.USE) ? units : "");
|
||||
}
|
||||
|
||||
public String getExtra() {
|
||||
return extra;
|
||||
}
|
||||
|
||||
public String getUnits() { return units; }
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
package info.nightscout.androidaps.interaction.utils
|
||||
|
||||
import kotlin.jvm.JvmOverloads
|
||||
import java.math.RoundingMode
|
||||
import java.text.DecimalFormat
|
||||
import java.util.regex.Pattern
|
||||
|
||||
/**
|
||||
* Helper to minimise various floating point values, with or without unit, to fit into specified
|
||||
* and limited size, scarifying precision (rounding up) and extra characters like leading zero,
|
||||
* following zero(s) in fractional part, extra plus sign etc.
|
||||
*
|
||||
* Created by dlvoy on 2019-11-12
|
||||
*/
|
||||
class SmallestDoubleString @JvmOverloads constructor(inputString: String, withUnits: Units = Units.SKIP) {
|
||||
|
||||
private var sign: String
|
||||
private var decimal: String
|
||||
private var separator: String
|
||||
private var fractional: String
|
||||
var extra = ""
|
||||
var units: String
|
||||
private val withUnits: Units
|
||||
|
||||
enum class Units {
|
||||
SKIP, USE
|
||||
}
|
||||
|
||||
fun minimise(maxSize: Int): String {
|
||||
val originalSeparator = separator
|
||||
if ("0$fractional".toInt() == 0) {
|
||||
separator = ""
|
||||
fractional = ""
|
||||
}
|
||||
if ("0$decimal".toInt() == 0 && fractional.isNotEmpty()) {
|
||||
decimal = ""
|
||||
}
|
||||
if (currentLen() <= maxSize) return toString()
|
||||
if (sign == "+") {
|
||||
sign = ""
|
||||
}
|
||||
if (currentLen() <= maxSize) {
|
||||
return toString()
|
||||
}
|
||||
while (fractional.length > 1 && fractional[fractional.length - 1] == '0') {
|
||||
fractional = fractional.substring(0, fractional.length - 1)
|
||||
}
|
||||
if (currentLen() <= maxSize) {
|
||||
return toString()
|
||||
}
|
||||
if (fractional.isNotEmpty()) {
|
||||
val remainingForFraction = maxSize - currentLen() + fractional.length
|
||||
var formatCandidate = "#"
|
||||
if (remainingForFraction >= 1) {
|
||||
formatCandidate = "#." + "#######".substring(0, remainingForFraction)
|
||||
}
|
||||
val df = DecimalFormat(formatCandidate)
|
||||
df.roundingMode = RoundingMode.HALF_UP
|
||||
val decimalSup = decimal.ifEmpty { "0" }
|
||||
val result = sign + df.format("$decimalSup.$fractional".toDouble()).replace(",", originalSeparator).replace(".", originalSeparator) +
|
||||
if (withUnits == Units.USE) units else ""
|
||||
return if (decimal.isNotEmpty()) result else result.substring(1)
|
||||
}
|
||||
return toString()
|
||||
}
|
||||
|
||||
private fun currentLen(): Int {
|
||||
return sign.length + decimal.length + separator.length + fractional.length +
|
||||
if (withUnits == Units.USE) units.length else 0
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return sign + decimal + separator + fractional +
|
||||
if (withUnits == Units.USE) units else ""
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private val pattern = Pattern.compile("^([+-]?)([0-9]*)([,.]?)([0-9]*)(\\([^)]*\\))?(.*?)$", Pattern.CASE_INSENSITIVE or Pattern.UNICODE_CASE)
|
||||
}
|
||||
|
||||
init {
|
||||
val matcher = pattern.matcher(inputString)
|
||||
matcher.matches()
|
||||
sign = matcher.group(1) ?: ""
|
||||
decimal = matcher.group(2) ?: ""
|
||||
separator = matcher.group(3) ?: ""
|
||||
fractional = matcher.group(4) ?: ""
|
||||
units = matcher.group(6) ?: ""
|
||||
if (fractional.isEmpty()) {
|
||||
separator = ""
|
||||
fractional = ""
|
||||
}
|
||||
val extraCandidate = matcher.group(5) ?: ""
|
||||
if (extraCandidate.length > 2) {
|
||||
extra = extraCandidate.substring(1, extraCandidate.length - 1)
|
||||
}
|
||||
units = units.trim()
|
||||
|
||||
this.withUnits = withUnits
|
||||
}
|
||||
}
|
|
@ -1,9 +1,7 @@
|
|||
package info.nightscout.androidaps.interaction.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.os.PowerManager
|
||||
import com.google.android.gms.wearable.DataMap
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import info.nightscout.shared.logging.LTag
|
||||
import javax.inject.Inject
|
||||
|
@ -72,4 +70,4 @@ class WearUtil @Inject constructor() {
|
|||
// we simply ignore if sleep was interrupted
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package info.nightscout.androidaps.tile
|
||||
|
||||
import dagger.android.AndroidInjection
|
||||
import info.nightscout.androidaps.tile.source.ActionSource
|
||||
import javax.inject.Inject
|
||||
|
||||
class ActionsTileService : TileBase() {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package info.nightscout.androidaps.tile
|
||||
|
||||
import dagger.android.AndroidInjection
|
||||
import info.nightscout.androidaps.tile.source.QuickWizardSource
|
||||
import javax.inject.Inject
|
||||
|
||||
class QuickWizardTileService : TileBase() {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package info.nightscout.androidaps.tile
|
||||
|
||||
import dagger.android.AndroidInjection
|
||||
import info.nightscout.androidaps.tile.source.TempTargetSource
|
||||
import javax.inject.Inject
|
||||
|
||||
class TempTargetTileService : TileBase() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package info.nightscout.androidaps.tile
|
||||
package info.nightscout.androidaps.tile.source
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
|
@ -1,9 +1,11 @@
|
|||
package info.nightscout.androidaps.tile
|
||||
package info.nightscout.androidaps.tile.source
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.interaction.actions.BackgroundActionActivity
|
||||
import info.nightscout.androidaps.tile.Action
|
||||
import info.nightscout.androidaps.tile.TileSource
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import info.nightscout.shared.logging.LTag
|
||||
import info.nightscout.shared.sharedPreferences.SP
|
|
@ -1,9 +1,10 @@
|
|||
package info.nightscout.androidaps.tile
|
||||
package info.nightscout.androidaps.tile.source
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.content.res.Resources
|
||||
import androidx.annotation.DrawableRes
|
||||
import info.nightscout.androidaps.tile.Action
|
||||
import info.nightscout.androidaps.tile.TileSource
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import info.nightscout.shared.sharedPreferences.SP
|
||||
import info.nightscout.shared.weardata.EventData
|
|
@ -1,4 +1,4 @@
|
|||
package info.nightscout.androidaps.tile
|
||||
package info.nightscout.androidaps.tile.source
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
|
@ -66,7 +66,6 @@ abstract class BaseWatchFace : WatchFace() {
|
|||
@Inject lateinit var dateUtil: DateUtil
|
||||
|
||||
private var disposable = CompositeDisposable()
|
||||
|
||||
private val rawData = RawDisplayData()
|
||||
|
||||
protected val singleBg get() = rawData.singleBg
|
||||
|
@ -96,11 +95,11 @@ abstract class BaseWatchFace : WatchFace() {
|
|||
var mCOB2: TextView? = null
|
||||
var mBgi: TextView? = null
|
||||
var mLoop: TextView? = null
|
||||
var mTimePeriod: TextView? = null
|
||||
private var mTimePeriod: TextView? = null
|
||||
var mDay: TextView? = null
|
||||
var mDayName: TextView? = null
|
||||
private var mDayName: TextView? = null
|
||||
var mMonth: TextView? = null
|
||||
var isAAPSv2: View? = null
|
||||
private var isAAPSv2: View? = null
|
||||
var mHighLight: TextView? = null
|
||||
var mLowLight: TextView? = null
|
||||
var mGlucoseDial: ImageView? = null
|
||||
|
@ -110,9 +109,9 @@ abstract class BaseWatchFace : WatchFace() {
|
|||
var mRelativeLayout: ViewGroup? = null
|
||||
var mLinearLayout: LinearLayout? = null
|
||||
var mLinearLayout2: LinearLayout? = null
|
||||
var mDate: LinearLayout? = null
|
||||
var mChartTap: LinearLayout? = null // Steampunk only
|
||||
var mMainMenuTap: LinearLayout? = null // Steampunk,Digital only
|
||||
private var mDate: LinearLayout? = null
|
||||
private var mChartTap: LinearLayout? = null // Steampunk only
|
||||
private var mMainMenuTap: LinearLayout? = null // Steampunk,Digital only
|
||||
var chart: LineChartView? = null
|
||||
|
||||
var ageLevel = 1
|
||||
|
@ -123,7 +122,7 @@ abstract class BaseWatchFace : WatchFace() {
|
|||
var gridColor = Color.WHITE
|
||||
var basalBackgroundColor = Color.BLUE
|
||||
var basalCenterColor = Color.BLUE
|
||||
var bolusColor = Color.MAGENTA
|
||||
private var bolusColor = Color.MAGENTA
|
||||
private var lowResMode = false
|
||||
private var layoutSet = false
|
||||
var bIsRound = false
|
||||
|
@ -137,8 +136,8 @@ abstract class BaseWatchFace : WatchFace() {
|
|||
|
||||
// related endTime manual layout
|
||||
var layoutView: View? = null
|
||||
var specW = 0
|
||||
var specH = 0
|
||||
private var specW = 0
|
||||
private var specH = 0
|
||||
var forceSquareCanvas = false // Set to true by the Steampunk watch face.
|
||||
private var batteryReceiver: BroadcastReceiver? = null
|
||||
private var colorDarkHigh = 0
|
||||
|
@ -338,7 +337,7 @@ abstract class BaseWatchFace : WatchFace() {
|
|||
return (System.currentTimeMillis() - singleBg.timeStamp).toDouble()
|
||||
}
|
||||
|
||||
protected fun readingAge(shortString: Boolean): String {
|
||||
private fun readingAge(shortString: Boolean): String {
|
||||
if (singleBg.timeStamp == 0L) {
|
||||
return if (shortString) "--" else "-- Minute ago"
|
||||
}
|
||||
|
@ -491,7 +490,7 @@ abstract class BaseWatchFace : WatchFace() {
|
|||
invalidate()
|
||||
}
|
||||
|
||||
protected fun setDateAndTime() {
|
||||
private fun setDateAndTime() {
|
||||
mTime?.text = dateUtil.timeString()
|
||||
mHour?.text = dateUtil.hourString()
|
||||
mMinute?.text = dateUtil.minuteString()
|
||||
|
@ -512,7 +511,7 @@ abstract class BaseWatchFace : WatchFace() {
|
|||
}
|
||||
}
|
||||
|
||||
protected fun strikeThroughSgvIfNeeded() {
|
||||
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()
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
package info.nightscout.androidaps.watchfaces
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import androidx.annotation.LayoutRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.ustwo.clockwise.common.WatchMode
|
||||
|
@ -13,6 +14,7 @@ class BigChartWatchface : BaseWatchFace() {
|
|||
if (resources.displayMetrics.widthPixels < SCREEN_SIZE_SMALL || resources.displayMetrics.heightPixels < SCREEN_SIZE_SMALL) R.layout.activity_bigchart_small
|
||||
else R.layout.activity_bigchart
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun setDataFields() {
|
||||
super.setDataFields()
|
||||
mStatus?.text = status.externalStatus + if (sp.getBoolean(R.string.key_show_cob, true)) (" " + this.status.cob) else ""
|
||||
|
@ -118,4 +120,4 @@ class BigChartWatchface : BaseWatchFace() {
|
|||
setColorDark()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -197,7 +197,7 @@ class CircleWatchface : WatchFace() {
|
|||
myLayout?.layout(0, 0, myLayout?.measuredWidth ?: 0, myLayout?.measuredHeight ?: 0)
|
||||
}
|
||||
|
||||
val minutes: String
|
||||
private val minutes: String
|
||||
get() {
|
||||
var minutes = "--'"
|
||||
if (singleBg.timeStamp != 0L) {
|
||||
|
@ -421,4 +421,4 @@ class CircleWatchface : WatchFace() {
|
|||
override fun getWatchFaceStyle(): WatchFaceStyle {
|
||||
return WatchFaceStyle.Builder(this).setAcceptsTapEvents(true).build()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,33 +1,32 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<ListPreference
|
||||
android:key="tile_action_1"
|
||||
android:title="Action 1"
|
||||
android:defaultValue="wizard"
|
||||
android:entries="@array/tile_action_names"
|
||||
android:entryValues="@array/tile_action_values"/>
|
||||
android:entryValues="@array/tile_action_values"
|
||||
android:key="tile_action_1"
|
||||
android:title="Action 1" />
|
||||
|
||||
<ListPreference
|
||||
android:key="tile_action_2"
|
||||
android:title="Action 2"
|
||||
android:defaultValue="treatment"
|
||||
android:entries="@array/tile_action_names"
|
||||
android:entryValues="@array/tile_action_values"/>
|
||||
android:entryValues="@array/tile_action_values"
|
||||
android:key="tile_action_2"
|
||||
android:title="Action 2" />
|
||||
|
||||
<ListPreference
|
||||
android:key="tile_action_3"
|
||||
android:title="Action 3"
|
||||
android:defaultValue="carbs"
|
||||
android:entries="@array/tile_action_names"
|
||||
android:entryValues="@array/tile_action_values"/>
|
||||
android:entryValues="@array/tile_action_values"
|
||||
android:key="tile_action_3"
|
||||
android:title="Action 3" />
|
||||
|
||||
<ListPreference
|
||||
android:key="tile_action_4"
|
||||
android:title="Action 4"
|
||||
android:defaultValue="temp_target"
|
||||
android:entries="@array/tile_action_names"
|
||||
android:entryValues="@array/tile_action_values"/>
|
||||
android:entryValues="@array/tile_action_values"
|
||||
android:key="tile_action_4"
|
||||
android:title="Action 4" />
|
||||
|
||||
</PreferenceScreen>
|
||||
|
|
|
@ -1,33 +1,32 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<ListPreference
|
||||
android:key="tile_tempt_1"
|
||||
android:title="Target 1"
|
||||
android:defaultValue="activity"
|
||||
android:entries="@array/tile_tempt_names"
|
||||
android:entryValues="@array/tile_tempt_values"/>
|
||||
android:entryValues="@array/tile_tempt_values"
|
||||
android:key="tile_tempt_1"
|
||||
android:title="Target 1" />
|
||||
|
||||
<ListPreference
|
||||
android:key="tile_tempt_2"
|
||||
android:title="Target 2"
|
||||
android:defaultValue="eating_soon"
|
||||
android:entries="@array/tile_tempt_names"
|
||||
android:entryValues="@array/tile_tempt_values"/>
|
||||
android:entryValues="@array/tile_tempt_values"
|
||||
android:key="tile_tempt_2"
|
||||
android:title="Target 2" />
|
||||
|
||||
<ListPreference
|
||||
android:key="tile_tempt_3"
|
||||
android:title="Target 3"
|
||||
android:defaultValue="hypo"
|
||||
android:entries="@array/tile_tempt_names"
|
||||
android:entryValues="@array/tile_tempt_values"/>
|
||||
android:entryValues="@array/tile_tempt_values"
|
||||
android:key="tile_tempt_3"
|
||||
android:title="Target 3" />
|
||||
|
||||
<ListPreference
|
||||
android:key="tile_tempt_4"
|
||||
android:title="Target 4"
|
||||
android:defaultValue="manual"
|
||||
android:entries="@array/tile_tempt_names"
|
||||
android:entryValues="@array/tile_tempt_values"/>
|
||||
android:entryValues="@array/tile_tempt_values"
|
||||
android:key="tile_tempt_4"
|
||||
android:title="Target 4" />
|
||||
|
||||
</PreferenceScreen>
|
||||
|
|
Loading…
Reference in a new issue