feat: draw full padel screen (score, court, HR, time)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,33 +1,129 @@
|
||||
import Toybox.Lang;
|
||||
import Toybox.Graphics;
|
||||
import Toybox.WatchUi;
|
||||
import Toybox.System;
|
||||
import Toybox.Timer;
|
||||
|
||||
class garmin_padelView extends WatchUi.View {
|
||||
private const ACCENT = 0x00E0A0; // padel green (sets/games)
|
||||
private const LABEL_COLOR = 0x808080; // muted grey (S/G/pts labels)
|
||||
|
||||
function initialize() {
|
||||
private var _court as CourtRenderer;
|
||||
private var _timer as Timer.Timer;
|
||||
|
||||
public function initialize() {
|
||||
View.initialize();
|
||||
_court = new CourtRenderer();
|
||||
_timer = new Timer.Timer();
|
||||
}
|
||||
|
||||
// Load your resources here
|
||||
function onLayout(dc as Dc) as Void {
|
||||
setLayout(Rez.Layouts.MainLayout(dc));
|
||||
public function onShow() as Void {
|
||||
_timer.start(method(:onTick), 1000, true); // refresh clock + HR every second
|
||||
}
|
||||
|
||||
// Called when this View is brought to the foreground. Restore
|
||||
// the state of this View and prepare it to be shown. This includes
|
||||
// loading resources into memory.
|
||||
function onShow() as Void {
|
||||
public function onHide() as Void {
|
||||
_timer.stop();
|
||||
}
|
||||
|
||||
// Update the view
|
||||
function onUpdate(dc as Dc) as Void {
|
||||
// Call the parent onUpdate function to redraw the layout
|
||||
View.onUpdate(dc);
|
||||
public function onTick() as Void {
|
||||
WatchUi.requestUpdate();
|
||||
}
|
||||
|
||||
// Called when this View is removed from the screen. Save the
|
||||
// state of this View here. This includes freeing resources from
|
||||
// memory.
|
||||
function onHide() as Void {
|
||||
public function onUpdate(dc as Graphics.Dc) as Void {
|
||||
var m = getApp().getMatch();
|
||||
var w = dc.getWidth();
|
||||
var h = dc.getHeight();
|
||||
var cx = w / 2;
|
||||
var cy = h / 2;
|
||||
|
||||
dc.setColor(Graphics.COLOR_WHITE, Graphics.COLOR_BLACK);
|
||||
dc.clear();
|
||||
|
||||
_court.draw(dc, cx, cy, m.servingQuadrant(), !m.isMatchOver());
|
||||
_drawLeftColumn(dc, m);
|
||||
_drawRightColumn(dc, m, w);
|
||||
_drawHeartRate(dc, cx, 40);
|
||||
_drawTime(dc, cx, h - 44);
|
||||
|
||||
if (m.isMatchOver()) {
|
||||
_drawWinner(dc, cx, cy, m);
|
||||
}
|
||||
}
|
||||
|
||||
// Left: S and G mini-columns, your team on top, opponents below.
|
||||
private function _drawLeftColumn(dc as Graphics.Dc, m as PadelMatch) as Void {
|
||||
var sX = 24;
|
||||
var gX = 60;
|
||||
var labelY = 150;
|
||||
var usY = 178;
|
||||
var themY = 206;
|
||||
|
||||
dc.setColor(LABEL_COLOR, Graphics.COLOR_TRANSPARENT);
|
||||
dc.drawText(sX, labelY, Graphics.FONT_XTINY, "S", Graphics.TEXT_JUSTIFY_CENTER);
|
||||
dc.drawText(gX, labelY, Graphics.FONT_XTINY, "G", Graphics.TEXT_JUSTIFY_CENTER);
|
||||
|
||||
dc.setColor(ACCENT, Graphics.COLOR_TRANSPARENT);
|
||||
dc.drawText(sX, usY, Graphics.FONT_TINY, m.sets(US).toString(), Graphics.TEXT_JUSTIFY_CENTER);
|
||||
dc.drawText(sX, themY, Graphics.FONT_TINY, m.sets(THEM).toString(), Graphics.TEXT_JUSTIFY_CENTER);
|
||||
dc.drawText(gX, usY, Graphics.FONT_TINY, m.games(US).toString(), Graphics.TEXT_JUSTIFY_CENTER);
|
||||
dc.drawText(gX, themY, Graphics.FONT_TINY, m.games(THEM).toString(), Graphics.TEXT_JUSTIFY_CENTER);
|
||||
}
|
||||
|
||||
// Right: pts column, your team on top, opponents below.
|
||||
private function _drawRightColumn(dc as Graphics.Dc, m as PadelMatch, w as Number) as Void {
|
||||
var pX = w - 42;
|
||||
var labelY = 150;
|
||||
var usY = 178;
|
||||
var themY = 206;
|
||||
|
||||
dc.setColor(LABEL_COLOR, Graphics.COLOR_TRANSPARENT);
|
||||
dc.drawText(pX, labelY, Graphics.FONT_XTINY, "pts", Graphics.TEXT_JUSTIFY_CENTER);
|
||||
|
||||
dc.setColor(Graphics.COLOR_WHITE, Graphics.COLOR_TRANSPARENT);
|
||||
dc.drawText(pX, usY, Graphics.FONT_TINY, m.pointLabel(US), Graphics.TEXT_JUSTIFY_CENTER);
|
||||
dc.drawText(pX, themY, Graphics.FONT_TINY, m.pointLabel(THEM), Graphics.TEXT_JUSTIFY_CENTER);
|
||||
}
|
||||
|
||||
private function _drawHeartRate(dc as Graphics.Dc, cx as Number, y as Number) as Void {
|
||||
var hr = getApp().getHeartRate();
|
||||
var bpm = hr.getHeartRate();
|
||||
var text = (bpm == null) ? "-- bpm" : bpm.toString() + " bpm";
|
||||
dc.setColor(Graphics.COLOR_RED, Graphics.COLOR_TRANSPARENT);
|
||||
dc.drawText(cx, y, Graphics.FONT_TINY, text, Graphics.TEXT_JUSTIFY_CENTER);
|
||||
_drawZoneBar(dc, cx, y + 26, hr.getZone());
|
||||
}
|
||||
|
||||
// 5-segment bar; segments up to the current zone are filled.
|
||||
private function _drawZoneBar(dc as Graphics.Dc, cx as Number, y as Number, zone as Number) as Void {
|
||||
var segW = 12;
|
||||
var segH = 6;
|
||||
var gap = 3;
|
||||
var totalW = 5 * segW + 4 * gap;
|
||||
var x = cx - totalW / 2;
|
||||
for (var i = 1; i <= 5; i += 1) {
|
||||
if (i <= zone) {
|
||||
dc.setColor(ACCENT, Graphics.COLOR_TRANSPARENT);
|
||||
dc.fillRectangle(x, y, segW, segH);
|
||||
} else {
|
||||
dc.setColor(LABEL_COLOR, Graphics.COLOR_TRANSPARENT);
|
||||
dc.drawRectangle(x, y, segW, segH);
|
||||
}
|
||||
x += segW + gap;
|
||||
}
|
||||
}
|
||||
|
||||
private function _drawTime(dc as Graphics.Dc, cx as Number, y as Number) as Void {
|
||||
var now = System.getClockTime();
|
||||
var text = now.hour.format("%02d") + ":" + now.min.format("%02d");
|
||||
dc.setColor(Graphics.COLOR_WHITE, Graphics.COLOR_TRANSPARENT);
|
||||
dc.drawText(cx, y, Graphics.FONT_SMALL, text, Graphics.TEXT_JUSTIFY_CENTER);
|
||||
}
|
||||
|
||||
private function _drawWinner(dc as Graphics.Dc, cx as Number, cy as Number, m as PadelMatch) as Void {
|
||||
var text = (m.winner() == US) ? "You win!" : "They win";
|
||||
dc.setColor(ACCENT, Graphics.COLOR_BLACK);
|
||||
dc.fillRectangle(cx - 70, cy - 18, 140, 36);
|
||||
dc.setColor(Graphics.COLOR_BLACK, Graphics.COLOR_TRANSPARENT);
|
||||
dc.drawText(cx, cy - 14, Graphics.FONT_SMALL, text, Graphics.TEXT_JUSTIFY_CENTER);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user