This repository has been archived on 2026-08-08. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
DynaLab-V0/src/dynalab/ui/windows.py
T
2026-07-11 16:53:25 +01:00

212 lines
6.9 KiB
Python

# Copyright (C) 2026 Hector van der Aa <hector@h3cx.dev>
# Copyright (C) 2026 Association Exergie <association.exergie@gmail.com>
# SPDX-License-Identifier: GPL-3.0-or-later
import dearpygui.dearpygui as dpg
import dpg_gauges as dpgg
from dynalab.state import AppState
from dynalab.tags import (
LISTBOX_RECORD_CONFIGURATION,
LISTBOX_RECORD_CONFIGURATION_ADD_SINGAL,
MENU_FILE_QUIT,
MENU_RECORD_CONFIGURATION,
MENU_WINDOW_DATA_INPUT,
MENU_WINDOW_RECORD,
TEXT_INPUT_RECORD_CONFIGURATION,
WINDOW_DATA_INPUT_GAUGE_GRID,
WINDOW_GROUP_DATA_INPUT,
WINDOW_GROUP_RECORD,
WINDOW_RECORD_CONFIGURATION,
WINDOW_RECORD_CONFIGURATION_ADD_SIGNAL,
)
from dynalab.ui.routines import (
listbox_record_configuration_add_item,
listbox_record_configuration_add_item_select,
listbox_record_configuration_remove_selected_item,
show_window_record_configuration,
switch_window,
)
from dynalab.i18n import _
LOADING_WINDOW_WIDTH = 600
LOADING_WINDOW_HEIGHT = 400
def _loading_content_layout(
viewport_size: tuple[int, int],
logo_size: tuple[int, int],
text_size: tuple[int, int],
bottom_margin: int = 24,
) -> tuple[list[float], list[float], float]:
viewport_width, viewport_height = viewport_size
logo_width, logo_height = logo_size
text_width, text_height = text_size
logo_pos = [
(viewport_width - logo_width) / 2,
(viewport_height - logo_height) / 2,
]
text_row_pos = [
0,
max(viewport_height - text_height - bottom_margin, 0),
]
text_spacer_width = max((viewport_width - text_width) / 2, 0)
return logo_pos, text_row_pos, text_spacer_width
def build_loading() -> None:
with dpg.window(
label="DynaLab",
tag="loading_window",
width=LOADING_WINDOW_WIDTH,
height=LOADING_WINDOW_HEIGHT,
no_collapse=True,
no_resize=True,
no_move=True,
no_title_bar=True,
):
dpg.set_global_font_scale(0.5)
with dpg.group(horizontal=False, tag="loading_logo_group"):
dpg.add_image(texture_tag="logo", tag="loading_logo")
with dpg.group(horizontal=True, tag="loading_text_row"):
dpg.add_spacer(width=0, tag="loading_text_left_spacer")
dpg.add_text(
default_value="Loading DynaLab",
tag="loading_text",
color=(150, 150, 150, 255),
)
def center_loading_content() -> None:
if not dpg.does_item_exist("loading_window"):
return
dpg.set_item_pos("loading_window", [0, 0])
dpg.set_item_width("loading_window", LOADING_WINDOW_WIDTH)
dpg.set_item_height("loading_window", LOADING_WINDOW_HEIGHT)
# These may be unavailable before the first rendered frame
logo_size = dpg.get_item_rect_size("loading_logo")
text_size = dpg.get_item_rect_size("loading_text")
if logo_size is None or text_size is None:
return
logo_pos, text_row_pos, text_spacer_width = _loading_content_layout(
(LOADING_WINDOW_WIDTH, LOADING_WINDOW_HEIGHT), logo_size, text_size
)
dpg.set_item_pos("loading_logo_group", logo_pos)
dpg.set_item_pos("loading_text_row", text_row_pos)
dpg.set_item_width("loading_text_left_spacer", text_spacer_width)
def build_record_configuration_add_signal_window(state: AppState) -> None:
with dpg.window(
label="Add Signal",
tag=WINDOW_RECORD_CONFIGURATION_ADD_SIGNAL,
no_collapse=True,
show=False,
min_size=(500, 300),
modal=True,
):
dpg.add_listbox(
tag=LISTBOX_RECORD_CONFIGURATION_ADD_SINGAL,
num_items=10,
width=480,
)
with dpg.group(horizontal=True):
dpg.add_button(
label="Select",
callback=listbox_record_configuration_add_item_select,
user_data=state,
)
dpg.add_button(
label="Refresh",
callback=listbox_record_configuration_add_item,
user_data=state,
)
def build_record_configuration_window(state: AppState) -> None:
with dpg.window(
label="Recording Configuration",
tag=WINDOW_RECORD_CONFIGURATION,
no_collapse=True,
show=False,
min_size=(500, 300),
):
with dpg.group():
dpg.add_text("Configuration Name")
dpg.add_input_text(tag=TEXT_INPUT_RECORD_CONFIGURATION)
dpg.add_text("Selected Signals")
dpg.add_listbox(
tag=LISTBOX_RECORD_CONFIGURATION,
num_items=10,
width=480,
)
with dpg.group(horizontal=True):
dpg.add_button(
label="Add",
callback=listbox_record_configuration_add_item,
user_data=state,
)
dpg.add_button(
label="Remove",
callback=listbox_record_configuration_remove_selected_item,
user_data=state,
)
def build_windows(state: AppState) -> None:
with dpg.window(label="DynaLab", tag="main_window", no_collapse=True):
with dpg.menu_bar():
with dpg.menu(label=_("File")):
dpg.add_menu_item(tag=MENU_FILE_QUIT, label=_("Quit"), enabled=True)
with dpg.menu(label=_("Record")):
dpg.add_menu_item(
tag=MENU_RECORD_CONFIGURATION,
label=_("Configuration"),
callback=show_window_record_configuration,
user_data=state,
)
with dpg.menu(label=_("Window")):
dpg.add_menu_item(
tag=MENU_WINDOW_RECORD,
label=_("Record"),
callback=switch_window,
user_data=state,
)
dpg.add_menu_item(
tag=MENU_WINDOW_DATA_INPUT,
label=_("Data Input"),
callback=switch_window,
user_data=state,
)
with dpg.child_window(
tag="content_area", autosize_x=True, height=0, border=False
):
# with dpg.group(tag=MENU_WINDOW_DATA_INPUT):
with dpg.group(tag=WINDOW_GROUP_DATA_INPUT):
state.window_map[MENU_WINDOW_DATA_INPUT] = WINDOW_GROUP_DATA_INPUT
with dpgg.gauge_panel(autosize_x=True, autosize_y=True):
with dpgg.gauge_grid(
columns="auto",
min_column_width=180,
tag=WINDOW_DATA_INPUT_GAUGE_GRID,
):
pass
with dpg.group(tag=WINDOW_GROUP_RECORD, show=False):
state.window_map[MENU_WINDOW_RECORD] = WINDOW_GROUP_RECORD
dpg.add_text("Some text")
build_record_configuration_window(state)
build_record_configuration_add_signal_window(state)