""" Copyright © IQ.Lvbs, apart of Project Teal Lvbs, All Rights Reserved, licensed under https://konn3kt.com/tos/ """ import pyray as rl import iqpilot.cereal.messaging as messaging from iqpilot.selfdrive.ui.mici.layouts.home import MiciHomeLayout from iqpilot.selfdrive.ui.mici.layouts.settings.settings import SettingsLayout from iqpilot.selfdrive.ui.mici.layouts.offroad_alerts import MiciOffroadAlerts from iqpilot.selfdrive.ui.mici.onroad.augmented_road_view import AugmentedRoadView from iqpilot.selfdrive.ui.ui_state import device, ui_state from iqpilot.selfdrive.ui.mici.layouts.onboarding import OnboardingWindow from iqpilot.system.ui.widgets import Widget from iqpilot.system.ui.widgets.scroller import Scroller from iqpilot.system.ui.lib.application import gui_app from iqpilot.system.ui.lib.multilang import multilang from iqpilot.system.version import training_version ONROAD_DELAY = 2.5 # seconds class MiciMainLayout(Widget): """Root mici layout. Lives at the bottom of the nav stack; settings push on top. Keeps the IQ.Pilot custom home + onroad as horizontally-scrolled pages, while the (stock) settings open as a swipe-to-dismiss NavWidget on the nav stack. """ def __init__(self): super().__init__() self._pm = messaging.PubMaster(['bookmarkButton']) self._prev_onroad = False self._prev_standstill = False self._onroad_time_delay: float | None = None self._setup = False self._rebuild_settings = False self._home_layout = MiciHomeLayout() self._alerts_layout = MiciOffroadAlerts() self._settings_layout = SettingsLayout() self._onroad_layout = AugmentedRoadView(bookmark_callback=self._on_bookmark_clicked) for widget in (self._home_layout, self._settings_layout, self._alerts_layout, self._onroad_layout): widget.set_rect(rl.Rectangle(0, 0, gui_app.width, gui_app.height)) self._scroller = Scroller([ self._alerts_layout, self._home_layout, self._onroad_layout, ], spacing=0, pad_start=0, pad_end=0) self._scroller.set_reset_scroll_at_show(False) # Disable scrolling when onroad is interacting with bookmark self._scroller.set_scrolling_enabled(lambda: not self._onroad_layout.is_swiping_left()) self._setup_callbacks() if ui_state.params.get("CompletedTrainingVersion") != training_version: ui_state.params.put("CompletedTrainingVersion", training_version) gui_app.add_nav_stack_tick(self._handle_transitions) gui_app.push_widget(self) self._onboarding_window = OnboardingWindow() if not self._onboarding_window.completed: gui_app.set_modal_overlay(self._onboarding_window) def _setup_callbacks(self): self._home_layout.set_callbacks(on_settings=self._on_settings_clicked) self._onroad_layout.set_click_callback(lambda: self._scroll_to(self._home_layout)) device.add_interactive_timeout_callback(self._on_interactive_timeout) multilang.add_change_callback(self._on_language_changed) def _on_language_changed(self): self._rebuild_settings = True def _scroll_to(self, layout: Widget): self._scroller.scroll_to(int(layout.rect.x), smooth=True) def show_event(self): super().show_event() self._scroller.show_event() def _render(self, _): if not self._setup: if self._alerts_layout.active_alerts() > 0: self._scroller.scroll_to(self._alerts_layout.rect.x) else: self._scroller.scroll_to(self._rect.width) self._setup = True self._scroller.render(self._rect) def _handle_transitions(self): if ui_state.started != self._prev_onroad: self._prev_onroad = ui_state.started if ui_state.started: self._onroad_time_delay = rl.get_time() else: self._scroll_to(self._home_layout) if self._onroad_time_delay is not None and rl.get_time() - self._onroad_time_delay >= ONROAD_DELAY: gui_app.pop_widgets_to(self, lambda: self._scroll_to(self._onroad_layout)) self._onroad_time_delay = None CS = ui_state.sm["carState"] if not CS.standstill and self._prev_standstill: gui_app.pop_widgets_to(self, lambda: self._scroll_to(self._onroad_layout)) self._prev_standstill = CS.standstill if self._rebuild_settings: self._rebuild_settings = False gui_app.pop_widgets_to(self, instant=True) self._settings_layout = SettingsLayout() self._settings_layout.set_rect(rl.Rectangle(0, 0, gui_app.width, gui_app.height)) def _on_interactive_timeout(self): if ui_state.started: if not ui_state.sm["carState"].standstill: gui_app.pop_widgets_to(self, lambda: self._scroll_to(self._onroad_layout)) else: gui_app.pop_widgets_to(self, instant=True) self._scroll_to(self._home_layout) def _on_settings_clicked(self): gui_app.push_widget(self._settings_layout) def _on_bookmark_clicked(self): user_bookmark = messaging.new_message('bookmarkButton') user_bookmark.valid = True self._pm.send('bookmarkButton', user_bookmark)