Common commit

This commit is contained in:
2025-10-16 18:42:32 +07:00
parent 124065d2ac
commit 40c320a1ac
21 changed files with 1916 additions and 379 deletions

242
modules/ui/gui/Sample.py Normal file
View File

@@ -0,0 +1,242 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Fletприложение: боковая панель + рабочая область
(с учётом всех уточнений: исчезновение текста при сворачивании,
акцент только на активной группе/вкладке, иконка‑кнопка смены темы,
фиолетовый акцентный цвет).
"""
import flet as ft
# ---------- Параметры изображений ----------
LOGO_LIGHT_COLLAPSED = "logo_light_small.png" # светлый логотип, «маленький»
LOGO_LIGHT_EXPANDED = "logo_light_large.png" # светлый логотип, «большой»
LOGO_DARK_COLLAPSED = "logo_dark_small.png" # тёмный логотип, «маленький»
LOGO_DARK_EXPANDED = "logo_dark_large.png" # тёмный логотип, «большой»
# ---------- Цвета ----------
LIGHT_BG = "#e0f7fa"
DARK_BG = "#263238"
LIGHT_ACC = "#9C27B0" # фиолетовый 500
DARK_ACC = "#7B1FA2" # фиолетовый 700
# ---------- Вспомогательные функции ----------
def status_lamp(color: str) -> ft.Icon:
return ft.Icon(ft.Icons.CIRCLE, size=12, color=color)
def group_icon(name: str) -> ft.Icon:
mapping = {
"Repository": ft.Icons.ARCHIVE,
"Environment": ft.Icons.FOLDER,
"Civit": ft.Icons.HEXAGON,
"Tasks": ft.Icons.DOWNLOAD,
}
return ft.Icon(mapping.get(name, ft.Icons.FOLDER), size=20)
def tab_icon() -> ft.Icon:
return ft.Icon(ft.Icons.FILE_COPY, size=30)
# ---------- Главная функция ----------
def main(page: ft.Page):
page.title = "Flet Sidebar Demo"
page.vertical_alignment = ft.MainAxisAlignment.START
page.horizontal_alignment = ft.CrossAxisAlignment.START
# ----- Состояния -----
is_expanded = True
group_expanded = {
"Repository": True,
"Environment": False,
"Civit": False,
"Tasks": False,
}
selected_group: str | None = None
selected_tab_name: str | None = None
selected_tab = ft.Text(value="Выберите вкладку", size=24, weight=ft.FontWeight.W_400)
# ----- Логотип -----
def get_logo_path() -> str:
if page.theme_mode == ft.ThemeMode.LIGHT:
return LOGO_LIGHT_EXPANDED if is_expanded else LOGO_LIGHT_COLLAPSED
else:
return LOGO_DARK_EXPANDED if is_expanded else LOGO_DARK_COLLAPSED
# ----- Панель навигации -----
sidebar = ft.Container(
width=200 if is_expanded else 60,
bgcolor=ft.Colors.SURFACE,
padding=ft.padding.all(8),
content=ft.Column(spacing=8, controls=[]),
)
# ----- Рабочая область -----
main_area = ft.Container(
expand=True,
padding=ft.padding.all(20),
content=ft.Container(
alignment=ft.alignment.center,
content=selected_tab
)
)
# ----- Макет -----
page.add(ft.Row(controls=[sidebar, main_area], expand=True))
# ----- Пересоздание боковой панели -----
def rebuild_sidebar():
"""Пересоздаёт содержимое боковой панели."""
controls = []
# 1. Логотип (с кликом)
logo_img = ft.Image(
src=get_logo_path(),
width=50 if not is_expanded else 150,
height=50 if not is_expanded else 150,
fit=ft.ImageFit.CONTAIN
)
logo_container = ft.Container(
content=logo_img,
on_click=lambda e: toggle_sidebar()
)
controls.append(logo_container)
# 2. Группы вкладок
groups = {
"Repository": ["Create", "Upload"],
"Environment": ["Create", "Upload", "Install"],
"Civit": ["Initialize", "Overview", "Selection"],
"Tasks": ["Upload"],
}
for grp_name, tabs in groups.items():
controls.append(build_group(grp_name, tabs))
# 3. Кнопка смены темы (только иконка)
controls.append(ft.Container(height=20))
theme_icon = ft.Icons.SUNNY if page.theme_mode == ft.ThemeMode.LIGHT else ft.Icons.NIGHTLIGHT_ROUNDED
theme_btn = ft.IconButton(
icon=theme_icon,
on_click=lambda e: toggle_theme()
)
controls.append(theme_btn)
sidebar.content.controls = controls
page.update()
# ----- Группа + подменю -----
def build_group(name: str, tabs: list[str]) -> ft.Container:
"""Создаёт одну группу с подменю."""
# Фон заголовка только для активной группы
header_bg = LIGHT_ACC if selected_group == name else ft.Colors.TRANSPARENT
# 1⃣ Первый ряд: статус‑лампочка, иконка, название группы
title_row = ft.Row(
controls=[
status_lamp("#ffeb3b"),
group_icon(name),
ft.Text(name, weight=ft.FontWeight.BOLD, color=ft.Colors.ON_PRIMARY)
],
alignment=ft.MainAxisAlignment.START,
vertical_alignment=ft.CrossAxisAlignment.CENTER,
spacing=8,
)
# 2⃣ Второй ряд: подстрока (отображается только при развёрнутой панели)
subtitle_row = ft.Row(
controls=[
ft.Text("Подстрока", size=10, color=ft.Colors.GREY)
],
alignment=ft.MainAxisAlignment.START,
vertical_alignment=ft.CrossAxisAlignment.CENTER,
spacing=8,
)
header_content = ft.Column(
controls=[title_row] + ([subtitle_row] if is_expanded else []),
spacing=2,
)
header = ft.Container(
padding=ft.padding.only(left=8, right=8, top=4, bottom=4),
bgcolor=header_bg,
border_radius=8,
content=header_content,
on_click=lambda e: toggle_group(name),
)
# Список вкладок
tab_items = []
for tab_name in tabs:
icon = tab_icon()
title = ft.Text(tab_name, color=ft.Colors.ON_SURFACE_VARIANT)
if selected_tab_name == tab_name:
icon.color = LIGHT_ACC if page.theme_mode == ft.ThemeMode.LIGHT else DARK_ACC
title.color = LIGHT_ACC if page.theme_mode == ft.ThemeMode.LIGHT else DARK_ACC
row = ft.Row(
controls=[icon],
alignment=ft.MainAxisAlignment.START,
vertical_alignment=ft.CrossAxisAlignment.CENTER,
spacing=8
)
if is_expanded:
row.controls.append(title)
item = ft.Container(
content=row,
padding=ft.padding.only(left=16),
on_click=lambda e, t=tab_name, g=name: select_tab(g, t)
)
tab_items.append(item)
sublist = ft.Container(
content=ft.Column(controls=tab_items, spacing=0),
height=0 if not group_expanded[name] else len(tabs) * 48,
)
return ft.Column(
controls=[header, sublist],
spacing=4
)
# ----- События -----
def toggle_sidebar():
nonlocal is_expanded
is_expanded = not is_expanded
sidebar.width = 200 if is_expanded else 80
rebuild_sidebar()
def toggle_group(name: str):
group_expanded[name] = not group_expanded[name]
rebuild_sidebar()
def select_tab(group: str, tab: str):
nonlocal selected_group, selected_tab_name
selected_group = group
selected_tab_name = tab
selected_tab.value = f"{tab}\n(Icon + text)"
rebuild_sidebar()
def toggle_theme():
if page.theme_mode == ft.ThemeMode.LIGHT:
page.theme_mode = ft.ThemeMode.DARK
page.bgcolor = DARK_BG
else:
page.theme_mode = ft.ThemeMode.LIGHT
page.bgcolor = LIGHT_BG
rebuild_sidebar()
page.update()
# ----- Инициализация -----
page.bgcolor = LIGHT_BG
rebuild_sidebar()
# ---------- Запуск ----------
if __name__ == "__main__":
ft.app(target=main)