Swipe gesture controls, menu system, MQTT alert parameter check
This commit is contained in:
162
matrix.py
162
matrix.py
@@ -146,33 +146,83 @@ class Matrix64Display(SampleBase):
|
||||
self.mqtt = MQTTListener()
|
||||
self.mqtt.start()
|
||||
|
||||
# Menu state
|
||||
self.menu_mode = False
|
||||
self.menu_selection = 0
|
||||
|
||||
# Swipe gesture detection
|
||||
self.last_button = None
|
||||
self.last_button_time = 0
|
||||
self.swipe_timeout = 0.4 # seconds
|
||||
|
||||
# Buttons
|
||||
self.button1 = Button(0, pull_up=True, hold_time=1.5)
|
||||
self.button2 = Button(1, pull_up=True, hold_time=1.5)
|
||||
self.button1.when_pressed = self.on_button1_press
|
||||
self.button1.when_held = self.on_button_held
|
||||
self.button2.when_pressed = self.on_button2_press
|
||||
self.button2.when_held = self.on_button_held
|
||||
self.button0 = Button(0, pull_up=True, hold_time=1.0)
|
||||
self.button1 = Button(1, pull_up=True, hold_time=1.0)
|
||||
|
||||
self.button0.when_pressed = lambda: self.on_button_press(0)
|
||||
self.button1.when_pressed = lambda: self.on_button_press(1)
|
||||
self.button0.when_held = self.on_button0_held
|
||||
self.button1.when_held = self.on_button1_held
|
||||
|
||||
def show_feedback(self, message, duration=2):
|
||||
self.feedback_message = message
|
||||
self.feedback_until = time.time() + duration
|
||||
|
||||
def on_button1_press(self):
|
||||
if not self.button1.is_held:
|
||||
self.current_view = (self.current_view + 1) % NUM_VIEWS
|
||||
self.last_view_change = time.time()
|
||||
def on_button_press(self, button_id):
|
||||
"""Handle button press for swipe detection."""
|
||||
now = time.time()
|
||||
|
||||
# Check for swipe gesture
|
||||
if self.last_button is not None and (now - self.last_button_time) < self.swipe_timeout:
|
||||
if self.last_button == 0 and button_id == 1:
|
||||
# Swipe 0→1
|
||||
if self.menu_mode:
|
||||
self.menu_selection = (self.menu_selection - 1) % NUM_VIEWS # Up
|
||||
else:
|
||||
self.current_view = (self.current_view + 1) % NUM_VIEWS # Next
|
||||
self.last_view_change = now
|
||||
self.show_feedback(VIEW_NAMES[self.current_view], 1.5)
|
||||
self.last_button = None
|
||||
return
|
||||
elif self.last_button == 1 and button_id == 0:
|
||||
# Swipe 1→0
|
||||
if self.menu_mode:
|
||||
self.menu_selection = (self.menu_selection + 1) % NUM_VIEWS # Down
|
||||
else:
|
||||
self.current_view = (self.current_view - 1) % NUM_VIEWS # Prev
|
||||
self.last_view_change = now
|
||||
self.show_feedback(VIEW_NAMES[self.current_view], 1.5)
|
||||
self.last_button = None
|
||||
return
|
||||
|
||||
# Single button press (for menu select)
|
||||
if self.menu_mode and button_id == 1:
|
||||
# Select highlighted view
|
||||
self.current_view = self.menu_selection
|
||||
self.menu_mode = False
|
||||
self.show_feedback(VIEW_NAMES[self.current_view], 1.5)
|
||||
self.last_button = None
|
||||
return
|
||||
|
||||
self.last_button = button_id
|
||||
self.last_button_time = now
|
||||
|
||||
def on_button2_press(self):
|
||||
if not self.button2.is_held:
|
||||
self.current_view = (self.current_view - 1) % NUM_VIEWS
|
||||
self.last_view_change = time.time()
|
||||
self.show_feedback(VIEW_NAMES[self.current_view], 1.5)
|
||||
def on_button0_held(self):
|
||||
"""Long press button 0 = open menu."""
|
||||
self.menu_mode = not self.menu_mode
|
||||
if self.menu_mode:
|
||||
self.menu_selection = self.current_view
|
||||
self.show_feedback("Menú", 1)
|
||||
else:
|
||||
self.show_feedback("Cerrado", 1)
|
||||
self.last_button = None
|
||||
|
||||
def on_button_held(self):
|
||||
self.auto_cycle = not self.auto_cycle
|
||||
self.show_feedback("AUTO ON" if self.auto_cycle else "AUTO OFF", 2)
|
||||
def on_button1_held(self):
|
||||
"""Long press button 1 = toggle auto-cycle."""
|
||||
if not self.menu_mode:
|
||||
self.auto_cycle = not self.auto_cycle
|
||||
self.show_feedback("AUTO ON" if self.auto_cycle else "AUTO OFF", 2)
|
||||
self.last_button = None
|
||||
|
||||
def update_data(self):
|
||||
try:
|
||||
@@ -242,6 +292,57 @@ class Matrix64Display(SampleBase):
|
||||
x = (64 - msg_len) // 2
|
||||
graphics.DrawText(canvas, time_font, x, 38, msg_color, self.feedback_message)
|
||||
|
||||
def draw_menu(self, canvas, fonts, colors):
|
||||
"""Draw view selection menu with scrolling."""
|
||||
time_font, data_font, small_font = fonts
|
||||
time_color, humidity_color, hdd_color, label_color, line_color = colors
|
||||
|
||||
# Full black background
|
||||
for y in range(64):
|
||||
graphics.DrawLine(canvas, 0, y, 63, y, graphics.Color(0, 0, 0))
|
||||
|
||||
# Title
|
||||
title = "Vistas"
|
||||
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)
|
||||
|
||||
# Menu items (3 visible at a time, selected centered)
|
||||
visible_items = 4
|
||||
item_height = 12
|
||||
start_y = 22
|
||||
|
||||
# Calculate scroll offset to keep selection centered
|
||||
center_slot = visible_items // 2
|
||||
scroll_offset = max(0, min(self.menu_selection - center_slot, NUM_VIEWS - visible_items))
|
||||
|
||||
for i in range(visible_items):
|
||||
view_idx = scroll_offset + i
|
||||
if view_idx >= NUM_VIEWS:
|
||||
break
|
||||
|
||||
y = start_y + i * item_height
|
||||
name = VIEW_NAMES[view_idx]
|
||||
|
||||
if view_idx == self.menu_selection:
|
||||
# Highlight selected
|
||||
highlight_color = graphics.Color(0, 40, 80)
|
||||
for hy in range(y - 9, y + 2):
|
||||
if 0 <= hy < 64:
|
||||
graphics.DrawLine(canvas, 0, hy, 63, hy, highlight_color)
|
||||
text_color = graphics.Color(100, 255, 200)
|
||||
graphics.DrawText(canvas, data_font, 4, y, text_color, "> " + name)
|
||||
else:
|
||||
text_color = graphics.Color(100, 100, 100)
|
||||
graphics.DrawText(canvas, data_font, 8, y, text_color, name)
|
||||
|
||||
# Scroll indicators
|
||||
if scroll_offset > 0:
|
||||
graphics.DrawText(canvas, small_font, 58, 18, label_color, "^")
|
||||
if scroll_offset + visible_items < NUM_VIEWS:
|
||||
graphics.DrawText(canvas, small_font, 58, 62, label_color, "v")
|
||||
|
||||
def draw_view_0(self, canvas, fonts, colors):
|
||||
"""Vista Principal"""
|
||||
time_font, data_font, small_font = fonts
|
||||
@@ -439,20 +540,25 @@ class Matrix64Display(SampleBase):
|
||||
|
||||
canvas.Clear()
|
||||
|
||||
if self.current_view == 0:
|
||||
self.draw_view_0(canvas, fonts, colors)
|
||||
elif self.current_view == 1:
|
||||
self.draw_view_1(canvas, fonts, colors)
|
||||
elif self.current_view == 2:
|
||||
self.draw_view_2(canvas, fonts, colors)
|
||||
elif self.current_view == 3:
|
||||
self.draw_view_3(canvas, fonts, colors)
|
||||
# Menu mode takes priority over views
|
||||
if self.menu_mode:
|
||||
self.draw_menu(canvas, fonts, colors)
|
||||
else:
|
||||
# Draw current view
|
||||
if self.current_view == 0:
|
||||
self.draw_view_0(canvas, fonts, colors)
|
||||
elif self.current_view == 1:
|
||||
self.draw_view_1(canvas, fonts, colors)
|
||||
elif self.current_view == 2:
|
||||
self.draw_view_2(canvas, fonts, colors)
|
||||
elif self.current_view == 3:
|
||||
self.draw_view_3(canvas, fonts, colors)
|
||||
|
||||
# Camera alert overlay (highest priority)
|
||||
if self.mqtt.is_alert_active():
|
||||
self.draw_camera_alert(canvas, fonts)
|
||||
# Feedback overlay
|
||||
elif self.feedback_message and current_time < self.feedback_until:
|
||||
# Feedback overlay (only when not in menu)
|
||||
elif not self.menu_mode and self.feedback_message and current_time < self.feedback_until:
|
||||
self.draw_feedback(canvas, fonts, colors)
|
||||
else:
|
||||
self.feedback_message = None
|
||||
|
||||
Reference in New Issue
Block a user