Files

167 lines
6.4 KiB
Python
Raw Permalink Normal View History

2025-10-30 20:31:02 +01:00
import lvgl as lv
2025-11-23 09:00:38 +01:00
from lvgl import LvReferenceError
2026-01-23 21:37:53 +01:00
from .widget_animator import WidgetAnimator
2025-10-30 20:31:02 +01:00
from .view import back_screen
2025-12-05 13:37:11 +01:00
from mpos.ui import topmenu as topmenu
2026-01-23 23:25:22 +01:00
from .display_metrics import DisplayMetrics
2026-01-23 22:26:01 +01:00
from .appearance_manager import AppearanceManager
2025-10-30 20:31:02 +01:00
downbutton = None
backbutton = None
down_start_x = 0
down_start_y = 0
2025-10-30 20:31:02 +01:00
back_start_y = 0
back_start_x = 0
short_movement_threshold = 10
2025-11-20 16:36:14 +01:00
backbutton_visible = False
downbutton_visible = False
def is_short_movement(dx, dy):
return dx < short_movement_threshold and dy < short_movement_threshold
2025-10-30 20:31:02 +01:00
2025-11-23 09:00:38 +01:00
def _passthrough_click(x, y, indev):
obj = lv.indev_search_obj(lv.screen_active(), lv.point_t({'x': x, 'y': y}))
# print(f"Found object: {obj}")
if obj:
try:
# print(f"Simulating press/click/release on {obj}")
obj.send_event(lv.EVENT.PRESSED, indev)
obj.send_event(lv.EVENT.CLICKED, indev)
obj.send_event(lv.EVENT.RELEASED, indev) # gets lost
except LvReferenceError as e:
print(f"Object to click is gone: {e}")
2025-10-30 20:31:02 +01:00
def _back_swipe_cb(event):
2025-11-20 16:36:14 +01:00
global backbutton, back_start_y, back_start_x, backbutton_visible
2025-10-30 20:52:26 +01:00
event_code = event.get_code()
2025-10-30 20:31:02 +01:00
indev = lv.indev_active()
if not indev:
return
point = lv.point_t()
indev.get_point(point)
2025-10-30 20:52:26 +01:00
x = point.x
y = point.y
2025-11-20 16:36:14 +01:00
dx = abs(x - back_start_x)
dy = abs(y - back_start_y)
2025-10-30 20:52:26 +01:00
#print(f"visual_back_swipe_cb event_code={event_code} and event_name={name} and pos: {x}, {y}")
if event_code == lv.EVENT.PRESSED:
2025-10-30 20:31:02 +01:00
back_start_y = y
back_start_x = x
2025-10-30 20:52:26 +01:00
elif event_code == lv.EVENT.PRESSING:
2025-11-20 16:36:14 +01:00
should_show = not is_short_movement(dx, dy)
if should_show != backbutton_visible:
backbutton_visible = should_show
2026-01-23 21:37:53 +01:00
WidgetAnimator.smooth_show(backbutton) if should_show else WidgetAnimator.smooth_hide(backbutton)
2025-11-20 16:36:14 +01:00
backbutton.set_pos(round(x / 10), back_start_y)
2025-10-30 20:52:26 +01:00
elif event_code == lv.EVENT.RELEASED:
2025-11-20 16:36:14 +01:00
if backbutton_visible:
backbutton_visible = False
2026-01-23 21:37:53 +01:00
WidgetAnimator.smooth_hide(backbutton)
2026-01-23 20:46:36 +01:00
if x > DisplayMetrics.width() / 5:
2025-12-05 13:37:11 +01:00
if topmenu.drawer_open :
topmenu.close_drawer()
else :
back_screen()
2025-11-20 16:36:14 +01:00
elif is_short_movement(dx, dy):
# print("Short movement - treating as tap")
2025-11-23 09:00:38 +01:00
_passthrough_click(x, y, indev)
2025-10-30 20:52:26 +01:00
2025-10-30 20:31:02 +01:00
def _top_swipe_cb(event):
2025-12-05 13:37:11 +01:00
if topmenu.drawer_open:
2025-10-30 20:52:26 +01:00
print("ignoring top swipe gesture because drawer is open")
2025-10-30 20:31:02 +01:00
return
2025-10-30 20:52:26 +01:00
2025-11-20 16:36:14 +01:00
global downbutton, down_start_x, down_start_y, downbutton_visible
2025-10-30 20:52:26 +01:00
event_code = event.get_code()
2025-10-30 20:31:02 +01:00
indev = lv.indev_active()
if not indev:
return
point = lv.point_t()
indev.get_point(point)
2025-10-30 20:52:26 +01:00
x = point.x
y = point.y
2025-11-20 16:36:14 +01:00
dx = abs(x - down_start_x)
dy = abs(y - down_start_y)
# print(f"visual_back_swipe_cb event_code={event_code} and event_name={name} and pos: {x}, {y}")
2025-10-30 20:52:26 +01:00
if event_code == lv.EVENT.PRESSED:
2025-10-30 20:31:02 +01:00
down_start_x = x
down_start_y = y
2025-10-30 20:52:26 +01:00
elif event_code == lv.EVENT.PRESSING:
2025-11-20 16:36:14 +01:00
should_show = not is_short_movement(dx, dy)
if should_show != downbutton_visible:
downbutton_visible = should_show
2026-01-23 21:37:53 +01:00
WidgetAnimator.smooth_show(downbutton) if should_show else WidgetAnimator.smooth_hide(downbutton)
2025-11-20 16:36:14 +01:00
downbutton.set_pos(down_start_x, round(y / 10))
2025-10-30 20:52:26 +01:00
elif event_code == lv.EVENT.RELEASED:
2025-11-20 16:36:14 +01:00
if downbutton_visible:
downbutton_visible = False
2026-01-23 21:37:53 +01:00
WidgetAnimator.smooth_hide(downbutton)
dx = abs(x - down_start_x)
dy = abs(y - down_start_y)
2026-01-23 20:46:36 +01:00
if y > DisplayMetrics.height() / 5:
2025-12-05 13:37:11 +01:00
topmenu.open_drawer()
2025-11-20 16:36:14 +01:00
elif is_short_movement(dx, dy):
# print("Short movement - treating as tap")
2025-11-23 09:00:38 +01:00
_passthrough_click(x, y, indev)
2025-10-30 20:52:26 +01:00
2025-10-30 20:31:02 +01:00
def handle_back_swipe():
global backbutton
rect = lv.obj(lv.layer_top())
2026-01-23 22:26:01 +01:00
rect.set_size(AppearanceManager.NOTIFICATION_BAR_HEIGHT, lv.layer_top().get_height()-AppearanceManager.NOTIFICATION_BAR_HEIGHT) # narrow because it overlaps buttons
2025-10-30 20:31:02 +01:00
rect.set_scrollbar_mode(lv.SCROLLBAR_MODE.OFF)
2025-10-30 20:52:26 +01:00
rect.set_scroll_dir(lv.DIR.NONE)
2026-01-23 22:26:01 +01:00
rect.set_pos(0, AppearanceManager.NOTIFICATION_BAR_HEIGHT)
2025-10-30 20:31:02 +01:00
style = lv.style_t()
style.init()
style.set_bg_opa(lv.OPA.TRANSP)
style.set_border_width(0)
2025-10-30 20:52:26 +01:00
style.set_radius(0)
2025-11-21 09:12:45 +01:00
if False: # debug the swipe zone with a red border
2025-10-30 20:52:26 +01:00
style.set_bg_opa(15)
style.set_border_width(4)
style.set_border_color(lv.color_hex(0xFF0000)) # Red border for visibility
style.set_border_opa(lv.OPA._50) # 50% opacity for the border
2025-10-30 20:31:02 +01:00
rect.add_style(style, 0)
rect.add_event_cb(_back_swipe_cb, lv.EVENT.PRESSED, None)
rect.add_event_cb(_back_swipe_cb, lv.EVENT.PRESSING, None)
rect.add_event_cb(_back_swipe_cb, lv.EVENT.RELEASED, None)
2025-10-30 20:52:26 +01:00
# button with label that shows up during the dragging:
2025-10-30 20:31:02 +01:00
backbutton = lv.button(lv.layer_top())
2025-10-30 20:52:26 +01:00
backbutton.set_pos(0, round(lv.layer_top().get_height() / 2))
2025-10-30 20:31:02 +01:00
backbutton.add_flag(lv.obj.FLAG.HIDDEN)
backbutton.add_state(lv.STATE.DISABLED)
2025-10-30 20:52:26 +01:00
backlabel = lv.label(backbutton)
backlabel.set_text(lv.SYMBOL.LEFT)
backlabel.set_style_text_font(lv.font_montserrat_18, lv.PART.MAIN)
2025-10-30 20:52:26 +01:00
backlabel.center()
2025-10-30 20:31:02 +01:00
def handle_top_swipe():
global downbutton
rect = lv.obj(lv.layer_top())
2026-01-23 22:26:01 +01:00
rect.set_size(lv.pct(100), AppearanceManager.NOTIFICATION_BAR_HEIGHT)
2025-10-30 20:31:02 +01:00
rect.set_pos(0, 0)
rect.set_scrollbar_mode(lv.SCROLLBAR_MODE.OFF)
style = lv.style_t()
style.init()
style.set_bg_opa(lv.OPA.TRANSP)
2025-10-30 20:52:26 +01:00
style.set_border_width(0)
style.set_radius(0)
2025-11-21 09:12:45 +01:00
if False: # debug the swipe zone with a red border
style.set_bg_opa(15)
style.set_border_width(4)
style.set_border_color(lv.color_hex(0xFF0000)) # Red border for visibility
style.set_border_opa(lv.OPA._50) # 50% opacity for the border
2025-10-30 20:31:02 +01:00
rect.add_style(style, 0)
rect.add_event_cb(_top_swipe_cb, lv.EVENT.PRESSED, None)
rect.add_event_cb(_top_swipe_cb, lv.EVENT.PRESSING, None)
rect.add_event_cb(_top_swipe_cb, lv.EVENT.RELEASED, None)
2025-10-30 20:52:26 +01:00
# button with label that shows up during the dragging:
2025-10-30 20:31:02 +01:00
downbutton = lv.button(lv.layer_top())
2025-10-30 20:52:26 +01:00
downbutton.set_pos(0, round(lv.layer_top().get_height() / 2))
2025-10-30 20:31:02 +01:00
downbutton.add_flag(lv.obj.FLAG.HIDDEN)
downbutton.add_state(lv.STATE.DISABLED)
2025-10-30 20:52:26 +01:00
downlabel = lv.label(downbutton)
downlabel.set_text(lv.SYMBOL.DOWN)
downlabel.set_style_text_font(lv.font_montserrat_18, lv.PART.MAIN)
2025-10-30 20:52:26 +01:00
downlabel.center()