mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-11-07 04:53:47 +08:00
a82935f326
Integrate onroad views, configurable widgets, local settings, steering-profile contracts, Bluetooth and Android Auto with their device and runtime services. Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com> Co-authored-by: Daniel Koepping <elkoled@gmail.com> Co-authored-by: Danny <dannyirwin31@yahoo.com> Co-authored-by: DimitriChrysafis <Dimitri.chrysafis@gmail.com> Co-authored-by: Dom <168790843+firestar5683@users.noreply.github.com> Co-authored-by: Harald Schäfer <harald.the.engineer@gmail.com> Co-authored-by: Prabhaav Pillai <prabhaav@msu.edu> Co-authored-by: Shane Smiskol <shane@smiskol.com> Co-authored-by: dirwin31 <83434411+dirwin31@users.noreply.github.com> Co-authored-by: firestarsdog <229254897+firestarsdog@users.noreply.github.com> Co-authored-by: stef <19478336+stefpi@users.noreply.github.com> Co-authored-by: whoisdomi <dcantu83@gmail.com> Co-authored-by: Intelli <contact@intelli.software> Co-authored-by: pharmacomaniac <blittle65@gmail.com> Co-authored-by: prabhaavp <prabhaav@msu.edu>
106 lines
3.7 KiB
Python
106 lines
3.7 KiB
Python
"""Supplied Software viewport data and inert, typed input requests."""
|
|
|
|
from collections.abc import Callable
|
|
from dataclasses import dataclass
|
|
from enum import StrEnum
|
|
|
|
|
|
class DownloadLabel(StrEnum):
|
|
CHECK = "CHECK"
|
|
DOWNLOAD = "DOWNLOAD"
|
|
|
|
|
|
class SoftwareRequest(StrEnum):
|
|
SET_AUTOMATIC_UPDATES = "set_automatic_updates"
|
|
CHECK_FOR_UPDATES = "check_for_updates"
|
|
DOWNLOAD_UPDATE = "download_update"
|
|
FAST_UPDATE = "fast_update"
|
|
ROLLBACK = "rollback"
|
|
OPEN_BRANCH_CHOOSER = "open_branch_chooser"
|
|
OPEN_UNINSTALL_CONFIRMATION = "open_uninstall_confirmation"
|
|
OPEN_ERROR_LOG = "open_error_log"
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class SoftwareAction:
|
|
request: SoftwareRequest
|
|
desired_enabled: bool | None = None
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class SoftwareState:
|
|
current_version: str = ""
|
|
automatic_updates: bool | None = True
|
|
download_status: str = "up to date, last checked never"
|
|
download_label: DownloadLabel = DownloadLabel.CHECK
|
|
target_branch: str = ""
|
|
available_actions: frozenset[SoftwareRequest] = frozenset(SoftwareRequest)
|
|
|
|
|
|
BUTTON_ROWS = (
|
|
(SoftwareRequest.CHECK_FOR_UPDATES, 2),
|
|
(SoftwareRequest.OPEN_BRANCH_CHOOSER, 3),
|
|
(SoftwareRequest.OPEN_UNINSTALL_CONFIRMATION, 4),
|
|
(SoftwareRequest.OPEN_ERROR_LOG, 5),
|
|
)
|
|
|
|
|
|
def button_rect(row: int) -> tuple[int, int, int, int]:
|
|
return 1860, 50 + row * 171 + 35, 250, 100
|
|
|
|
|
|
DIRECT_BUTTONS = ((SoftwareRequest.FAST_UPDATE, (1540, 427, 250, 100)),
|
|
(SoftwareRequest.ROLLBACK, (1260, 427, 250, 100)))
|
|
|
|
|
|
TOGGLE_RECT = (1950, 266, 160, 80)
|
|
|
|
|
|
class SoftwareInput:
|
|
"""Single-pointer hit testing. The caller decides what any request means."""
|
|
|
|
def __init__(self, emit: Callable[[SoftwareAction], None]):
|
|
self.emit = emit
|
|
self._pressed: tuple[float, float, SoftwareRequest, bool | None] | None = None
|
|
|
|
@staticmethod
|
|
def _target(x: float, y: float, state: SoftwareState) -> SoftwareRequest | None:
|
|
if not (550 <= x < 2110 and 50 <= y < 1030):
|
|
return None
|
|
tx, ty, tw, th = TOGGLE_RECT
|
|
if tx <= x < tx + tw and ty <= y < ty + th:
|
|
return SoftwareRequest.SET_AUTOMATIC_UPDATES if SoftwareRequest.SET_AUTOMATIC_UPDATES in state.available_actions else None
|
|
for request, (bx, by, bw, bh) in DIRECT_BUTTONS:
|
|
if bx <= x < bx + bw and by <= y < by + bh:
|
|
return request if request in state.available_actions else None
|
|
for request, row in BUTTON_ROWS:
|
|
bx, by, bw, bh = button_rect(row)
|
|
if bx <= x < bx + bw and by <= y < by + bh:
|
|
if request == SoftwareRequest.CHECK_FOR_UPDATES and state.download_label == DownloadLabel.DOWNLOAD:
|
|
request = SoftwareRequest.DOWNLOAD_UPDATE
|
|
return request if request in state.available_actions else None
|
|
return None
|
|
|
|
def press(self, x: float, y: float, state: SoftwareState) -> None:
|
|
target = self._target(x, y, state)
|
|
displayed_toggle = state.automatic_updates if target == SoftwareRequest.SET_AUTOMATIC_UPDATES else None
|
|
self._pressed = (x, y, target, displayed_toggle) if target is not None else None
|
|
|
|
def move(self, x: float, y: float, state: SoftwareState) -> None:
|
|
if self._pressed is not None:
|
|
_, _, target, displayed_toggle = self._pressed
|
|
if (self._target(x, y, state) != target or
|
|
(target == SoftwareRequest.SET_AUTOMATIC_UPDATES and state.automatic_updates != displayed_toggle)):
|
|
self.cancel()
|
|
|
|
def release(self, x: float, y: float, state: SoftwareState) -> None:
|
|
self.move(x, y, state)
|
|
if self._pressed is not None:
|
|
_, _, request, displayed_toggle = self._pressed
|
|
desired = not displayed_toggle if displayed_toggle is not None else None
|
|
self.emit(SoftwareAction(request, desired))
|
|
self.cancel()
|
|
|
|
def cancel(self) -> None:
|
|
self._pressed = None
|