UI improvements: bordered feedback, centered titles, cloud animation, Tesla margins
This commit is contained in:
62
matrix.py
62
matrix.py
@@ -225,9 +225,16 @@ class Matrix64Display(SampleBase):
|
|||||||
time_font, data_font, small_font = fonts
|
time_font, data_font, small_font = fonts
|
||||||
time_color, humidity_color, hdd_color, label_color, line_color = colors
|
time_color, humidity_color, hdd_color, label_color, line_color = colors
|
||||||
|
|
||||||
for y in range(24, 44):
|
# Black background
|
||||||
|
for y in range(22, 46):
|
||||||
graphics.DrawLine(canvas, 0, y, 63, y, graphics.Color(0, 0, 0))
|
graphics.DrawLine(canvas, 0, y, 63, y, graphics.Color(0, 0, 0))
|
||||||
|
|
||||||
|
# Border lines
|
||||||
|
border_color = graphics.Color(60, 60, 60)
|
||||||
|
graphics.DrawLine(canvas, 0, 22, 63, 22, border_color)
|
||||||
|
graphics.DrawLine(canvas, 0, 45, 63, 45, border_color)
|
||||||
|
|
||||||
|
# Message
|
||||||
msg_color = graphics.Color(0, 255, 100)
|
msg_color = graphics.Color(0, 255, 100)
|
||||||
msg_len = len(self.feedback_message) * 7
|
msg_len = len(self.feedback_message) * 7
|
||||||
x = (64 - msg_len) // 2
|
x = (64 - msg_len) // 2
|
||||||
@@ -241,8 +248,9 @@ class Matrix64Display(SampleBase):
|
|||||||
now = datetime.datetime.now()
|
now = datetime.datetime.now()
|
||||||
time_str = f"{now.hour:02d}:{now.minute:02d}:{now.second:02d}"
|
time_str = f"{now.hour:02d}:{now.minute:02d}:{now.second:02d}"
|
||||||
|
|
||||||
anim_offset = int(math.sin(self.animation_frame * 0.3) * 2)
|
# Weather Icon (cloud moves, sun/icon stays fixed)
|
||||||
draw_weather_icon(canvas, anim_offset, 0, self.weather_desc)
|
cloud_offset = int(math.sin(self.animation_frame * 0.3) * 2)
|
||||||
|
draw_weather_icon(canvas, 0, 0, self.weather_desc, cloud_offset)
|
||||||
|
|
||||||
graphics.DrawLine(canvas, 28, 0, 28, 25, line_color)
|
graphics.DrawLine(canvas, 28, 0, 28, 25, line_color)
|
||||||
|
|
||||||
@@ -279,25 +287,29 @@ class Matrix64Display(SampleBase):
|
|||||||
time_font, data_font, small_font = fonts
|
time_font, data_font, small_font = fonts
|
||||||
time_color, humidity_color, hdd_color, label_color, line_color = colors
|
time_color, humidity_color, hdd_color, label_color, line_color = colors
|
||||||
|
|
||||||
graphics.DrawText(canvas, data_font, 4, 8, time_color, "Discos")
|
# Centered title
|
||||||
|
title = "Discos"
|
||||||
|
title_len = len(title) * 5
|
||||||
|
title_x = (64 - title_len) // 2
|
||||||
|
graphics.DrawText(canvas, data_font, title_x, 8, time_color, title)
|
||||||
graphics.DrawLine(canvas, 0, 10, 63, 10, line_color)
|
graphics.DrawLine(canvas, 0, 10, 63, 10, line_color)
|
||||||
|
|
||||||
if self.hdd_temps and len(self.hdd_temps) > 1:
|
if self.hdd_temps and len(self.hdd_temps) > 1:
|
||||||
temps = [(i+1, int(t[0])) for i, t in enumerate(self.hdd_temps[1:7]) if t]
|
temps = [(i+1, int(t[0])) for i, t in enumerate(self.hdd_temps[1:7]) if t]
|
||||||
|
|
||||||
y = 20
|
y = 22
|
||||||
for idx, (num, temp_val) in enumerate(temps[:3]):
|
for idx, (num, temp_val) in enumerate(temps[:3]):
|
||||||
temp_color = get_hdd_color(temp_val)
|
temp_color = get_hdd_color(temp_val)
|
||||||
graphics.DrawText(canvas, data_font, 0, y, label_color, f"{num}:")
|
graphics.DrawText(canvas, data_font, 2, y, label_color, f"{num}:")
|
||||||
graphics.DrawText(canvas, data_font, 14, y, temp_color, f"{temp_val}C")
|
graphics.DrawText(canvas, data_font, 16, y, temp_color, f"{temp_val}C")
|
||||||
y += 10
|
y += 11
|
||||||
|
|
||||||
y = 20
|
y = 22
|
||||||
for idx, (num, temp_val) in enumerate(temps[3:6]):
|
for idx, (num, temp_val) in enumerate(temps[3:6]):
|
||||||
temp_color = get_hdd_color(temp_val)
|
temp_color = get_hdd_color(temp_val)
|
||||||
graphics.DrawText(canvas, data_font, 34, y, label_color, f"{num}:")
|
graphics.DrawText(canvas, data_font, 34, y, label_color, f"{num}:")
|
||||||
graphics.DrawText(canvas, data_font, 48, y, temp_color, f"{temp_val}C")
|
graphics.DrawText(canvas, data_font, 48, y, temp_color, f"{temp_val}C")
|
||||||
y += 10
|
y += 11
|
||||||
|
|
||||||
if self.auto_cycle:
|
if self.auto_cycle:
|
||||||
graphics.DrawText(canvas, small_font, 58, 62, label_color, "A")
|
graphics.DrawText(canvas, small_font, 58, 62, label_color, "A")
|
||||||
@@ -323,8 +335,9 @@ class Matrix64Display(SampleBase):
|
|||||||
|
|
||||||
graphics.DrawLine(canvas, 0, 30, 63, 30, line_color)
|
graphics.DrawLine(canvas, 0, 30, 63, 30, line_color)
|
||||||
|
|
||||||
anim_offset = int(math.sin(self.animation_frame * 0.3) * 2)
|
# Weather icon (cloud animates, position fixed)
|
||||||
draw_weather_icon(canvas, 4 + anim_offset, 34, self.weather_desc)
|
cloud_offset = int(math.sin(self.animation_frame * 0.3) * 2)
|
||||||
|
draw_weather_icon(canvas, 4, 34, self.weather_desc, cloud_offset)
|
||||||
|
|
||||||
if self.temperature is not None:
|
if self.temperature is not None:
|
||||||
temp_color = get_temperature_color(self.temperature)
|
temp_color = get_temperature_color(self.temperature)
|
||||||
@@ -338,25 +351,28 @@ class Matrix64Display(SampleBase):
|
|||||||
time_font, data_font, small_font = fonts
|
time_font, data_font, small_font = fonts
|
||||||
time_color, humidity_color, hdd_color, label_color, line_color = colors
|
time_color, humidity_color, hdd_color, label_color, line_color = colors
|
||||||
|
|
||||||
# Title
|
# Centered title
|
||||||
graphics.DrawText(canvas, data_font, 14, 8, time_color, "Tesla")
|
title = "Tesla"
|
||||||
|
title_len = len(title) * 5
|
||||||
|
title_x = (64 - title_len) // 2
|
||||||
|
graphics.DrawText(canvas, data_font, title_x, 8, time_color, title)
|
||||||
graphics.DrawLine(canvas, 0, 10, 63, 10, line_color)
|
graphics.DrawLine(canvas, 0, 10, 63, 10, line_color)
|
||||||
|
|
||||||
if self.tesla:
|
if self.tesla:
|
||||||
# Battery
|
# Battery (with margin)
|
||||||
battery = self.tesla.get("battery")
|
battery = self.tesla.get("battery")
|
||||||
if battery is not None:
|
if battery is not None:
|
||||||
battery_color = graphics.Color(0, 255, 80) if battery > 20 else graphics.Color(255, 50, 50)
|
battery_color = graphics.Color(0, 255, 80) if battery > 20 else graphics.Color(255, 50, 50)
|
||||||
graphics.DrawText(canvas, data_font, 0, 22, label_color, "Bat:")
|
graphics.DrawText(canvas, data_font, 4, 24, label_color, "Bat")
|
||||||
graphics.DrawText(canvas, time_font, 24, 24, battery_color, f"{battery}%")
|
graphics.DrawText(canvas, time_font, 26, 26, battery_color, f"{battery}%")
|
||||||
|
|
||||||
# Range
|
# Range (with margin)
|
||||||
range_km = self.tesla.get("range")
|
range_km = self.tesla.get("range")
|
||||||
if range_km is not None:
|
if range_km is not None:
|
||||||
graphics.DrawText(canvas, data_font, 0, 36, label_color, "Km:")
|
graphics.DrawText(canvas, data_font, 4, 38, label_color, "Km")
|
||||||
graphics.DrawText(canvas, time_font, 20, 38, time_color, f"{range_km}")
|
graphics.DrawText(canvas, time_font, 22, 40, time_color, f"{range_km}")
|
||||||
|
|
||||||
# Status
|
# Status (centered)
|
||||||
charging = self.tesla.get("charging", False)
|
charging = self.tesla.get("charging", False)
|
||||||
plugged = self.tesla.get("plugged", False)
|
plugged = self.tesla.get("plugged", False)
|
||||||
|
|
||||||
@@ -370,7 +386,9 @@ class Matrix64Display(SampleBase):
|
|||||||
status = "Listo"
|
status = "Listo"
|
||||||
status_color = graphics.Color(100, 100, 100)
|
status_color = graphics.Color(100, 100, 100)
|
||||||
|
|
||||||
graphics.DrawText(canvas, data_font, 4, 54, status_color, status)
|
status_len = len(status) * 5
|
||||||
|
status_x = (64 - status_len) // 2
|
||||||
|
graphics.DrawText(canvas, data_font, status_x, 56, status_color, status)
|
||||||
else:
|
else:
|
||||||
graphics.DrawText(canvas, data_font, 4, 32, label_color, "Sin datos")
|
graphics.DrawText(canvas, data_font, 4, 32, label_color, "Sin datos")
|
||||||
|
|
||||||
|
|||||||
@@ -54,31 +54,31 @@ def _draw_cloud_shape(canvas, x, y, color):
|
|||||||
graphics.DrawCircle(canvas, x + 12, y + 7, r, color)
|
graphics.DrawCircle(canvas, x + 12, y + 7, r, color)
|
||||||
|
|
||||||
|
|
||||||
def draw_partly_cloudy(canvas, x, y):
|
def draw_partly_cloudy(canvas, x, y, cloud_offset=0):
|
||||||
"""Draw sun partially covered by cloud."""
|
"""Draw sun partially covered by cloud. Cloud can be animated."""
|
||||||
sun_color = graphics.Color(255, 200, 0)
|
sun_color = graphics.Color(255, 200, 0)
|
||||||
ray_color = graphics.Color(255, 140, 0)
|
ray_color = graphics.Color(255, 140, 0)
|
||||||
cloud_color = graphics.Color(220, 220, 220)
|
cloud_color = graphics.Color(220, 220, 220)
|
||||||
|
|
||||||
# Draw partial sun
|
# Draw partial sun (stays in place)
|
||||||
graphics.DrawLine(canvas, x + 8, y + 2, x + 8, y + 4, ray_color)
|
graphics.DrawLine(canvas, x + 8, y + 2, x + 8, y + 4, ray_color)
|
||||||
graphics.DrawLine(canvas, x + 2, y + 8, x + 4, y + 8, ray_color)
|
graphics.DrawLine(canvas, x + 2, y + 8, x + 4, y + 8, ray_color)
|
||||||
graphics.DrawLine(canvas, x + 3, y + 3, x + 5, y + 5, ray_color)
|
graphics.DrawLine(canvas, x + 3, y + 3, x + 5, y + 5, ray_color)
|
||||||
for r in range(4, 0, -1):
|
for r in range(4, 0, -1):
|
||||||
graphics.DrawCircle(canvas, x + 8, y + 8, r, sun_color)
|
graphics.DrawCircle(canvas, x + 8, y + 8, r, sun_color)
|
||||||
|
|
||||||
# Draw cloud
|
# Draw cloud (with animation offset)
|
||||||
_draw_cloud_shape(canvas, x + 6, y + 10, cloud_color)
|
_draw_cloud_shape(canvas, x + 6 + cloud_offset, y + 10, cloud_color)
|
||||||
|
|
||||||
|
|
||||||
def draw_partly_cloudy_night(canvas, x, y):
|
def draw_partly_cloudy_night(canvas, x, y, cloud_offset=0):
|
||||||
"""Draw moon partially covered by cloud."""
|
"""Draw moon partially covered by cloud."""
|
||||||
moon_color = graphics.Color(255, 255, 200)
|
moon_color = graphics.Color(255, 255, 200)
|
||||||
cloud_color = graphics.Color(180, 180, 200)
|
cloud_color = graphics.Color(180, 180, 200)
|
||||||
|
|
||||||
for r in range(4, 0, -1):
|
for r in range(4, 0, -1):
|
||||||
graphics.DrawCircle(canvas, x + 8, y + 8, r, moon_color)
|
graphics.DrawCircle(canvas, x + 8, y + 8, r, moon_color)
|
||||||
_draw_cloud_shape(canvas, x + 6, y + 10, cloud_color)
|
_draw_cloud_shape(canvas, x + 6 + cloud_offset, y + 10, cloud_color)
|
||||||
|
|
||||||
|
|
||||||
def draw_cloudy(canvas, x, y):
|
def draw_cloudy(canvas, x, y):
|
||||||
@@ -218,16 +218,40 @@ WEATHER_ICONS = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def draw_weather_icon(canvas, x, y, weather_state):
|
def draw_weather_icon(canvas, x, y, weather_state, cloud_offset=0):
|
||||||
"""Draw weather icon based on state string."""
|
"""Draw weather icon based on state string.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
canvas: The LED matrix canvas
|
||||||
|
x, y: Position to draw at
|
||||||
|
weather_state: Weather condition string
|
||||||
|
cloud_offset: Animation offset for cloud movement (optional)
|
||||||
|
"""
|
||||||
weather_lower = weather_state.lower() if weather_state else ''
|
weather_lower = weather_state.lower() if weather_state else ''
|
||||||
|
|
||||||
# Try exact match
|
# Icons with cloud animation support
|
||||||
|
ANIMATED_ICONS = {
|
||||||
|
'partlycloudy': draw_partly_cloudy,
|
||||||
|
'partly-cloudy-day': draw_partly_cloudy,
|
||||||
|
'partly-cloudy-night': draw_partly_cloudy_night,
|
||||||
|
}
|
||||||
|
|
||||||
|
# Try animated icons first
|
||||||
|
if weather_lower in ANIMATED_ICONS:
|
||||||
|
ANIMATED_ICONS[weather_lower](canvas, x, y, cloud_offset)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Try exact match for static icons
|
||||||
if weather_lower in WEATHER_ICONS:
|
if weather_lower in WEATHER_ICONS:
|
||||||
WEATHER_ICONS[weather_lower](canvas, x, y)
|
WEATHER_ICONS[weather_lower](canvas, x, y)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Try partial match
|
# Try partial match
|
||||||
|
for key, draw_func in ANIMATED_ICONS.items():
|
||||||
|
if key in weather_lower or weather_lower in key:
|
||||||
|
draw_func(canvas, x, y, cloud_offset)
|
||||||
|
return
|
||||||
|
|
||||||
for key, draw_func in WEATHER_ICONS.items():
|
for key, draw_func in WEATHER_ICONS.items():
|
||||||
if key in weather_lower or weather_lower in key:
|
if key in weather_lower or weather_lower in key:
|
||||||
draw_func(canvas, x, y)
|
draw_func(canvas, x, y)
|
||||||
|
|||||||
Reference in New Issue
Block a user