import Toybox.Graphics; import Toybox.Lang; import Toybox.Math; import Toybox.System; import Toybox.WatchUi; class KittieCatsView extends WatchUi.WatchFace { private var theme; private var backgroundHi; private var backgroundLo; private var armHour; private var armMinute; private var armSecond; private var icons; private var iconSize; private var sleepTime; private var wakeTime; private var sleeping = false; function initialize() { WatchFace.initialize(); } function onLayout(dc as Dc) as Void { } function onShow() as Void { self.theme = ThemeManager.getInstance().getCurrentTheme(); self.backgroundHi = Application.loadResource(self.theme.BackgroundHi); self.backgroundLo = Application.loadResource(self.theme.BackgroundLo); self.armHour = Application.loadResource(self.theme.ArmHour); self.armMinute = Application.loadResource(self.theme.ArmMinute); self.armSecond = Application.loadResource(self.theme.ArmSecond); self.icons = Application.loadResource(Rez.Drawables.Icons); self.iconSize = self.icons.getHeight(); var profile = UserProfile.getProfile(); self.sleepTime = profile.sleepTime; self.wakeTime = profile.wakeTime; } function onHide() as Void { self.backgroundHi = null; self.backgroundLo = null; self.armHour = null; self.armMinute = null; self.armSecond = null; self.icons = null; } function onUpdate(dc as Dc) as Void { var highPowerMode = self.isHighPowerMode(); var clockTime = System.getClockTime(); var complications = ComplicationSubscriber.getSnapshot(); dc.setColor(Graphics.COLOR_BLACK, Graphics.COLOR_BLACK); dc.clear(); dc.setAntiAlias(true); dc.drawBitmap(0, 0, highPowerMode ? self.backgroundHi : self.backgroundLo); if (highPowerMode) { // --- Icons --- self.drawIcon(dc, 0, 104, 145); self.drawIcon(dc, 1, 170, 300); self.drawIcon(dc, 2, 170, 335); self.drawIcon(dc, 3, 237, 335); } // --- Arms --- // Base the hour arm on minutes as well, to prevent the arm from staying on the // current hour tick mark right up until the 59th minute self.drawArm(dc, self.armHour, (clockTime.hour * 60) + clockTime.min, 720, highPowerMode ? self.theme.ArmHourTintHi : self.theme.ArmHourTintLo); self.drawArm(dc, self.armMinute, clockTime.min, 60, highPowerMode ? self.theme.ArmMinuteTintHi : self.theme.ArmMinuteTintLo); if (highPowerMode) { self.drawArm(dc, self.armSecond, clockTime.sec, 60, null); // --- Complications --- self.drawShadowedText(dc, 116, 186, Graphics.FONT_XTINY, complications.HeartRate, Graphics.TEXT_JUSTIFY_CENTER | Graphics.TEXT_JUSTIFY_VCENTER, Graphics.COLOR_BLACK, Graphics.COLOR_WHITE, 2); self.drawShadowedText(dc, 195, 313, Graphics.FONT_XTINY, complications.Steps, Graphics.TEXT_JUSTIFY_LEFT | Graphics.TEXT_JUSTIFY_VCENTER, Graphics.COLOR_BLACK, Graphics.COLOR_WHITE, 2); self.drawShadowedText(dc, 195, 346, Graphics.FONT_XTINY, complications.BodyBattery, Graphics.TEXT_JUSTIFY_LEFT | Graphics.TEXT_JUSTIFY_VCENTER, Graphics.COLOR_BLACK, Graphics.COLOR_WHITE, 2); self.drawShadowedText(dc, 261, 346, Graphics.FONT_XTINY, complications.Stress, Graphics.TEXT_JUSTIFY_LEFT | Graphics.TEXT_JUSTIFY_VCENTER, Graphics.COLOR_BLACK, Graphics.COLOR_WHITE, 2); } } function onExitSleep() as Void { self.sleeping = false; } function onEnterSleep() as Void { self.sleeping = true; } private function isHighPowerMode() as Boolean { if (self.sleeping) { return false; } // Since isSleepMode is deprecated, base it on the wake and sleep times. Unfortunately this means // the display will never be in high power mode between those times even if desired. // Can't figure out how to check for the locked state either. // Might want to check for DND mode instead if this is annoying. var now = Time.now(); var today = Time.today(); if (now.greaterThan(today.add(self.sleepTime)) && now.lessThan(today.add(self.wakeTime))) { return false; } return true; } private function drawArm(dc as Dc, bitmap as BitmapType, value as Lang.Numeric, max as Lang.Numeric, tintColor as Lang.Numeric or Null) as Void { var offsetX = Math.floor(bitmap.getWidth() / 2); var offsetY = Math.floor(bitmap.getWidth() / 2); var rotation = new Graphics.AffineTransform(); rotation.translate(offsetX, offsetY); rotation.rotate(((Math.PI * 2) / max) * value); rotation.translate(-offsetX, -offsetY); // NOTE: drawBitmap2 fails on the Forerunner 165 with an error "Source must be native color format" dc.drawBitmap2(0, 0, bitmap, { :tintColor => tintColor, :filterMode => Graphics.FILTER_MODE_BILINEAR, :transform => rotation }); } private function drawShadowedText(dc as Dc, x as Lang.Numeric, y as Lang.Numeric, font as Graphics.FontType, text as Lang.Object or Null, justification as Graphics.TextJustification or Lang.Number, textColor as Graphics.ColorType, shadowColor as Graphics.ColorType, shadowOffset as Lang.Numeric) as Void { dc.setColor(shadowColor, Graphics.COLOR_TRANSPARENT); dc.drawText(x + shadowOffset, y + shadowOffset, font, text, justification); dc.setColor(textColor, Graphics.COLOR_TRANSPARENT); dc.drawText(x, y, font, text, justification); } private function drawIcon(dc as Dc, iconIndex as Lang.Numeric, x as Lang.Numeric, y as Lang.Numeric) { dc.drawBitmap2(x - (iconIndex * self.iconSize), y, self.icons, { :bitmapX => iconIndex * self.iconSize, :bitmapWidth => self.iconSize, :bitmapHeight => self.iconSize }); } }